Following the recent posts on porting KDE Android applications to KF6, CI/CD changes for APKs and changes to packaging of KDE Android apps here’s an update on where we are meanwhile with switching KDE’s Android apps to KF6.

Infrastructure improvements

Style plugin packaging fixes

There have been two crucial fixes which finally give us generally starting and visually correct apps:

  • Fixed loading of the Kirigami QML plugin (MR 1394).
  • Fixed bundling of the Breeze Qt Quick Controls style with androiddeployqt (MR 1395 and MR 84).
KTrip's about page running inside the Android emulator with the Breeze style and in German.
KTrip with Breeze style and working translations.

APK optimizations

The Qt 6 based APKs tend to be noticeably larger than what we used to have with Qt 5. There’s multiple reasons for that:

  • Depending on Qt5Compat graphical effects costs about 4 MB storage / 1.5 MB download size due to its runtime dependency on the shader compilation pipeline. A handful of remaining uses have been removed from Kirigami meanwhile, with MR 1407 being the last one.
  • Remaining uses of the Qt.labs.platform module pull in QtWidgets as a dependency. For Qt 5 we used to have a patch to avoid that, for Qt 6 we need to find every single use and port away from that. That’s another 6.5 MB storage / 2.5 MB download size.
  • We used to have a much more minimal Craft default configuration for Qt 5. This has changed as more apps ended up needing a more diverse set of dependencies (such as the full ffmpeg stack for Tokodon, or support for signed PDFs in Okular), as well as Craft itself having become a more widely used part of our infrastructure on all platforms. Work on enabling application-specific minimized builds of particular heavy dependencies is ongoing (e.g. MR 740 or MR 743).

The above mentioned numbers might seem small on their own, but that’s to be seen against typically 20-30Mb APKs and are for things that are largely unused, ie. this is an easy 10-20% gain which doesn’t just affect every user but also our build and distribution infrastructure.

Permission checks

On Android applications need to explicitly request permissions for accessing certain components or information, such as the camera or the current location. That’s neither new nor related to the transition to Qt 6, but re-testing on a fresh installation on the latest Android version has exposed a few places where we missed these runtime permission requests.

Qt 6 has new API for doing this, but with Qt 6.5 that is still somewhat cumbersome to use as it’s only available on platforms with a permission system. While you can ifdef that in C++ it’s very inconvenient in QML, either way not good for easy and maintainable code (see e.g. the use in KWeatherCore).

With Qt 6.6 this significantly improved as the permission API is now available unconditionally on all platforms and just always reports “permission already granted” on platforms without a permission system, resulting in much simpler code (see e.g. the use in Qrca).

Android system dialog for granting access to the camera triggered by Qrca.
Qrca requesting camera permissions.

Video processing

An issue that turned out to be particularly challenging has been a crash in KF’s barcode scanner when used after an application had been suspended at any point in time previously. Suspending applications happens on Android when an app is no longer in the foreground, so this is a very common scenario, and we have at least 4 apps with integrated barcode scanning.

Meanwhile we have at least identified the underlying cause in Qt Multimedia code, where some RHI state invalidated by suspension isn’t properly restored/reset after resuming. A crude patch for addressing that is meanwhile in review, whether that turns out to be the right way to fix this remains to be seen.

Dark mode support

Something we have been missing so far and that became easier to implement with Qt 6 is automatic support for the dark UI mode. While we have the style for this, we lacked the detection and automatic switching logic on Android so far, which has changed now:

There’s still one missing piece before we can enable this unconditionally though, we lack support for icon re-coloring on Android, or alternatively for bundling Breeze Dark icons.

About page of Alligator using a dark color scheme. Icons are hardly visible due to not being properly colored yet.
Alligator with Breeze Dark color scheme but hardly visible icons.

Emoji glyph rendering

A rather severe issue for apps like NeoChat or Tokodon was the lack of emoji glyph rendering in Qt 6 apps. This was a result of using fewer bundled dependencies of Qt but building those libraries ourselves instead, and thus ending up with a Freetype build that lacked support for PNG glyphs.

Once identified this was a matter of changing a few settings in Craft, and a minor patch to libpng’s pkgconfig file.

List of public transport providers grouped by country showing the corresponding flag in KTrip.
KTrip backend selection page with emoji flags.

Application status

Working

For some applications we meanwhile have a continuous F-Droid publishing in the nightly repository enabled again, using “works at least as well as the previous Qt 5 nightly build” as decision criteria:

In progress

There’s a few apps that have generally working Qt 6 APKs in general but are blocked on specific issues:

  • Alligator fails to add and fetch feeds.
  • Qrca and Vakzination are both blocked on the above mentioned video processing issue.
  • NeoChat still shows visual glitches in avatar textures and is also affected by the barcode scanner crash.

No Qt 6 APK builds yet

The third group are apps in various stages of porting to Qt 6 and with no port of their APK builds yet:

Itinerary

Personally my goal here is of course to get Itinerary working with Qt 6 in time for the 24.02 release, without disrupting users of the nightly build F-Droid repository. That’s why my focus has been on apps containing or using building blocks relevant for Itinerary (such as all of the above mentioned infrastructure issues).

With all of that in place the actual port of Itinerary is then hopefully not such a big deal anymore, in particular with the nasty barcode scanning crash fixed.

How you can help

You can help with porting and polishing the apps still needing work! Here’s the checklist I tend to follow for that:

  • The application is fully ported to Qt 6 and works on Linux with QT_QUICK_CONTROLS_MOBILE=1 and QT_QUICK_CONTROLS_STLYE set to org.kde.breeze or Material respectively.
  • There is a passing Android CI job.
  • The APK packaging has been ported as described here.
  • There is a CI job building the APK, as described here.
  • The APK does actually start on a phone or inside the emulator. With all the above mentioned work this is rarely a problem anymore, but can still happen due to a missing dependency for example.
  • There is an application-specific Craft exclusion list as described here.
  • Check if all icons show up as they do on desktop. Bundling icons is a rather error prone aspect of APK packaging.
  • If the app uses anything requiring special permissions (camera, location, notifications, etc) check whether those are properly requested. This benefits from testing on a very recent Android version.
  • Check if continuous publishing to the nightly F-Droid repository is enabled here.

If you want to help and/or have questions, feel free to join us in the KDE Android Matrix channel.