Porting KDE Android apps to Qt6/KF6
With the first Qt 6 based release of KDE software rapidly approaching, there’s still one thing that has been lagging behind in porting so far, working Android APK packages. After recent changes on our build and deployment infrastructure, on Qt and on KDE Frameworks we are getting closer to that though.
Code changes
One of the larger areas of source incompatible change in Qt 6 was the removal of the QtAndroidExtras module, affecting for example:
- Interfacing with JNI code via
QAndroidJniObject
(nowQJniObject
in Qt6::Core). - Access to the context or activity handle via
QtAndroid
(nowQAndroidApplication
in Qt6::Core). - Permission checks and requests via
QtAndroid
(if you are lucky now with the newQPermission
API in Qt6::Core, otherwise with private API inQtCore/private/qandroidextras_p.h
).
A lot of this has been taken care of already though, as we have Qt 6 Android coverage on the KDE CI since quite some time, and all of this is doable while still keeping compatibility with Qt 5.
For most of the following this is unfortunately not the case though, so those changes can only be applied
when Qt 6 is required. The Java code is such a case, if you inherit from org.qtproject.qt5.android.bindings.QtActivity
for example,
the qt5
part of the fully qualified class name is now just qt
.
Build system and packaging changes
If your app doesn’t have a custom Java Activity class you’ll find the above fully qualified class name in the Android Manifest XML file, it needs to be changed there in the same way.
<application android:name="org.qtproject.qt.android.bindings.QtApplication" android:label="My App" android:icon="@mipmap/ic_launcher">
<activity android:name="org.qtproject.qt.android.bindings.QtActivity" android:label="My App" ... android:exported="true">
In case you have a custom build.gradle
file instead of implicitly using the one from the Qt template
that will also need a few adjustments. Anything mentioning qt5
is an obvious candidate but there’s
likely more. The easiest way here is probably to rebase your customizations on top of the one provided by
Qt in $PREFIX/src/android/templates/build.gradle
.
And finally the CMake part of the buildsystem will need changes as well. In KF5 ECM did create APKs magically, but the way this was injected into the CMake toolchain file is clashing with Qt 6 also having its own CMake toolchain file now. So we need explicit CMake API for creating APKs now:
include(ECMAddAndroidApk)
ecm_add_android_apk(myapp ANDROID_DIR ${CMAKE_CURRENT_SOURCE_DIR}/android)
Craft changes
Building the APK with Craft is then mostly a matter of configuration meanwhile. As most dependencies don’t have a Qt 6 based release yet, you will likely need to switch all of those to use the latest Git version.
[BlueprintSettings]
libs/qt.qtMajorVersion=6
kde/frameworks.version=master
In a few cases you might also encounter Craft blueprints that still unconditionally pull in Qt 5 and thus likely break the build. Dependencies on Qt modules that no longer exist in Qt 6 are a possible reason for example. A corresponding condition on the Qt version tends to fix that.
if CraftPackageObject.get("libs/qt").instance.subinfo.options.dynamic.qtMajorVersion == "5":
self.runtimeDependencies["libs/qt5/qtquickcontrols2"] = None
CI/CD changes
With the Jenkins-based binary factory being up for retirement Qt 6 based APKs can only be built on the Gitlab CI on KDE Invent. So this has to be set up and configured differently than with Qt 5 as well.
Defining APK builds jobs now happens in the .gitlab-ci.yml
file in the corresponding repository,
by including the respective templates in the same way other CI jobs are defined. In many cases this however
will also imply switching to the new style of including templates that
Ingo described here.
include:
- project: sysadmin/ci-utilities
file:
- /gitlab-templates/craft-android-apks.yml
The location for customized Craft settings also changed, those now go into a .craft.ini
file
at the top-level of the application repository. For now you’ll typically need at least the above
mentioned version settings there.
Examples
There’s a few apps having those changes applied meanwhile which might serve as examples:
Remaining issues
While for Kongress the above will result in a properly signed and working Qt 6 based APK, that’s unfortunately not the case for all apps yet. One of the larger known issues is that the Breeze Qt Quick Controls style doesn’t load on Android, so apps including that will still fail to start.