Opzet voor Android
Inleiding
Qt biedt uitstekende ondersteuning voor Android, maar toepassingen vereisen een aanzienlijke hoeveelheid aanpassingen om naar behoren op Android te kunnen werken.
Er zijn een paar zaken nodig:
- Een ontwerpblauwdruk
- Instelling qqc2-breeze-style
- Pictogrammen gebundeld met de toepassing
- An Android manifest
- Optioneel een Gradle bouwbestand
- Optionally a splash screen XML file
- CMake function to package for Android
Het Craft-blueprint is nodig om alle afhankelijkheden samen met de toepassing te bundelen, teneinde een Android APK-pakket te genereren.
The qqc2-breeze-style is an alternative to qqc2-desktop-style that is especially geared for mobile platforms like Android and Plasma Mobile.
The application's Craft blueprint needs conditional code to not mix desktop and mobile styling, while the C++ code will need special care not to use the wrong configuration for desktop and mobile. The CMake code might optionally also need conditional code, although it can be avoided.
Het bundelen van de pictogrammen die nodig zijn voor de werking van de toepassing gebeurt met behulp van KDE's 'extra-cmake-modules', hulpmiddelen van Qt voor het bundelen van hulpbronnen en CMake-functies uit Kirigami en Kirigami Addons.
The Android manifest declares the metadata and additional files that need to be bundled with the Android application.
The Gradle build file is needed in case you use extra-cmake-modules integration to apply existing metadata from your application into the Android build, such as the application version, or in case you want special build options.
The Splash screen XML file is needed in case you want to add a splash screen with custom icon, background and positioning.
Ontwerpblauwdruk
De qqc2-breeze-style instellen
To start using qqc2-breeze-style, you will need to add it to Craft. Because it is only used for Android, it will require a conditional clause, especially if the application is already set up to build on Windows and/or Linux using qqc2-desktop style. This requires importing the CraftCore module:
from CraftCore import CraftCore
# ...
def setDependencies(self):
# ...
if not CraftCore.compiler.isAndroid:
self.runtimeDependencies["kde/frameworks/tier1/breeze-icons"] = None
self.runtimeDependencies["kde/frameworks/tier3/qqc2-desktop-style"] = None
else:
self.runtimeDependencies["kde/plasma/qqc2-breeze-style"] = NoneA similar "if not Android, use qqc2-desktop-style, else use qqc2-breeze-style" logic needs to be applied to CMake as well, in case either method of finding qqc2-desktop-style is used:
if (NOT ANDROID)
find_package(KF6QQC2DesktopStyle REQUIRED)
ecm_find_qmlmodule(org.kde.desktop REQUIRED)
endif()Conditional code is also required in C++.
On Android, KDE applications do not use QApplication, but rather QGuiApplication. In addition to setting qqc2-breeze-style only for Android, the initialization order needs to be dealt with in the very likely case that your application is already compatible with the desktop. This can be achieved like so:
int main(int argc, char* argv[])
{
KIconTheme::initTheme();
#ifdef Q_OS_ANDROID
QGuiApplication app(argc, argv);
QQuickStyle::setStyle("org.kde.breeze");
#else
QIcon::setFallbackThemeName("breeze");
if (qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE"))
{
QQuickStyle::setStyle("org.kde.desktop");
}
QApplication app(argc, argv);
// ...
#endif
}KirigamiAppDefaults usage
If you use KirigamiAppDefaults::Apply(), the above C++ code is already managed for you.Te leveren pictogrammen
Het eerste wat nodig is om de toepassing Breeze-pictogrammen te laten gebruiken, is het opnemen van KIconThemes in uw project.
Er zijn enkele CMake-opdrachten nodig om uw toepassingspictogram te bundelen met de toepassing.
Lastly, an extra CMake command coming from Kirigami can be used to bundle Kirigami icons into your application (and optionally Kirigami Addons icons).
KIconThemes
This can be done by:
- Het toevoegen als een afhankelijkheid in Craft:
def setDependencies(self):
self.runtimeDependencies["kde/frameworks/tier3/kiconthemes"] = None- Het toevoegen als een afhankelijkheid in CMake:
find_package(KF6 REQUIRED COMPONENTS IconThemes)
# ...
target_link_libraries(kirigami-hello
PRIVATE
# ...
KF6::IconThemes
)- Het gebruiken in de C++-code, in het bestand
main.cpp:
#include <KIconTheme>
// ...
int main(int argc, char* argv[])
{
KIconTheme::initTheme();
QApplication app(argc, argv);
// ...
}Merk op dat hoewel de projectnaam en de CMake-aanroep het meervoud gebruiken (KIconThemes, KF6IconThemes), de C++-aanroep het enkelvoud gebruikt (KIconTheme).
KIconThemes moet worden geïnitialiseerd voordat de toepassing wordt gestart.
KirigamiAppDefaults usage
If you use KirigamiAppDefaults::Apply(), the above KIconThemes initialization in C++ code is already managed for you.Toepassingspictogram
Als uw applicatie een pictogram heeft, moet dit aan uw project worden toegevoegd, zowel als een QML-hulpbron als onderdeel van de pictograminstallatie.
Normaal gesproken kan op Linux het toepassingspictogram eenvoudig in de juiste map worden geïnstalleerd, waarna het pictogram door de toepassing wordt opgehaald wanneer dat nodig is. Meestal bestaat het toepassingspictogram uit een primair SVG-pictogram, gecombineerd met meerdere PNG-pictogrammen in verschillende formaten.
Het installeren van het SVG-pictogram gebeurt als volgt in CMake:
install(FILES ${CMAKE_SOURCE_DIR}/icons/org.kde.myapp.svg
DESTINATION ${KDE_INSTALL_FULL_ICONDIR}/hicolor/scalable/apps)Het installeren van de PNG-pictogrammen gaat als volgt:
ecm_install_icons(ICONS
16-apps-myapp.png
24-apps-myapp.png
32-apps-myapp.png
48-apps-myapp.png
64-apps-myapp.png
128-apps-myapp.png
256-apps-myapp.png
512-apps-myapp.png
DESTINATION share/icons)Wanneer het toepassingspictogram op Linux wordt geïnstalleerd, wordt een PNG-pictogram zoals 48-apps-myapp.png geplaatst in ${INSTALL_PREFIX}/share/icons/hicolor/48x48/apps/myapp.png en een SVG-pictogram in ${INSTALL_PREFIX}/share/icons/hicolor/scalable/apps/org.kde.myapp.svg, waarbij ${INSTALL_PREFIX} meestal staat voor /usr, /usr/local of ~/.local. Merk op dat in het geval van PNG's de pictogramnaam wordt vertaald naar het pad dat het in het bestandssysteem zal hebben.
Zodra het pictogram op deze wijze is geïnstalleerd, kan het in QML-code eenvoudig worden aangeroepen via myapp of org.kde.myapp, op dezelfde manier als bij een aanroep vanuit QIcon::fromTheme(). Dit kan worden gebruikt bij elk QML-besturingselement dat over een icon.name-eigenschap beschikt.
Android heeft geen dergelijke standaardmap en het installeren van het pictogram heeft geen effect; het moet met de applicatie worden gebundeld. Om dit te doen, kan de PNG naar de eigen installatiemap worden gestuurd met behulp van ecm_add_app_icon() en kan een PNG- of SVG-bestand in de toepassing worden ingesloten als een Qt-hulpbronbestand in ecm_add_qml_module() of ecm_target_qml_sources().
Het PNG-toepassingspictogram is geïnstalleerd met:
ecm_add_app_icon(myapp ICONS ${PROJECT_SOURCE_DIR}/icons/256-apps-myapp.png)En het belangrijkste toepassingspictogram is als Qt-hulpbron meegeleverd met:
ecm_add_qml_module(myapp URI org.kde.myapp)
ecm_target_qml_sources(myapp SOURCES Main.qml RESOURCES ../icons/org.kde.myapp.svg)Hierdoor wordt het toepassingspictogram beschikbaar als een Qt-hulpbron onder qrc:/qt/qml/org/kde/myapp/org.kde.myapp.svg. Dit kan worden gebruikt met elk QML-besturingselement dat een eigenschap icon.source heeft.
Het pad RESOURCES is afhankelijk van de plaats van de pictogrammen zijn geïnstalleerd. Traditioneel wordt een map icons/ aangemaakt in de hoofdmap van het project voor het opslaan van alle pictogrammen, aangezien deze niet echt als bronbestanden worden beschouwd.
Nadat de pictogrammen zijn geïnstalleerd (voor Linux) en gebundeld (voor Windows en Android), kunt u ze in de code instellen. In QML-code moet u, voor compatibiliteit met zowel Windows als Android, het gebundelde pictogram gebruiken; in C++-code, met name bij het instellen van het vensterpictogram, kunt u standaard het thema-pictogram gebruiken en het gebundelde pictogram als terugvaloptie voor QGuiApplication::setWindowIcon():
QGuiApplication::setWindowIcon(QIcon::fromTheme("org.kde.myapp", QIcon(":/qt/qml/org/kde/myapp/org.kde.myapp.svg")));Kirigami-pictogrammen
Hoewel Android geen standaardmap heeft voor het installeren van pictogrammen uit een pictogramthema, is het mogelijk om de benodigde Kirigami-pictogrammen samen met uw Android-toepassing te bundelen.
Om dit te kunnen doen, zijn twee dingen nodig:
- Prepare the project with KIconThemes
- Include breeze-icons in your Craft blueprint
- kirigami_package_breeze_icons()
Om KIconThemes in te stellen, zie het bovenstaande gedeelte KIconThemes.
Om Breeze-pictogrammen als afhankelijkheid aan uw project toe te voegen, voegt u dit toe aan uw Craft-blauwdruk:
def setDependencies(self):
# ...
self.runtimeDependencies["kde/frameworks/tier1/breeze-icons"] = NoneBecause of the way the Android build is done, it is not possible for Craft to automatically do the icon bundling. Kirigami thus provides a CMake function kirigami_package_breeze_icons() which, at build time, clones and prepares the icons for bundling. This command needs to come before the step detailed in CMake function to package for Android.
The CMake command kirigami_package_breeze_icons() does not need to be wrapped behind a conditional, as it only ever runs when on Android.
Additionally, if you are using Kirigami Addons in your application, you may pass the ${KIRIGAMI_ADDONS_ICONS} variable to also ship the necessary icons for components such as FormCard.AboutPage and similar.
kirigami_package_breeze_icons(ICONS
org.kde.myapp insert-image-symbolic kde application-exit-symbolic
edit-clear-all-symbolic edit-undo-symbolic document-save-symbolic
applications-development-symbolic system-user-list donate-symbolic
${KIRIGAMI_ADDONS_ICONS}
)Android-manifest
An Android manifest is an XML file describing the application to the Android build tools, operating system, and stores. The file must be called AndroidManifest.xml.
Qt uses the Android manifest and supports additional configuration to call the necessary tools to build an APK that can be installed on Android.
KDE-toepassingen bewaren het manifest in een android/-map in de hoofdmap van het project.
Een Android-manifest kan er zo uitzien:
<?xml version='1.0' encoding='utf-8'?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.kde.myapp"
android:installLocation="auto">
<application android:name="org.qtproject.qt.android.bindings.QtApplication" android:label="MyApp" android:usesCleartextTraffic="true" android:icon="@drawable/myapp">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation"
android:name="org.qtproject.qt.android.bindings.QtActivity"
android:label="MyApp"
android:windowSoftInputMode="adjustResize"
android:launchMode="singleTop"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="myapp"/>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
</manifest>It is mostly boilerplate and can be copied and modified to an existing project, but it is worth learning what parts need to be accounted for.
In the <manifest> tag, the package corresponds to the name that identifies the application internally by Android. It needs to use reverse DNS notation. It should match the application ID specified in code.
In the <application> and <activity> tags, the android:label should be the user-facing name of the application. In the tag <meta-data>, android:value should match the target name as specified in CMake.
In the <application> tag, the android:icon="@drawable/myapp" should be an icon stored in android/res/drawable/, without the file extension. In this example, the file would be android/res/drawable/myapp.png. The res folder stands for "resources". If not specified, the default Android placeholder icon will be shown in the app menu and on the installation prompt instead.
An Activity stands for what the application will do in different states. For example, it might perform certain actions while on the foreground and other actions while on the background. Typically a Qt/KDE application has only one activity.
Each Activity can have one or more Intent Filters. An Intent is something the activity is able to do, which in the case of a KDE application is usually an action, but can also be a service. For example, if the application intends to launch, then it needs to signal to Android that this Activity is the entrypoint for the app (android.intent.action.MAIN) and that the intent is of type LAUNCHER to show up on the app menu screen and be able to launch. This should generally be sufficient for most KDE applications.
The <meta-data> tag can be repeated multiple times and have multiple purposes, and special Qt-specific configurations can be used. The android.app.lib_name metadata is required.
The <uses-permission> tag is straightforward and allows the application to request permission to perform a specific action. A Permission is different from an Intent in that the Intent requests another component to perform an action related to the activity, while a permission is a request for access to functionality that is by default not available.
The <supports-screens> tag specifies which form factors (screen sizes and pixel densities, phones or tablets) the application supports. Because QML applications are convergent, "any size" should be a reasonable default.
The only parts of the above example that are not required are android:icon="@drawable/myapp" (used only if your application already has an icon) and <uses-permissions> (which should only be added when actually needed).
Startscherm
A Splash Screen is an optional screen containing a static image or animation that shows up when launching an application to allow a few seconds for the app to initialize. When no splash screen is specified, the application will be shown as soon as it is opened, even if not ready.
To add it to your application, you will need to specify it in the AndroidManifest.xml metadata:
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/splash"/>In turn, an android/res/drawable/splash.xml file must exist:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:width="128dp" android:height="128dp" android:gravity="center">
<bitmap
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitXY"
android:src="@drawable/myapp"/>
</item>
</layer-list>This simple example commonly used in KDE applications centers the application icon in an empty background, and so an application icon residing in android/res/drawable/ is required.
Een APK voorbereiden
The last step needed to actually allow building an APK for Android is a simple CMake function that uses the files in the android/ directory:
ecm_add_android_apk(myapp
ANDROID_DIR ${PROJECT_SOURCE_DIR}/android
)Gebouw
Volg Toepassingen bouwen voor Android om uw toepassing voor Android te bouwen.
CI-bouwsels
Als het project correct is geconfigureerd om op Windows te bouwen en gebruikmaakt van de KDE-infrastructuur voor het hosten van de code (KDE Invent), is het mogelijk om Android CI/CD-taken te configureren.
Om dit te doen, moet u de relevante CI-sjablonen voor Windows toevoegen met een .gitlab-ci.yaml-bestand en uw afhankelijkheden vermelden in een .kde-ci.yaml-bestand zoals vermeld in Continuous Integration System.