KDE Android apps porting update
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).
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.platformmodule 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).
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.
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.
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:
- Kongress
- Keysmith
- KTrip
- Kasts
- KWeather
- Tokodon - opening threads still fails in some cases, but unlike in the last Qt 5 builds the login flow works.
- Kontrast
- Tasks
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:
- Calindori - QML not ported yet
- Elisa - working Qt 6 port, but APK not ported yet
- KAlgebra Mobile - partially working Qt 6 port, APK not ported yet
- Kirigami Gallery - Qt 6 port still in a branch, APK not ported yet
- Klimbgrades - QML not ported yet
- KRecorder - no Qt 6 port yet
- KTuberling - APK not ported yet
- Okular - Qt 6 port ongoing
- Plasma Camera - QML not ported yet
- Plasma Phonebook - working Qt 6 port, APK ported but missing CI job
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=1andQT_QUICK_CONTROLS_STLYEset toorg.kde.breezeorMaterialrespectively. - 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.