Skip to content

Porting KDE Android apps to Qt6/KF6

Saturday, 11 November 2023 | Volker Krause

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 (now QJniObject in Qt6::Core).
  • Access to the context or activity handle via QtAndroid (now QAndroidApplicationin Qt6::Core).
  • Permission checks and requests via QtAndroid (if you are lucky now with the new QPermission API in Qt6::Core, otherwise with private API in QtCore/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 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="" android:label="My App" android:icon="@mipmap/ic_launcher">
    <activity android:name="" 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:

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.


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.

  - project: sysadmin/ci-utilities
      - /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.


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.