Qt on Android Episode 4 - How to prepare your Qt application for publishing on Android markets
erratum 2014-04-13: Updated Bundle Qt libs pros and cons.
Update2: Here you can read also the Chinese version, thanks goes to Foruok.
After we’ve learned how to set up the development environment and how to use Qt on Android, it’s time to move forward and in this article we are going to learn about different deployment systems and how to sign the package in order to publish it in any Android markets.
Choosing the right deploying system
Qt Creator supports three deployment systems:
- Use Ministro service to install Qt
- Bundle Qt libs in APK
- Deploy local Qt libs to temporary directory
Use Ministro service to install Qt
Back in 2009, when I started this project, there were only a few devices out there with Android. Most of them had very limited free space (less than 100 Mb), so, using Qt statically or bundling Qt libs into the APK was out of the question, also back then Google Market had way more limited size than today (50Mb limit/apk). As you can see I was forced to invent Ministro. Even today most of the mid/low-end devices don’t have too much space!
How it works?
- Instead of bundling everything into your APK, your package will contain ONLY your application .so file(s), its needed resources and a list with all needed external libs.
- When your application starts, it tries to connect to Ministro service, if it fails it means that Ministro is not installed and it opens the Android Play for the user to install Ministro. After it successfully connects to Ministro, it sends the dependencies list.
- Ministro checks if these dependencies are already available, if not, then it downloads only the missing ones in a central secure location and it sends back to the application another list with all the needed libs that the application must load before it loads your qt application.
- The application loads the libs from Ministro’s location, then your application, then it continues the running process.
Now let’s see the advantages and disadvantages of using Ministro.
Advantages:
- Using Ministro, the user needs to download the Qt libs ONLY once. If the user downloads another Qt application, it will use the existing libraries. Of course if that application needs more libs, Ministro will download only those that are missing.
- Ministro can detect if the device armv5 CPU has VFP or if the device armv7 CPU has NEON and it can download libs specific to that device CPU. Even if your application is not built with these CPU features, just using Qt libs built with them will make it run faster (on armv5, VFP really makes the difference, it will be way much faster). Currently these libs are not available, but I intend to publish them starting with 5.4.
- Ministro can upgrade Qt libs, without you needing to release a new application.
- You can target all Android platforms with a single APK. Because most likely your application (.so) file(s) are not very big, they can easily fit into a single APK. If your application doesn’t do intensive computation you can use only armv5 .so files to target both armv5 and armv7 platforms, because even if your APK contains only armv5 libs, Ministro will download the Qt libs specific for your device.
- You can use your own Ministro sources with your own libraries. Basically you’ll need an HTTP/HTTPS server with a valid certificate and to create and upload Ministro’s repository to that server. Because there is a lot to tell on this topic, I’m going to create a wiki page with all the information you need about this topic.
Disadvantages:
- Some people don’t like Ministro because the users must install Ministro service once. There are lots of apps out there which require other services, if my mother can install and use Google Hangouts on an older Android version, which needs Google Play service to be installed manually, or MX Player that needs MX Player Codecs to be installed manually, I’m pretty sure she will be just fine with any Qt application which requires Ministro to be installed once.
- Ministro upgrades Qt libraries and it might break things. I’m very concerned on this topic! To address this problem Ministro uses a different location for every major Qt release e.g:
- https://download.qt-project.org/ministro/android/qt5/qt-5.1
- https://download.qt-project.org/ministro/android/qt5/qt-5.2
- https://download.qt-project.org/ministro/android/qt5/qt-5.3
Even more, every source is using a Debian-like release scheme with three different repositories:
- unstable – this is a pre-release repository used by Qt Project/Necessitas developers to test a new release. Before a new SDK release is announced, this repository is used to push the new libs and test it before officially announcing it.
- testing – after all tests pass, the libs are moved from unstable to testing repository and then we announce them on https://groups.google.com/forum/#!forum/android-qt, http://lists.qt-project.org/pipermail/android-development and on http://mail.kde.org/pipermail/necessitas-devel. The new version will stay in testing repository for at least one month to give enough time for the developers to test their existing apps using the new libs. Additional updates will be released in testing repository and the period may be extended if any regressions are reported. A new update must stay at least two weeks in testing repository.
- stable – after testing repository is regression free, the libs are moved to stable repository. It is very important that testing repository is regressions free before it lands on stable because in ~7 days all Android Ministro users will be notified about the new release and it will be very unpleasant if the users apps do not run any more!
Using this scheme Ministro users have no regression in 4 years and 13 Necessitas releases and 5 Qt project releases!
As you can see Ministro is quite safe on this matter!
Bundle Qt libs in APK
This feature was added recently to Qt Creator. Beside your application and your resources, Qt Creator adds all Qt libraries that your application needs to run.
Advantages:
- The APK contains everything it needs to run.
- erratum 2014-04-13: The ability of including custom builds of Qt. Improves time-to-market as you don’t have to wait for official releases before you can get your crucial bug fix. There’s also no waiting period after a new version of Qt is released before you can deploy it with your application.
- erratum 2014-04-13: The Qt libraries are not updated behind your back, no worries about sudden regressions.
- erratum 2014-04-13: The libraries will be served with your package in the store’s main infrastructure, whereas the Ministro libraries are served in the Qt Project infrastructure. The latter has not been tested for very large download volumes, so at this point we do not know how well it can serve a hugely successful application.
- erratum 2014-04-13: If done through Google Play, the download goes through the regular mechanisms on the device, so it continues in the background when your user suspends it, with progress indication in the status bar, and it obeys your users’ settings regarding downloads and updates over a mobile data connection.
Disadvantages:
The APK is HUGE due to Qt libs which are pretty big (+40Mb/platform).erratum 2014-04-13: The APK is big comparing with the Ministro’s version, due to Qt files which are pretty big. Qt files can go slightly over 40Mb/platform if you are going to use all of Qt modules. Of course your application doesnt need all the modules, so, if your application uses only Qt Quick Controls + Qt SVG + Qt Multimedia + Qt Sensors + Qt XML modules, Qt files (libs + plugins + additional files) are ~20Mb/platform and your APK will be ~10Mb.- All Qt libs must be unpacked!
So your application will need a lot of free space to run (+50Mb)erratum 2014-04-13: The APK is NOT deleted after you install the application, but is kept by Android O.S. in order to access its assets, so, don’t forget to to count its size as well. At first run, our application will extract Qt libs and plugin to the application home folder. To check exactly how much space your application uses, you have to go to Settings->Apps->your application, and check Total of the STORAGE section. I checked gallery Qt Quick Controls example with Qt SVG + Qt Multimedia + Qt Sensors + Qt XML and it occupies slightly over 35Mb. Currently only just averyfew apps on Google Play require that much space to run. - Most of the mid/low-end device users can’t afford to spend that much free space!
- Due to big size you can’t target more than one platform/apk. You must create an APK for every platform (armv5, armv7, x86).
This will be confusing for armv7 users because AFAIK Google Play will list your application twice, once for armv7 and once for armv5 (see MX Player Codecs). If my mother can install a simple application, I’m pretty sure that she doesn’t know what kind of CPU her phone has, actually I’m pretty sure that she doesn’t know what a CPU is or if her device has such a thing …erratum 2014-04-13: it seems that Google Play doesn’t list your application twice. - Can’t use VFP on armv5 devices and NEON on armv7 devices.
- Qt libs can’t be shared by multiple Qt apps on the same device.
- Can’t get Qt libs updates automatically.
As you can see there is no perfect solution, the pros from Ministro go to cons of the Bundle Qt libs in APK and the cons go to pros :).
Deploy local Qt libs to temporary directory
This deploy system is used mostly by Qt hackers when hacking on Qt itself because it is the fastest way to deploy modified Qt libs on the device to test them. Do not use it in production!
In the end you are the one who will make the choice, I just wanted to present you all the advantages and disadvantages of every deployment system.
Package Signing
This is the last and most important step before publishing. In order to sign the package you’ll need a keystore and a self-signed certificate.
If you don’t have such a certificate, Qt Creator can help you to easily create one, you just need to press create button and fill the keystore and certificate fields, check the following image:
You can only upgrade your application with the same certificate you publish it with! So, make sure you are making backups of the keystore file.
If you already have a keystore, then just browse its location.
Next step is to switch your project to release and check sign package and open package location after build, check the following image:
After you’ve pressed run button, in a few moments Qt Creator will open the location where your package was built and signed, be sure you are choosing the signed one (QtApp-release.apk)! Check the following image:
That’s all folks, see you next time when will see how to use JNI to extend our Android applications.
Nice article.Could you show us show us how to put ads in the apps developed by Qt on android too?Like tapjoy and admob.
Yes, but that will come in the next episodes.
there is now support form multiple apk
http://developer.android.com/google/play/publishing/multiple-apks.html
Did I said something else?
Nice article. It’s a pity you didn’t talk about the fourth deployment system: static linking.
AFAIK static linking is not possible (yet).
hello, If we want to develop Apps for Android use Qt, which way is recommended, Qt Quick or QWidget based?
Depends: if you don’t need kinetic scrolling and fancy animation, then QWidget should be ok, otherwise Qt Quick Controls are a better choice.
Hello, the Chinese version is here:
http://blog.csdn.net/foruok/article/details/23355097
Hi, which version of QTCreator do you have?
I have 3.1 beta but i dont see QT deploment options, i succefully made app with libraries included but i dont see how to choose ministro. 🙁
I used Qt Creator 3.1, the *deployment options* must be there, please check carefully the first image in this article.
Hi, Bogdan. First of all, thank you for this great and informative blog series about Qt for Android!
I just have to correct a couple of key things here because I think the option to bundle Qt libraries is getting an undeservedly bad reputation in this entry 🙂
1. The size of an APK which bundles everything you need to run your Qt application is nowhere near 40 MB. It is about 7.5 MB for a QtWidget app and about 8.7 MB for a Qt Quick Controls app. It’s a little bit larger than most Java applications in the store, but in my opinion the compromise is worth it.
2. Supporting multiple architectures: The MX Player Kodek you link is apparently not using Google Play’s “multiple APK” feature. Instead, they have registered multiple applications with one APK each and different names, giving the confusing number of listings as you mention. But Google Play allows you to upload more than one APK for a single application, and will show the most appropriate one to users. (From the documentation: All users see only one version of your application on Google Play).
I recommend that people use multiple APKs even for applications that are Ministro-based, because otherwise the binary code of their own applications will have to be duplicated in the APK, increasing the download size for their users for no good reason.
Also, since I personally prefer the bundling option, I’ll add a few more pros of bundling libraries which are not in your list:
– Flexibility: The ability of including custom builds of Qt. Improves time-to-market as you don’t have to wait for official releases before you can get your crucial bug fix. There’s also no waiting period after a new version of Qt is released before you can deploy it with your application.
– Predictability: The Qt libraries are not updated behind your back and the binaries are signed by your private key. No risk of malicious code or sudden regressions.
– The libraries will be served with your package in the store’s main infrastructure, whereas the Ministro libraries are served in the Qt Project infrastructure. The latter has not been tested for very large download volumes, so at this point we do not know how well it can serve a hugely successful application.
– If done through Google Play, the download goes through the regular mechanisms on the device, so it continues in the background when your user suspends it, with progress indication in the status bar, and it obeys your users’ settings regarding downloads and updates over a mobile data connection.
Hi Eskil,
1. There is a misunderstanding, 40Mb is the size of *Qt libs* not of the APK, I’ll make it more clear! I also reviewed the numbers (I have them for a looong time) and it seems they are much better now.
2. AH, I was mislead my MX Codecs, I’ll update the article.
Thanks for the pros of of bundling libraries, I’ll add them to the list. I have a problem with “predictability” item in your list, because as it is it sounds like the LGPL libs from the open-source Qt SDK may contain “malicious code” … 🙂 Which is not true at all! So I’ll add it but slightly changed.
Im sorry, got it. I didnt know that debug and run makes difference 😀
Best way to make Qt applications share the same Qt libs is to have the Android vendor ship them in /system/lib/.
What about android service/binder ??
Currently there is no an easy way to use Android’s services/binder in Qt. It is on my TODO list, but I didn’t had time to code it.
Having previously built bridges between select C++ and Java Binder interfaces in Android, I’m now writing a simple prototype that would allow one to use QVariants to interface directly with Android Java binder interfaces. If you BogDan or anyone else is interested, feel free to contact me at
In the future, I’d like to add proper support for Android Services to Qt, and most probably I’ll need such a thing, I’ll ping you when I’ll start it ;-).
This image “Android_Qt_Creator_deployment.png” is deprecated. In newest Qt creator its looks different. Could You take a fresh one ?
Yep, a few things changed, I’ll update the post soon.
Hi, I’m doing is everything stated here, but only generates me QtApp-release-signed.apk not generate QtApp-release.apk.
I will be doing wrong,
I’m using Qt 5.4, 22 api sdk, android-NDK NDK-r10e
QtApp-release-signed.apk is what you need, things changed over the years :), I’ll update the post soon.
thanks, BogDan Vatra
Hello BogDan, I’d like to use sqlite in my application. But QSqlDatabase ::addDatabase(“QSQLITE”); fails.
I think Qsqlite library not linked in default build environment.
Can you tell me how to use it ?
Thanks in advance.
Hmm it is strange, it should work ../ contains sqlite plugin.
I need more info about it.
0 – what Qt version are you using?
1 – what is your deployment method ? (Bundle Qt libs, or Ministro?)
2 – if you choose “Bundle Qt libs” than please check if the qt_build_folder/android-build/libs/
Hello BodDan,
It is working fine now, It was my mistake.
It’s great my QT app is working on Android.
Dear BogDan,
Congrats for the amazing work done and thanks a ton for the cool tutorial. I Just followed the instructions..and things work like a charm, when I tried the sample scribble app on an android tablet.
But one small thing came as a nasty surprise.. My tablet has an EMR sensor, so that I can use a stylus on it. Scribbling works with finger; but doesn’t work with stylus. Stylus only recognizes mouseDown and mouseUp.. mouseMove is not recognized. I logged all events; nothing is fired at Qt end when stylus moves.
Is it that something is missing in the bridge ? If that’s the case, any update is expected in near future ?
If I can fix this on my own, please give me some clue. Please add few extra steps; I am pretty new to this.
Thanks in advance,
Aby.
Hi BogDan,
An update:
For time being, I managed to bypass the issue by overriding dispatchTouchEvent. I added a slot in scribblearea, which gets a signal from java class on dispatchTouchEvent, for TOOL_TYPE_STYLUS.
As of now I an struggling with getting the right coordinates. Touch returns relative coordinates (thru mouse events); but getX/getY from java returns absolute coordinates. I can just add the ‘hard-coded’ offset value and fix it; but trying to get the ‘right’ solution.
Regards,
Aby.