Skip to main content
Salta al contingut

Configuració a l'Android

Preparant la vostra aplicació C++ per a l'Android

Introducció

Les Qt tenen un bon suport de l'Android, les aplicacions requereixen un nombre important de modificacions per a funcionar correctament a l'Android.

Són necessàries poques coses:

L'esquema de Craft és necessari per a empaquetar totes les dependències juntament amb l'aplicació per a generar un paquet APK d'Android.

El «qqc2-breeze-style» és una alternativa a «qqc2-desktop-style» que està especialment orientat a plataformes mòbils com l'Android i el Plasma Mobile.

L'esquema Craft de l'aplicació necessita un codi condicional per no barrejar l'estil d'escriptori i mòbil, mentre que el codi C++ necessitarà una cura especial per no utilitzar la configuració incorrecta per a l'escriptori i el mòbil. El codi CMake podria necessitar opcionalment també codi condicional, encara que es pot evitar.

Empaquetar les icones necessàries perquè l'aplicació funcioni es fa amb l'ajuda dels «extra-cmake-modules». les eines d'empaquetament de recursos de les Qt, així com de les funciones de Kirigami i Kirigami Addons CMake.

El manifest d'Android declara les metadades i fitxers addicionals que s'han d'empaquetar amb l'aplicació Android.

El fitxer de construcció de Gradle és necessari en cas que utilitzeu la integració «extra-cmake-modules» per aplicar les metadades existents de la vostra aplicació a la construcció d'Android, com ara la versió de l'aplicació, o en cas que vulgueu opcions de construcció especials.

El fitxer XML de pantalla de presentació és necessari en cas que vulgueu afegir una pantalla de presentació amb una icona personalitzada, fons i posicionament.

Esquema de Craft

Definició de «qqc2-breeze-style»

Per a començar a utilitzar el «qqc2-breeze-style», haureu d'afegir-lo a Craft. Com que només s'utilitza a l'Android, requerirà una clàusula condicional, especialment si l'aplicació ja està configurada per a construir en el Windows i/o Linux utilitzant l'estil «qqc2-desktop». Això requereix importar el mòdul CraftCore:

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"] = None

Una lògica similar a «si no és Android, utilitza el qqc2-desktop-style, en cas contrari utilitza qqc2-breeze-style» també s'ha d'aplicar al CMake, en cas que s'utilitzi qualsevol mètode per trobar «qqc2-desktop.-style»:

if (NOT ANDROID)
    find_package(KF6QQC2DesktopStyle REQUIRED)
    ecm_find_qmlmodule(org.kde.desktop REQUIRED)
endif()

El codi condicional també es requereix en el C++.

En l'Android, les aplicacions KDE no utilitzen QApplication, sinó QGuiApplication. A més d'establir «qqc2-breeze-style» només per a Android, l'ordre d'inicialització s'ha de tractar en el cas molt probable que l'aplicació ja sigui compatible amb l'escriptori. Això es pot aconseguir així:

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
}

Distribució d'icones

El primer que cal per a fer que l'aplicació utilitzi les icones Brisa és incloure KIconThemes en el projecte.

Es necessiten algunes ordres del CMake per afegir la icona de l'aplicació a l'aplicació.

Finalment, es pot utilitzar una ordre CMake extra procedent del Kirigami per a afegir icones del Kirigami a l'aplicació (i opcionalment icones de Kirigami Addons).

KIconThemes

Això es pot fer:

  • Afegint-la com a dependència al Craft:
def setDependencies(self):
    self.runtimeDependencies["kde/frameworks/tier3/kiconthemes"] = None
  • Afegint-la com a dependència al CMake:
find_package(KF6 REQUIRED COMPONENTS IconThemes)

# ...

target_link_libraries(kirigami-hello
    PRIVATE
    # ...
    KF6::IconThemes
)
  • Usant-la al codi C++, en el fitxer main.cpp:
#include <KIconTheme>

// ...
int main(int argc, char* argv[])
{
    KIconTheme::initTheme();
    QApplication app(argc, argv);
    // ...
}

Tingueu en compte que encara que el nom del projecte i la crida al CMake fan servir el plural (KIconThemes, KF6IconThemes), la crida C++ fa servir el singular (KIconTheme).

Cal inicialitzar KIconThemes abans de l'aplicació.

Icona de l'aplicació

Si l'aplicació té una icona, s'ha d'afegir al vostre projecte tant com un recurs QML i com a part de la instal·lació d'icones.

Habitualment al Linux, la icona de l'aplicació es pot instal·lar al directori correcte, i l'aplicació recuperarà la icona quan sigui necessari. Normalment, la icona de l'aplicació consisteix en una icona SVG primària, aparellada amb diverses mides d'icones PNG.

La instal·lació de la icona SVG es fa així en el CMake:

install(FILES ${CMAKE_SOURCE_DIR}/icons/org.kde.myapp.svg
    DESTINATION ${KDE_INSTALL_FULL_ICONDIR}/hicolor/scalable/apps)

I la instal·lació de les icones PNG es fa així:

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)

Quan s'instal·la la icona de l'aplicació al Linux, una icona PNG com 48-apps-myapp.png goes to ${INSTALL_PREFIX}/share/icons/hicolor/48x48/apps/myapp.png, i una icona SVG va a ${INSTALL_PREFIX}/share/icons/hicolor/scalable/apps/org.kde.myapp.svg, on ${INSTALL_PREFIX} normalment significa /usr, /usr/local o ~/.local. Tingueu en compte com en el cas dels PNG que el nom de la icona es tradueix al camí que tindrà en el sistema de fitxers.

Una vegada instal·lada la icona d'aquesta manera, en codi QML, es pot cridar simplement amb myapp o org.kde.myapp, com es cridaria des de QIcon::fromTheme(). Això es pot utilitzar amb qualsevol control QML que tingui una propietat icon.name.

L'Android no té aquest directori estàndard, i la instal·lació de la icona no té cap efecte; s'ha d'empaquetar amb l'aplicació. Per a fer-ho, el PNG es pot enviar al seu propi directori d'instal·lació d'ecm_add_app_icon() i un fitxer PNG o SVG es pot incrustar a l'aplicació com un fitxer de recursos Qt a ecm_add_qml_module() o ecm_target_qml_sources().

La icona de l'aplicació PNG s'instal·la amb:

ecm_add_app_icon(myapp ICONS ${PROJECT_SOURCE_DIR}/icons/256-apps-myapp.png)

I la icona principal de l'aplicació s'empaqueta com a recurs Qt amb:

ecm_add_qml_module(myapp URI org.kde.myapp)
ecm_target_qml_sources(myapp SOURCES Main.qml RESOURCES ../icons/org.kde.myapp.svg)

Això farà que la icona de l'aplicació estigui disponible com a recurs Qt a qrc:/qt/qml/org/kde/myapp/org.kde.myapp.svg. Això es pot utilitzar amb qualsevol control QML que tingui una propietat icon.source.

El camí RESOURCES depèn del lloc on estiguin instal·lades les icones. Tradicionalment, es crea una carpeta icons/ a l'arrel del projecte per a emmagatzemar totes les icones, ja que realment no compten com a fitxers de codi font.

Després d'instal·lar les icones (per al Linux) i empaquetades (per al Windows i l'Android), podeu definir-les al codi. Al codi QML, per a la compatibilitat amb el Windows i l'Android, hauríeu d'utilitzar la icona empaquetada; en el codi C++, especialment quan establiu la icona de la finestra, podeu utilitzar la icona del tema predeterminat i la icona empaquetada com a alternativa amb QGuiApplication::setWindowIcon():

QGuiApplication::setWindowIcon(QIcon::fromTheme("org.kde.myapp", QIcon(":/qt/qml/org/kde/myapp/org.kde.myapp.svg")));

Icones del Kirigami

Tot i que l'Android no té un directori estàndard on instal·lar icones des d'un tema d'icones, és possible afegir les icones Kirigami necessàries juntament amb la vostra aplicació Android.

Hi ha dues coses necessàries perquè això es faci:

  • Prepareu el projecte amb KIconThemes
  • Inclogueu les «breeze-icons» en l'esquema Craft
  • kirigami_package_breeze_icons()

Per a configurar KIconThemes, vegeu la secció anterior KIconThemes.

Per a afegir les «breeze-icon» com a dependència del vostre projecte, afegiu-ho al vostre esquema de Craft:

def setDependencies(self):
    # ...
    self.runtimeDependencies["kde/frameworks/tier1/breeze-icons"] = None

A causa de la forma en què es fa la construcció d'Android, no és possible que Craft faci automàticament l'empaquetament d'icones. El Kirigami proporciona una funció CMake kirigami_package_breeze_icons() que, en temps de construcció, clona i prepara les icones per a l'empaquetament. Aquesta ordre ha d'anar abans del pas detallat a la funció CMake per a empaquetar per a Android.

L'ordre CMake kirigami_package_breeze_icons() no cal que s'embolcalli darrere d'un condicional, ja que només s'executa quan està a l'Android.

A més, si utilitzeu els Kirigami Addons a l'aplicació, podeu passar la variable ${KIRIGAMI_ADDONS_ICONS} per a enviar també les icones necessàries per a components com ara FormCard.AboutPage i similars.

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}
)

Manifest d'Android

Un manifest d'Android és un fitxer XML que descriu l'aplicació a les eines de construcció d'Android, el sistema operatiu i les botigues. El fitxer cal que s'anomeni AndroidManifest.xml.

Les Qt usen el manifest d'Android i permeten una configuració addicional per a cridar les eines necessàries per a construir un APK que es pot instal·lar a l'Android.

Les aplicacions KDE mantenen el manifest emmagatzemat en un directori android/ a l'arrel del projecte.

Un manifest d'Android podria ser així:

<?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>

Es tracta majoritàriament d'un estàndard i es pot copiar i modificar a un projecte existent, però val la pena aprendre quines parts cal explicar.

A l'etiqueta <manifest>, el package correspon al nom que identifica l'aplicació internament a l'Android. Cal utilitzar la notació DNS inversa. Ha de coincidir amb l'ID de l'aplicació especificat en el codi.

A les etiquetes <application> i <activity>, el android:label hauria de ser el nom de l'aplicació de cara als usuaris. A l'etiqueta <meta-data>, android:value hauria de coincidir amb el nom de destinació tal com s'especifica a CMake.

A l'etiqueta <application>, la android:icon="@drawable/myapp" hauria de ser una icona emmagatzemada a android/res/drawable/, sense l'extensió de fitxer. En aquest exemple, el fitxer seria android/res/drawable/myapp.png. La carpeta res significa «recursos». Si no s'especifica, es mostrarà la icona predeterminada de marcador de posició d'Android al menú de l'aplicació i a l'indicador d'instal·lació.

Una Activity vol dir el que farà l'aplicació en estats diferents. Per exemple, pot realitzar certes accions mentre és en primer pla i altres accions mentre que és en segon pla. Normalment, una aplicació Qt/KDE només té una activitat.

Cada Activity pot tenir un o més Intent Filters. Un intent és una cosa que l'activitat és capaç de fer, que en el cas d'una aplicació KDE sol ser una acció, però també pot ser un servei. Per exemple, si l'aplicació té el propòsit de llançar, llavors cal indicar a l'Android que aquesta activitat és el punt d'entrada de l'aplicació (android.intent.action.MAIN) i que el propòsit és del tipus LAUNCHER per a mostrar-se a la pantalla de menú de l'aplicació i poder llançar-la. En general, això hauria de ser suficient per a la majoria d'aplicacions KDE.

L'etiqueta <meta-data> es pot repetir diverses vegades i té diversos propòsits, i es poden utilitzar configuracions específiques de les Qt especials. Es requereixen la metadada android.app.lib_name.

L'etiqueta <uses-permission> és directa i permet a l'aplicació sol·licitar permís per realitzar una acció específica. Un Permission és diferent d'un Intent, ja que Intent sol·licita un altre component per realitzar una acció relacionada amb l'activitat, mentre que un permís és una sol·licitud d'accés a la funcionalitat que no està disponible de manera predeterminada.

L'etiqueta <supports-screens> especifica quins factors de forma (mides de pantalla i densitats de píxels, telèfons o tauletes) admet l'aplicació. Com que les aplicacions QML són convergents, «any size» hauria de ser un valor predeterminat raonable.

Les úniques parts de l'exemple anterior que no són necessàries són android:icon="@drawable/myapp" (només s'utilitza si l'aplicació ja té una icona) i <uses-permissions> (que només s'hauria d'afegir quan sigui necessari).

Pantalla de presentació

Una «Splash Screen» (Pantalla de presentació) és una pantalla opcional que conté una imatge estàtica o una animació que es mostra quan es llança una aplicació que es veu durant uns segons perquè l'aplicació s'inicialitzi. Si no s'especifica cap pantalla de presentació, l'aplicació es mostrarà tan aviat com s'obri, encara que no estigui llesta.

Per afegir-la a la vostra aplicació, haureu d'especificar-ho a les metadades de l'AndroidManifest.xml:

<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/splash"/>

Al seu torn, ha d'existir un fitxer android/res/drawable/splash.xml:

<?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>

Aquest exemple senzill que s'utilitza habitualment a les aplicacions KDE centra la icona de l'aplicació en un fons buit, i per tant, es requereix una icona d'aplicació que resideixi a android/res/drawable/.

Preparant un APK

L'últim pas necessari per a permetre la construcció d'un APK per a Android és una simple funció CMake que utilitza els fitxers en el directori android/:

ecm_add_android_apk(myapp
    ANDROID_DIR ${PROJECT_SOURCE_DIR}/android
)

Construcció

Per a construir la vostra aplicació a l'Android, seguiu Construir aplicacions per a l'Android.

Construccions de CI

Si el projecte s'ha configurat correctament per a construir al Windows i està utilitzant la infraestructura KDE per al seu allotjament de codi (KDE Invent), és possible configurar els treballs CI/CD de l'Android.

Per a fer-ho, haureu d'afegir les plantilles CI rellevants del Windows amb un fitxer .gitlab-ci.yaml i llistar les vostres dependències en un fitxer .kde-ci.yaml com s'ha esmentat al Sistema d'integració contínua.