Deploying an Application on Android
This article gives a technical description of the steps required to take any given Qt application and deploy it to an Android device (or market place).
It is recommended that you use the androiddeployqt deployment tool or Qt Creator to automate this work rather than perform the steps manually. The following information will give you a technical insight into the structure of the resulting Android application which is not normally required just to write an application.
The APK Package
Applications on Android are packaged in a specially structured type of ZIP file called APK
. When you build a Qt application using qmake
and make
, the result will be a binary file which is built with the correct compiler and flags to be usable on an Android device with the target architecture.
In order to turn this into a runnable application, it has to be put into a special directory structure with some other files and packaged into an APK package.
Package Template
A template for the other sources of an APK package is contained in $QTDIR/src/android/java
. The first step of making an APK is to copy these files into an empty directory. In this guide, we'll refer to this build directory as $BUILD_TARGET
.
We also need to make sure the application binary is copied into the package. This can be achieved by using the following command after running qmake on your application's project file:
make install INSTALL_ROOT=$BUILD_TARGET
It will copy the application binary and any other installation requirements into the packaging directory.
The packaging directory will now consist of the following parts:
AndroidManifest.xml
The AndroidManifest.xml
file gives detailed meta-information about your application. This information is used for several things. It is used by the target device to decide which features to enable, the default orientation of the application, and so on. In addition, it's used by the market place for information on the version code, device support, package name, and lots more.
For more information about general capabilities of and requirements for the AndroidManifest.xml
file, please refer to the Android documentation on this topic.
There are some special variables recognized by Qt which can be placed inside the manifest:
android.app.use_local_qt_libs
: If this is set to1
, Qt libraries are expected to be found on the target device. If it is0
, then libraries must be requested from the Ministro service.android.app.bundle_local_qt_libs
: If set to1
, the Qt libraries are expected to be bundled as part of theAPK
. If set to0
, they are expected to be found in the/data/local/tmp/qt
folder on the target device.Note: If
use_local_qt_libs
is 0, then this variable has no effect, since libraries are then requested through Ministro instead.
Other variables in the manifest refer to resources, and more information about these can be found in the documentation for the resources below.
Java Code
Under $BUILD_TARGET/src
are the files comprising the Java code of the Android application. The regular Android application launcher is a Java process, so Qt applications have a Java-based entry point. The code in here will load the required Qt libraries, based on the meta-information given in other files in the template. The code supports all the three deployment mechanisms which are supported in Qt Creator and androiddeployqt
: Bundled, Ministro and Debug.
After loading the libraries, the Java code will call into the application's native main()
function on a new thread and the application will launch. At this point, the Java code in the template is used to delegate events from Android into Qt.
One thing to note about the files in this directory is that they can contain code specific to certain Android versions. Based on the minimum required Android API level of your application it might be necessary to remove some of this code. This is done automatically by androiddeployqt
and Qt Creator during packaging.
For example, lets say the code contains the following:
//@ANDROID-21 @Override public void onActivityReenter(int resultCode, Intent data) { // Do something return super.onActivityReenter(resultCode, data); } //@ANDROID-21
If your minimum Android API level is 20 or lower, then the code should be removed before building, since it's not a supported API on Android API level 20. However, if your minimum API level is 21 or higher, it should be left in.
Resources
Under the res/
folder in the $BUILD_TARGET
are Android resources that can be accessed from the AndroidManifest.xml
and Java code of your application. A typical example of resources which should be placed here are the icon files used by the application launcher to represent your application.
In Qt, some translations used for the Ministro service and some files with meta-information are in the default resources of the application.
res/values/libs.xml
One of the files containing meta information about the deployment of the application is libs.xml
. It consists of the following values:
qt_sources
: The URL of one or more Ministro repositories that contain the necessary Qt libraries. This is used when the Ministro deployment mechanism is active. Read the Ministro documentation for more information about such repositories.repository
: The Ministro repository to use at the given URL. This is used when the Ministro deployment mechanism is active.bundled_libs
: Libraries in the APK's library folder which should be loaded on start-up. Library names should be specified without thelib
prefix and.so
suffix.qt_libs
: Qt libraries which should be loaded on start-up. When bundled deployment is used, these are expected to be found inside theAPK
's library folder. When Ministro deployment is in use, they are requested from the Ministro service on the device. And when debugging deployment is in use, they are loaded from the/data/local/tmp/qt
directory on the target device.bundled_in_lib
: List of plugins which are bundled in theAPK
's library folder. This is only used when the bundling deployment mechanism is active. Qt's plugin system requires plugins to be placed in a special directory structure which contains information about the plugin category. The library folder in the APK does not support such a directory structure, so the bundled_in_lib array contains the information lost when the directory structure is flattened. Each item is a pair of paths, separated by a colon. The first of the pair is the file name of the file bundled inside theAPK
's library folder. The second of the pair is the original path of the file, relative to the Qt installation.bundled_in_assets
: List of other types of Qt files which are bundled inside theAPK
's asset folder. This value is only used when the bundling deployment mechanism is active. The format of the items is the same as for thebundled_in_lib array
. The difference is that the first of the pairs refers to the path of a file inside theassets
directory of the application instead of the library directory. This array is typically used for bundling QML imports, which also require a special directory structure to be used inside Qt.
res/values/strings.xml
The strings.xml
file contains some strings used by the AndroidManifest.xml
and by the deployment mechanisms, as well as some strings used when loading the Ministro service.
In particular, the application name and the name of the application binary can be specified here. There are also strings that contain additional libraries that should be loaded and JAR
files which should be included in the class path. The latter is only used for deployment with Ministro or debug deployment.
Libraries
Under libs
in the package directory, it's possible to place libraries that should be included in the application bundle. JAR
libraries should be placed directly under libs/
, while shared libraries should be put in a subdirectory suitably named after the target architecture of the libraries.
For deployment that bundles Qt in the APK
, the Qt JAR
files that are suffixed with "bundled"
should be put into the libs directory. It is also required that the necessary shared libraries and plugins are placed in the appropriate subdirectory of libs.
Building the Android Application Package
Once all the pieces are in place, a few steps are required to build the application package. First, a build script needs to be generated. This is done using the android
tool which is part of the Google Android SDK.
Example:
% android update project --path $BUILD_TARGET --target android-16 --name QtApp
This example will create build files in $BUILD_TARGET
for an APK
named QtApp
. The Java code will be compiled against the android-16
platform.
The project can then be built using the ant tool. If a release package is built it can be signed and aligned using jarsigner
and zipalign
.
androiddeployqt
Building an application package is complex, so Qt comes with a tool which handles the work for you. The steps described in this document so far are handled automatically by the tool.
Required Steps Before Running androiddeployqt
Before running the tool, you need run qmake
and make
your project. Running qmake
creates the Makefile
, and it will also generate a JSON
file containing important settings used by androiddeployqt
.
You should then install the application binary (and any other requirements) into the library folder of the APK
. If $BUILD_TARGET
is your build directory (the first time you do this, the directory should be empty at this point), then you can install the binary with the following command:
% make install INSTALL_ROOT=$BUILD_TARGET
Command Line Arguments
The only required command line argument when running the tool is --output
. This should be set to $BUILD_TARGET
, that is: the build directory where you installed your application binary.
Other command line arguments are optional but useful. Here's a quick overview. More information is available by passing the --help
argument to androiddeployqt.
--input <file name>
: This allows you to specify theJSON
file generated byqmake
. By default,androiddeployqt
will try to guess the file name based on the current working directory.--deployment <mechanism>
: Specify this to pick a different deployment mechanism than the default.--install
: Specify this to install the finished package on the target device or emulator. Note that if a previous version of the package is already installed, it will be uninstalled first, removing any data it might have stored locally.--device <ID>
: Specify the ID of the target device or emulator as reported by theadb
tool. If an ID is specified, it will be passed to all calls toadb
. If it is unspecified, no particular device or emulator will be requested byadb
, causing it to pick a default instead.--android-platform <platform>
: The SDK platform used for building the Java code of the application. By default, the latest available platform is used.--ant <path>
: Specify the path to theant
executable. If this is unspecified,androiddeployqt
will attempt to detect it on thePATH
.--release
: Specify this to create a release package instead of a debug package. With no other arguments, release packages are unsigned and cannot be installed to any device before they have been signed by a private key.--sign <url> <alias>
: Sign the resulting package. Specifying this also implies--release
. The URL of the keystore file and the alias of the key have to be specified. In addition, there are a number of options that can be specified which are passed through to thejarsigner
tool. Pass--help
toandroiddeployqt
for more information about these.--jdk <path>
: Specify the path to the Java Development Kit. This is only required for signing packages, as it is only used for finding thejarsigner
tool. If it is unspecified, thenandroiddeployqt
will attempt to detectjarsigner
, either using theJAVA_HOME
environment variable, or on thePATH
.--verbose
: Specify this to output more information about whatandroiddeployqt
is doing.
Dependencies Detection
Qt comes with a number of plugins which are loaded at run-time when they are needed. These can handle anything from connecting to SQL databases to loading specific image formats. Detecting plugin dependencies is impossible as the plugins are loaded at run-time, but androiddeployqt tries to guess such dependencies based on the Qt dependencies of your application. If the plugin has any Qt dependencies which are not also dependencies of your application, it will not be included by default. For instance, in order to ensure that the SVG image format plugin is included, you will need to add QT += svg
to your .pro
file so that the Qt SVG module becomes a dependency of your application.
If you are wondering why a particular plugin is not included automatically, you can run androiddeployqt with the --verbose
option to get the list of missing dependencies for each excluded plugin. You can achieve the same in Qt Creator by ticking the Verbose output check box in the Deployment configurations. This is located in the Run tab of your Projects settings.
It's also possible to manually specify the dependencies of your application. See the documentation for the ANDROID_DEPLOYMENT_DEPENDENCIES
qmake variable below.
Android-specific qmake Variables
Unless the project has special requirements such as third party libraries, it should be possible to run androiddeployqt
on it with no modifications and get a working Qt for Android application as a result.
However, there are a set of qmake
variables that can be used to tailor your package. At some point during development, you will most likely want to look into these variables, as they will e.g. allow you to set the name of your application as it appears in the application menu on devices.
Here is a list of some variables that are particularly interesting when making Android applications:
ANDROID_DEPLOYMENT_DEPENDENCIES
: By default,androiddeployqt
will detect the dependencies of your application. But since run-time usage of plugins cannot be detected, there could be false positives, as your application will depend on any plugins that are potential dependencies. If you want to minimize the size of yourAPK
, it's possible to override the automatic detection using theANDROID_DEPLOYMENT_DEPENDENCIES
variable. This should contain a list of all Qt files which need to be included, with paths relative to the Qt install root. Note that only the Qt files specified here will be included. Failing to include the correct files can result in crashes. It's also important to make sure the files are listed in the correct loading order. This variable provides a way to override the automatic detection entirely, so if a library is listed before its dependencies, it will fail to load on some devices.ANDROID_PACKAGE_SOURCE_DIR
: This variable can be used to specify a directory where additions and modifications can be made to the default Android package template. Theandroiddeployqt
tool will copy the application template from Qt into the build directory, and then it will copy the contents of theANDROID_PACKAGE_SOURCE_DIR
on top of this, overwriting any existing files. The update step where parts of the source files are modified automatically to reflect your other settings is then run on the resulting merged package. If you, for instance, want to make a customAndroidManifest.xml
for your application, then place this directly into the folder specified in this variable. You can also add custom Java files inANDROID_PACKAGE_SOURCE_DIR/src
.Note: When adding custom versions of the build files (like strings.xml, libs.xml, AndroidManifest.xml, etc.) to your project, make sure you copy them from the package template, which is located in
$QT/src/android/java
. You should never copy any files from the build directory, as these files have been altered to match the current build settings.ANDROID_EXTRA_LIBS
: A list of external libraries that will be copied into your application's library folder and loaded on start-up. This can be used, for instance, to enable OpenSSL in your application. Simply set the paths to the requiredlibssl.so
andlibcrypto.so
libraries here and OpenSSL should be enabled automatically.ANDROID_EXTRA_PLUGINS
: This variable can be used to specify different resources that your project has to bundle but cannot be delivered through the assets system, such as qml plugins. When using this variable,androiddeployqt
will make sure everything is packaged and deployed properly.
Deployment in Qt Creator
Qt Creator will run the androiddeployqt
tool for you, and provides easy and intuitive user interfaces to specify many of the options. For more information, see the Qt Creator documentation.
© 2021 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.