Verwendung des Play Feature Delivery

Was ist die Bereitstellung von Funktionen?

In der Entwicklerdokumentation von Google wird diese Funktion ausführlich beschrieben. Sie ermöglicht es Entwicklern, ihre Projekte so zu strukturieren, dass der Google Play Store den Inhalt ihrer App in mehrere herunterladbare Pakete aufteilen kann. Außerdem haben die Entwickler so die Kontrolle darüber, wie der Inhalt an die Nutzer ausgeliefert wird. Diese aufgeteilten Software- und Inhaltspakete werden über Android App Bundles (AAB) an den Google Play Store geliefert.

Beispielprojekt: FDMapLoader

Diese App nutzt die Play-Feature-Bereitstellung, um einem Benutzer auf Anforderung Bilder zu liefern. Die App kann leicht modifiziert werden, um eine App zu erstellen, die über 200 MB groß ist, um die Größenbeschränkungen der App und den Download mit einem großen Feature Delivery-Modul zu testen.

Build-Setup

  • fdwintermapmodule: Feature-Modul-Projekt für Qt Creator
  • fdmaploader: Hauptanwendungsprojekt für Qt Creator
  • fdmaploader-android-project: Android-Projekt zum Kompilieren des Android-App-Bundles.

FDWintermapModule kompilieren - Funktionsmodul

Laden Sie das fdwintermapmodule-Projekt auf Qt Creator, konfigurieren Sie es für Ihre Zielplattform und erstellen Sie es.

FDMapLoader kompilieren - Hauptanwendung

Laden Sie den fdmaploader nach Qt Creator, konfigurieren Sie ihn für Ihre Zielplattform und erstellen Sie ihn.

Android Projekt modifizieren

  • Kopieren Sie die erstellten Binärdateien (.so) aus den Verzeichnissen für die Funktionsmodule und die Hauptanwendung in die entsprechenden Bibliotheksverzeichnisse in einem Android-Projekt. (app/src/main/jniLibs/[target ABI]/ bzw. fdwintermapmodule/src/main/jniLibs/[target ABI]/ )
  • Kopieren Sie andere geänderte Dateien, z. B. Ressourcendateien und Java-Klassen. (.../res/... und .../src/main/java/... Verzeichnisse)
  • Erstellen Sie das Android-Projekt entweder mit Android Studio oder über die Befehlszeile mit dem Gradle-Wrapper (./gradlew bundle)
  • Zum Testen können Sie APKs aus einem Bundle erstellen und eine lokale Testversion mit bundletool auf einem Gerät installieren. Bundletool ist ein von Google bereitgestelltes Tool, auf dessen Verwendung wir später in dieser Dokumentation eingehen werden. Zum Testen und Freigeben können Sie das Bundle in die Google Play Console hochladen.

Eigene Inhalte hinzufügen

Dieses Beispiel ist so konzipiert, dass Entwickler problemlos eigene Inhalte hinzufügen können, um die Funktionsbereitstellung zu testen. Um die maximale Paketgröße im Play Store zu überschreiten, können Kartenbilder (es müssen nicht unbedingt Kartenbilder sein, aber es passt zum Thema des Beispiels) zum Ordner images in FDMapLoader und FDWintermapModule hinzugefügt werden, die Bildnamen müssen ebenfalls zur Datei images.qrc hinzugefügt werden.

Erstellen Sie Ihre eigenen

In den folgenden Abschnitten wird beschrieben, wie Sie Ihr eigenes Projekt erstellen können, das die Play Feature Delivery verwendet. Es wird empfohlen, das Beispiel als Grundlage zu verwenden. In dem Projekt wurde Qt 6.7.2 verwendet.

Feature-Modul

Feature Delivery behandelt C++-Bibliotheken wie normale Shared Libraries, die zur Laufzeit verfügbar sein können oder auch nicht. Vor dem Aufruf einer Bibliothek muss die Verfügbarkeit einer solchen geprüft werden.

  • Verwenden Sie Qt Creator, um eine C++ Shared Library zu erstellen.
  • Implementieren Sie Funktionen und fügen Sie Ressourcen hinzu.
  • Erstellen Sie .so-Binärdateien.

Hauptanwendung (Qt)

  • Verwenden Sie Qt Creator, um eine App zu erstellen (Qt Quick Projektvorlage wurde hier verwendet).
  • Implementieren Sie den Zugriff auf die Feature Delivery Bibliothek. Die zentrale Klasse in der Google Play Feature Delivery Java Bibliothek ist SplitInstallManager.
  • Android-Vorlagendateien können über die Schaltfläche "Create Templates" im QtCreator Projects -> Build&Run -> [target ABI] -> Build Steps -> Build Android APK erstellt werden. Vorlagen werden im Ordner "android" im Projekt erstellt.
  • Fügen Sie Java-Dateien in den Ordner .../android/src/java/[package...] und Dateipfade in CMakeLists.txt ein:
    qt_add_executable...
    ...[path]/[java-filename.java]
    ...
  • In diesem Beispiel wurde eine Java-Klasse erstellt, um die Aufrufe und Rückrufe zu verwalten. Auf die Java-Klasse würde dann von Qt aus mit JNI zugegriffen werden. Die Android-Dokumentation enthält eine einfache Beschreibung, wie man ein Modul anfordert.
  • Beim Hinzufügen von Java-Dateien unter dem android-Ordner im Projekt muss die Eigenschaft QT_ANDROID_PACKAGE_SOURCE_DIR zur CMakeLists.txt hinzugefügt werden:
    ...
    set_property(TARGET appFDMainApp APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
                 ${CMAKE_CURRENT_SOURCE_DIR}/android)
    ...
  • Außerdem muss die Hauptanwendung build.gradle über Abhängigkeiten für die Feature-API verfügen: Ersetzen Sie im Block dependencies
    implementation 'androidx.core:core:1.13.1'

    durch

    implementation("com.google.android.play:feature-delivery:2.1.0")
  • Implementieren Sie den Zugriff auf die vom Feature-Modul bereitgestellte Bibliothek. Da das Feature-Modul für die Hauptanwendung verfügbar sein kann oder auch nicht, werden die Module nicht zur Erstellungszeit verknüpft und die Aufrufe an das Modul müssen zur Laufzeit aufgelöst werden. Beispiel:
    typedef void* (*LoadModuleRulesFunc)();
    LoadModuleRulesFunc loadModuleRules =
        (LoadModuleRulesFunc) mFDModuleLibrary.resolve("loadModuleRules");
    if (loadModuleRules) {
        void* result = loadModuleRules();
        QScopedPointer<QString> resultStr{static_cast<QString*>(result)};
    }
  • Implementieren Sie die Benutzeroberfläche und andere erforderliche Teile der Hauptanwendung.

Funktionsmodul (Qt)

  • Verwenden Sie Qt Creator, um eine Anwendung zu erstellen (die Projektvorlage Qt C++ Library wurde verwendet).
  • Implementieren Sie die Funktionen, die das Modul bietet.

Android-Projekt (Android)

Die Erstellung eines Projekts zur Erstellung eines Android-App-Bundles für die Bereitstellung von Funktionen basiert hauptsächlich auf der Dokumentation von Android:

Erstellen Sie ein Android-Projekt manuell oder mit Android Studio (unter Verwendung der Vorlage "No Activity"). Das Projekt wird so modifiziert, dass es ein Top-Level-Projekt und zwei Unterprojekte enthält, app und feature-module. Die Android Studio-Vorlage erstellt das Unterprojekt app und feature-module kann mit der Vorlage File -> New -> New Module hinzugefügt werden.

Das Vorlagenprojekt erfordert mehrere Änderungen:

  • Fügen Sie das Feature Delivery Plugin auf der Hauptebene build.gradle hinzu:
    plugins {
        id 'com.android.application' version '8.5.2' apply false
        id 'com.android.dynamic-feature' version '8.5.2' apply false
        id 'com.android.library' version '8.5.2' apply false
    }
  • Fügen Sie das Feature-Modul zur settings.gradle hinzu, ändern Sie rootProject.name falls erforderlich:
    ...
    rootProject.name = "name-of-the-root-project"
    include(:app)
    include(:name-of-the-feature-module)

app - Unterprojekt

  • Das Android-Projekt benötigt Qt-Binärdateien aus dem App-Hauptprojekt:
    • Kopieren Sie native Bibliotheken in Qt build: [build directory]/android-build/libs/[target ABI] nach app/src/main/jniLibs/[target ABI]
    • Kopieren Sie die Jars in [build directory]/android-build/libs/ nach app/libs/
  • Aus dem Qt-Build werden auch die Inhalte der Ordner res, AndroidManifest.xml und local.properties an die entsprechenden Stellen im Android-Projekt kopiert.
  • Fügen Sie die Datei feature_names.xml in den Ordner app/src/main/res/values ein, die einen String für das Feature-Modul enthält:
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="feature_module_name">name-of-the-feature-module-here</string>
    </resources>
  • Fügen Sie die Datei keep.xml zum Ordner app/src/main/res/raw hinzu, die Folgendes enthält:
    <?xml version="1.0" encoding="utf-8"?>
    <resources xmlns:tools="http://schemas.android.com/tools"
        tools:keep="@string/feature_module_winter_map"
        tools:discard="" />

Änderungen an den Build-Dateien des App-Unterprojekts

Die in das Android-Projekt kopierten Build-Dateien benötigen einige Änderungen.

app - Unterprojekt

build.gradle
  • Entfernen Sie die Blöcke buildScript und repositories.
  • Der Android-Block im build.gradle der Hauptanwendung erfordert einige Änderungen:
    • defaultConfig
    • packagingOptions
    • dynamicFeatures
    • sourceSets
    • aaptOptions
    • dependencies
android {
...
  defaultConfig {
  ...
    applicationId "your-project-name-here"
  ...
  }
  packagingOptions.jniLibs.useLegacyPackaging true

  dynamicFeatures = [":your-dynamic-feature-name-here"]

  sourceSets {
    main {
      manifest.srcFile 'src/main/AndroidManifest.xml'
      java.srcDirs = [qtAndroidDir + '/src', 'src', 'java']
      aidl.srcDirs = [qtAndroidDir + '/src', 'src', 'aidl']
      res.srcDirs = [qtAndroidDir + '/res', 'res']
      resources.srcDirs = ['resources']
      renderscript.srcDirs = ['src']
      assets.srcDirs = ['assets']
      jniLibs.srcDirs = ['src/main/jniLibs/']
    }
  }

  // Do not compress Qt binary resources file
  aaptOptions {
    noCompress 'rcc'
  }
...
}

dependencies {
...
  implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
  implementation 'com.google.android.play:feature-delivery:2.1.0'
  implementation libs.material
...
}

Fügen Sie dem Android-Block auch eine Signierkonfiguration hinzu:

android {
...
  signingConfigs {
    release {
      store

      \code
android {
...
  signingConfigs {
    release {
      storeFile file("/absolute/path/to/the/keystore.jks")
      storePassword "myStorePassword"
      keyAlias "myKeyAlias"
      keyPassword "myKeyPassword"
    }
  }
  buildTypes {
    release {
      signingConfig signingConfigs.release
      ...
    }
  }
...
}
gradle.properties

Qt hat Projektvariablen zu gradle.properties hinzugefügt. Ändern Sie bei Bedarf den Wert von androidPackageName.

AndroidManifest.xml
  • Entfernen Sie package:
    ...
    <manifest
    ...
      android:package... <--remove
    ...
    >
    ...
  • Ändern Sie label und android.app.lib_name, falls erforderlich:
    ...
    <application ...
      android:label=" ...
      <activity ... >
        <meta-data android:name="android.app.lib_name" android:value=" ...
        />
    ...

feature-module - Unterprojekt

App- und Feature-Module werden als Unterprojekte für das übergeordnete Android-Projekt erstellt. Die Ordner- und Dateistruktur ist ähnlich wie die des App-Unterprojekts.

  • Feature-Modul-Binärdateien aus dem Qt-Build werden in den Ordner [name-of-feature-module]/src/main/jniLibs/
  • Wie in der Haupt-App sollte der Ordner src/main/res/ die Ordner xml und values haben, die qtprovider_paths.xml bzw. libs.xml enthalten. Beide Dateien können aus dem App-Projekt kopiert werden.
  • Wenn der Ordner src/main/res/ Drawable- oder Mipmap-Ordner enthält und das Feature diese nicht benötigt, können sie entfernt werden.
  • Im Feature-Modul sollte src/main/res/values nicht das Feld app_name enthalten. In einfachen Projekten, in denen strings.xml nicht für andere Zwecke benötigt wird, kann es entfernt werden.
  • libs.xml enthält nur den Namen des Merkmalsmoduls:
    ...
        <array name="load_local_libs">
            <item>name-of-the-feature-module-here</item>
        </array>
    
        <string name="static_init_classes"></string>
        <string name="use_local_qt_libs">0</string>
        <string name="bundle_local_qt_libs">0</string>
    ...
  • AndroidManifest.xml wird dem Verzeichnis src/main/ hinzugefügt:
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:dist="http://schemas.android.com/apk/distribution">
    
        <dist:module
            dist:instant="false"
            dist:title="@string/feature_module_title_string">
            <dist:delivery>
                <dist:on-demand />
            </dist:delivery>
            <dist:fusing dist:include="false" />
        </dist:module>
        <!-- This feature module does contain code. -->
        <application android:hasCode="true"/>
    </manifest>
  • Das Feature-Modul build.gradle ist dem des App-Projekts recht ähnlich, mit einigen Änderungen. Hier ist ein Beispiel aus dem Beispielprojekt:
    plugins {
        id 'com.android.dynamic-feature'
    }
    
    dependencies {
        implementation project(':app')
        implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
        implementation 'com.google.android.play:feature-delivery:2.1.0'
    }
    
    android {
    
        namespace = androidPackageName
        compileSdk = androidCompileSdkVersion
        ndkVersion androidNdkVersion
    
        // Extract native libraries from the APK
        packagingOptions.jniLibs.useLegacyPackaging true
    
        defaultConfig {
            resConfig "en"
            minSdkVersion qtMinSdkVersion
            targetSdkVersion qtTargetSdkVersion
        }
    
        sourceSets {
            main {
                manifest.srcFile 'src/main/AndroidManifest.xml'
                resources.srcDirs = ['resources']
                renderscript.srcDirs = ['src']
                assets.srcDirs = ['assets']
                jniLibs.srcDirs = ['src/main/jniLibs/']
           }
        }
    
        tasks.withType(JavaCompile) {
            options.incremental = true
        }
    
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
    
        lintOptions {
            abortOnError false
        }
    
        // Do not compress Qt binary resources file
        aaptOptions {
            noCompress 'rcc'
        }
    }
  • gradle.properties Die Datei kann aus dem app-Unterprojekt kopiert werden, wobei das androidPackageName in das Feature-Modul-Paket geändert wird.

Bauen und Bereitstellen

Das AAB-Bündel kann über die Befehlszeile mit dem gradle-Wrapper erstellt werden: ./gradlew bundle Das erstellte AAB befindet sich im Ordner build/outputs/bundle/release (oder debug). Das AAB kann dann in den Google Play Store kopiert und zum Testen freigegeben werden. Das Testen kann auch lokal durchgeführt werden, indem bundletool mit dem Parameter --local-testing verwendet wird. Bundletool-Dokumentation

Verwendete Bundletool-Befehle

  • APK:s aus einem Bundle generieren:
    bundletool build-apks --bundle=/path/to/bundle.aab --output=/path/to/apk/package.apks --local-testing
  • App auf dem Gerät installieren:
    bundletool install-apks --apks=/path/to/apk/package.apks

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.