In diesem Leitfaden wird beschrieben, wie Sie In-App-Updates in Ihrer App mit nativem Code (C oder C++) unterstützen. Es gibt separate Leitfäden für Fälle, in denen Ihre Implementierung die Programmiersprache Kotlin oder Java verwendet, und für Fälle, in denen Ihre Implementierung Unity oder Unreal Engine verwendet.
Native SDK – Übersicht
Das Play Core Native SDK gehört zur Play Core SDK-Familie. Das Native SDK enthält eine C-Header-Datei, app_update.h, die AppUpdateManager aus der Java Play In-App Update Library umschließt. Mit dieser Header-Datei kann Ihre App die API für In-App-Updates direkt über Ihren nativen Code aufrufen.
Entwicklungsumgebung einrichten
Herunterladen Play Core Native SDK
Bevor Sie herunterladen können, müssen Sie den folgenden Nutzungsbedingungen zustimmen.
Nutzungsbedingungen
Last modified: September 24, 2020- By using the Play Core Software Development Kit, you agree to these terms in addition to the Google APIs Terms of Service ("API ToS"). If these terms are ever in conflict, these terms will take precedence over the API ToS. Please read these terms and the API ToS carefully.
- For purposes of these terms, "APIs" means Google's APIs, other developer services, and associated software, including any Redistributable Code.
- “Redistributable Code” means Google-provided object code or header files that call the APIs.
- Subject to these terms and the terms of the API ToS, you may copy and distribute Redistributable Code solely for inclusion as part of your API Client. Google and its licensors own all right, title and interest, including any and all intellectual property and other proprietary rights, in and to Redistributable Code. You will not modify, translate, or create derivative works of Redistributable Code.
- Google may make changes to these terms at any time with notice and the opportunity to decline further use of the Play Core Software Development Kit. Google will post notice of modifications to the terms at https://developer.android.com/guide/playcore/license. Changes will not be retroactive.
Führen Sie eine der folgenden Aktionen aus:
- Installieren Sie Android Studio Version 4.0 oder höher. Installieren Sie über die Benutzeroberfläche des SDK-Managers die Android SDK-Plattformversion 10.0 (API-Level 29).
- Installieren Sie die Android SDK-Befehlszeilentools und verwenden Sie
sdkmanager, um die Android SDK-Plattformversion 10.0 (API-Level 29) zu installieren.
Bereiten Sie Android Studio für die native Entwicklung vor, indem Sie mit dem SDK-Manager die neuesten Versionen von CMake und dem Android Native Development Kit (NDK) installieren. Weitere Informationen zum Erstellen oder Importieren nativer Projekte finden Sie unter Erste Schritte mit dem NDK.
Laden Sie die ZIP-Datei herunter und extrahieren Sie sie in Ihr Projekt.
Downloadlink Größe SHA-256-Prüfsumme 54,8 MiB 008b8fedc6179a6dc6ccc21af75591afc7036f78f3d5559d844f1b923934fef0 Aktualisieren Sie die Datei
build.gradleIhrer App wie unten gezeigt:Groovy
// App build.gradle plugins { id 'com.android.application' } // Define a path to the extracted Play Core SDK files. // If using a relative path, wrap it with file() since CMake requires absolute paths. def playcoreDir = file('../path/to/playcore-native-sdk') android { defaultConfig { ... externalNativeBuild { cmake { // Define the PLAYCORE_LOCATION directive. arguments "-DANDROID_STL=c++_static", "-DPLAYCORE_LOCATION=$playcoreDir" } } ndk { // Skip deprecated ABIs. Only required when using NDK 16 or earlier. abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' } } buildTypes { release { // Include Play Core Library proguard config files to strip unused code while retaining the Java symbols needed for JNI. proguardFile '$playcoreDir/proguard/common.pgcfg' proguardFile '$playcoreDir/proguard/gms_task.pgcfg' proguardFile '$playcoreDir/proguard/per-feature-proguard-files' ... } debug { ... } } externalNativeBuild { cmake { path 'src/main/CMakeLists.txt' } } } dependencies { // Import these feature-specific AARs for each Google Play Core library. implementation 'com.google.android.play:app-update:2.1.0' implementation 'com.google.android.play:asset-delivery:2.3.0' implementation 'com.google.android.play:integrity:1.6.0' implementation 'com.google.android.play:review:2.0.2' // Import these common dependencies. implementation 'com.google.android.gms:play-services-tasks:18.0.2' implementation files("$playcoreDir/playcore-native-metadata.jar") ... }
Kotlin
// App build.gradle plugins { id("com.android.application") } // Define a path to the extracted Play Core SDK files. // If using a relative path, wrap it with file() since CMake requires absolute paths. val playcoreDir = file("../path/to/playcore-native-sdk") android { defaultConfig { ... externalNativeBuild { cmake { // Define the PLAYCORE_LOCATION directive. arguments += listOf("-DANDROID_STL=c++_static", "-DPLAYCORE_LOCATION=$playcoreDir") } } ndk { // Skip deprecated ABIs. Only required when using NDK 16 or earlier. abiFilters.clear() abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64") } } buildTypes { release { // Include Play Core Library proguard config files to strip unused code while retaining the Java symbols needed for JNI. proguardFile("$playcoreDir/proguard/common.pgcfg") proguardFile("$playcoreDir/proguard/gms_task.pgcfg") proguardFile("$playcoreDir/proguard/per-feature-proguard-files") ... } debug { ... } } externalNativeBuild { cmake { path = "src/main/CMakeLists.txt" } } } dependencies { // Import these feature-specific AARs for each Google Play Core library. implementation("com.google.android.play:app-update:2.1.0") implementation("com.google.android.play:asset-delivery:2.3.0") implementation("com.google.android.play:integrity:1.6.0") implementation("com.google.android.play:review:2.0.2") // Import these common dependencies. implementation("com.google.android.gms:play-services-tasks:18.0.2") implementation(files("$playcoreDir/playcore-native-metadata.jar")) ... }
Aktualisieren Sie die
CMakeLists.txt-Dateien Ihrer App wie unten gezeigt:cmake_minimum_required(VERSION 3.6) ... # Add a static library called “playcore” built with the c++_static STL. include(${PLAYCORE_LOCATION}/playcore.cmake) add_playcore_static_library() // In this example “main” is your native code library, i.e. libmain.so. add_library(main SHARED ...) target_include_directories(main PRIVATE ${PLAYCORE_LOCATION}/include ...) target_link_libraries(main android playcore ...)
Datenerfassung
Das Play Core Native SDK kann versionsbezogene Daten erheben, damit Google das Produkt verbessern kann. Dazu gehören:
- Paketname der App
- Paketversion der App
- Version des Play Core Native SDK
Diese Daten werden erhoben, wenn Sie Ihr App-Paket in die Play Console hochladen. Wenn Sie diese Datenerhebung deaktivieren möchten, entfernen Sie den Import von $playcoreDir/playcore-native-metadata.jar aus der Datei „build.gradle“.
Diese Datenerhebung im Zusammenhang mit Ihrer Nutzung des Play Core Native SDK und die Verwendung der erhobenen Daten durch Google erfolgen getrennt und unabhängig von der Erhebung von Bibliotheksabhängigkeiten durch Google, die in Gradle deklariert werden, wenn Sie Ihr App-Paket in die Play Console hochladen.
Nachdem Sie das Play Core Native SDK in Ihr Projekt eingebunden haben, fügen Sie die folgende Zeile in Dateien ein, die API-Aufrufe enthalten:
#include "play/app_update.h"
In-App-Update API initialisieren
Wenn Sie die In-App-Update API verwenden, müssen Sie sie zuerst initialisieren. Rufen Sie dazu die Funktion AppUpdateManager_init() auf, wie im folgenden Beispiel mit android_native_app_glue.h gezeigt:
void android_main(android_app* app) {
app->onInputEvent = HandleInputEvent;
AppUpdateErrorCode error_code =
AppUpdateManager_init(app->activity->vm, app->activity->clazz);
if (error_code == APP_UPDATE_NO_ERROR) {
// You can use the API.
}
}
Prüfen, ob ein Update verfügbar ist
Bevor Sie ein Update anfordern, prüfen Sie, ob ein Update für Ihre App verfügbar ist. Mit AppUpdateManager_requestInfo() wird eine asynchrone Anfrage gestartet, die die erforderlichen Informationen sammelt, um den In-App-Update-Vorgang später zu starten. Die Funktion gibt APP_UPDATE_NO_ERROR zurück, wenn die Anfrage erfolgreich gestartet wurde.
AppUpdateErrorCode error_code = AppUpdateManager_requestInfo()
if (error_code == APP_UPDATE_NO_ERROR) {
// The request has successfully started, check the result using
// AppUpdateManager_getInfo.
}
Sie können den laufenden Prozess und das Ergebnis der Anfrage mit AppUpdateManager_getInfo() verfolgen. Zusätzlich zum Fehlercode gibt diese Funktion eine opake AppUpdateInfo-Struktur zurück, mit der Sie Informationen zur Aktualisierungsanfrage abrufen können. Sie können diese Funktion beispielsweise in jeder Spielschleife aufrufen, bis sie ein Ergebnis ungleich null für info zurückgibt:
AppUpdateInfo* info;
GameUpdate() {
// Keep calling this in every game loop until info != nullptr
AppUpdateErrorCode error_code = AppUpdateManager_getInfo(&info);
if (error_code == APP_UPDATE_NO_ERROR && info != nullptr) {
// Successfully started, check the result in the following functions
}
...
}
Aktualität von Updates prüfen
Zusätzlich zur Prüfung, ob ein Update verfügbar ist, solltest du auch prüfen, wie viel Zeit vergangen ist, seit der Nutzer zuletzt über den Google Play Store über ein Update benachrichtigt wurde. So kannst du besser entscheiden, ob du ein flexibles oder ein sofortiges Update initiieren solltest. Beispielsweise könntest du ein paar Tage warten, bevor du den Nutzer über ein flexibles Update benachrichtigst, und dann noch einmal ein paar Tage, bevor du ein sofortiges Update verlangst.
Mit AppUpdateInfo_getClientVersionStalenessDays() können Sie die Anzahl der Tage prüfen, die seit der Verfügbarkeit des Updates im Google Play Store vergangen sind:
int32_t staleness_days = AppUpdateInfo_getClientVersionStalenessDays(info);
Updatepriorität prüfen
Mit der Google Play Developer API können Sie die Priorität jedes Updates festlegen. So kann in Ihrer App entschieden werden, wie dringend ein Update für den Nutzer empfohlen werden soll. Betrachten Sie beispielsweise die folgende Strategie zum Festlegen der Updatepriorität:
- Kleinere Verbesserungen an der Benutzeroberfläche: Update mit niedriger Priorität; weder ein flexibles noch ein sofortiges Update anfordern. Aktualisieren Sie die App nur, wenn der Nutzer nicht mit ihr interagiert.
- Leistungsverbesserungen: Update mit mittlerer Priorität; flexibles Update anfordern.
- Kritisches Sicherheitsupdate: Update mit hoher Priorität; sofortiges Update anfordern.
Zur Bestimmung der Priorität verwendet Google Play einen ganzzahligen Wert zwischen 0 und 5, wobei 0 der Standardwert und 5 die höchste Priorität ist. Wenn du die Priorität für ein Update festlegen möchtest, verwende das Feld inAppUpdatePriority unter Edits.tracks.releases in der Google Play Developer API. Alle neu hinzugefügten Versionen im Release haben dieselbe Priorität wie das Release. Die Priorität kann nur beim Roll-out eines neuen Release festgelegt und später nicht mehr geändert werden.
Lege die Priorität mithilfe der Google Play Developer API fest, wie in der Dokumentation zur Play Developer API beschrieben. Geben Sie die Priorität des In-App-Updates in der Ressource Edit.tracks an, die in der Methode Edit.tracks: update übergeben wird.
Im folgenden Beispiel wird gezeigt, wie eine App mit dem Versionscode 88 und dem inAppUpdatePriority 5 veröffentlicht wird:
{ "releases": [{ "versionCodes": ["88"], "inAppUpdatePriority": 5, "status": "completed" }] }
Im Code Ihrer App können Sie die Prioritätsstufe für ein bestimmtes Update mit AppUpdateInfo_getPriority() prüfen:
int32_t priority = AppUpdateInfo_getPriority(info);
Update starten
Nachdem Sie bestätigt haben, dass ein Update verfügbar ist, können Sie mit AppUpdateManager_requestStartUpdate() ein Update anfordern. Bevor Sie eine Aktualisierung anfordern, rufen Sie ein aktuelles AppUpdateInfo-Objekt ab und erstellen Sie ein AppUpdateOptions-Objekt, um den Aktualisierungsablauf zu konfigurieren. Ein AppUpdateOptions-Objekt definiert Optionen für einen In-App-Update-Vorgang, einschließlich der Angabe, ob das Update flexibel oder sofort erfolgen soll.
Im folgenden Beispiel wird ein AppUpdateOptions-Objekt für einen flexiblen Updateablauf erstellt:
// Creates an AppUpdateOptions configuring a flexible in-app update flow.
AppUpdateOptions* options;
AppUpdateErrorCode error_code = AppUpdateOptions_createOptions(APP_UPDATE_TYPE_FLEXIBLE, &options);
Im folgenden Beispiel wird ein AppUpdateOptions-Objekt für einen sofortigen Update-Flow erstellt:
// Creates an AppUpdateOptions configuring an immediate in-app update flow.
AppUpdateOptions* options;
AppUpdateErrorCode error_code = AppUpdateOptions_createOptions(APP_UPDATE_TYPE_IMMEDIATE, &options);
Das Objekt AppUpdateOptions enthält auch ein Feld AllowAssetPackDeletion, das festlegt, ob das Update bei begrenztem Gerätespeicher Asset-Packs löschen darf. Dieses Feld ist standardmäßig auf false festgelegt. Sie können es jedoch mit der Methode AppUpdateOptions_setAssetPackDeletionAllowed() auf true festlegen:
bool allow = true;
AppUpdateErrorCode error_code = AppUpdateOptions_setAssetPackDeletionAllowed(options, allow);
Wenn du ein aktuelles AppUpdateInfo-Objekt und ein richtig konfiguriertes AppUpdateOptions-Objekt hast, rufe AppUpdateManager_requestStartUpdate() auf, um asynchron einen Update-Vorgang anzufordern. Übergib dabei eine Android-Aktivität jobject für den letzten Parameter.
AppUpdateErrorCode request_error_code =
AppUpdateManager_requestStartUpdate(info, options, app->activity->clazz);
Wenn Sie Ressourcen entlasten möchten, beenden Sie Instanzen von AppUpdateInfo und AppUpdateOptions, die Sie nicht mehr benötigen. Rufen Sie dazu AppUpdateInfo_destroy() bzw. AppUpdateOptions_destroy() auf.
AppUpdateInfo_destroy(info);
AppUpdateOptions_destroy(options);
Bei einem sofortigen Update wird in Google Play eine Bestätigungsseite für den Nutzer angezeigt. Wenn der Nutzer die Anfrage akzeptiert, wird das Update automatisch von Google Play im Vordergrund heruntergeladen und installiert. Nach erfolgreicher Installation wird die App mit der aktualisierten Version neu gestartet.
Für einen flexiblen Update-Ablauf kannst du weiterhin aktuelle AppUpdateInfo-Objekte anfordern, um den aktuellen Updatestatus im Blick zu behalten, während der Nutzer weiterhin mit der App interagiert. Nachdem der Download erfolgreich abgeschlossen wurde, musst du den Abschluss des Updates durch Aufrufen von AppUpdateManager_requestCompleteUpdate() auslösen, wie im folgenden Beispiel gezeigt:
AppUpdateStatus status = AppUpdateInfo_getStatus(info);
if (status == APP_UPDATE_DOWNLOADED) {
AppUpdateErrorCode error_code = AppUpdateManager_requestCompleteUpdate();
if (error_code != APP_UPDATE_NO_ERROR)
{
// There was an error while completing the update flow.
}
}
Ressourcen können freigegeben werden, indem die Funktion AppUpdateManager_destroy() aufgerufen wird, nachdem die API in der App nicht mehr verwendet wird.
Fehlerbehandlung
In diesem Abschnitt werden Lösungen für häufige Fehler beschrieben, die durch bestimmte AppUpdateErrorCode-Werte angezeigt werden:
- Der Fehlercode
-110, APP_UPDATE_INITIALIZATION_NEEDEDgibt an, dass die API nicht erfolgreich initialisiert wurde. Rufen SieAppUpdateManager_init()auf, um die API zu initialisieren. - Der Fehlercode
-4, APP_UPDATE_INVALID_REQUESTgibt an, dass einige Parameter der Anfrage für den Update-Ablauf fehlerhaft sind. Prüfen Sie, ob die ObjekteAppUpdateInfoundAppUpdateOptionsnicht null und korrekt formatiert sind. - Der Fehlercode
-5, APP_UPDATE_UNAVAILABLEgibt an, dass kein anwendbares Update verfügbar ist. Achten Sie darauf, dass die Zielversion denselben Paketnamen, dieselbe Anwendungs-ID und denselben Signaturschlüssel hat. Wenn ein Update verfügbar ist, leeren Sie den Cache der App und rufen SieAppUpdateManager_requestAppUpdateInfo()noch einmal auf, umAppUpdateInfozu aktualisieren. - Der Fehlercode
-6, APP_UPDATE_NOT_ALLOWEDgibt an, dass der vomAppUpdateOption-Objekt angegebene Aktualisierungstyp nicht zulässig ist. Prüfen Sie, ob das ObjektAppUpdateInfoangibt, dass der Updatetyp zulässig ist, bevor Sie den Updatevorgang starten.
Nächste Schritte
Testen Sie die In-App-Updates Ihrer App, um zu prüfen, ob die Integration ordnungsgemäß funktioniert.