Questa guida descrive come supportare gli aggiornamenti in-app nella tua app utilizzando codice nativo (C o C++). Esistono guide separate per i casi in cui l'implementazione utilizza il linguaggio di programmazione Kotlin o il linguaggio di programmazione Java e per i casi in cui l'implementazione utilizza Unity o Unreal Engine.
Panoramica dell'SDK nativo
L'SDK nativo della libreria di base Play fa parte della famiglia di SDK della libreria di base Play. L'SDK nativo
include un file di intestazione C, app_update.h, che esegue il wrapping di AppUpdateManager
dalla libreria Java Play In-App Update. Questo file di intestazione consente alla tua app di chiamare l'API per gli aggiornamenti in-app direttamente dal codice nativo.
Configurazione dell'ambiente di sviluppo
Scarica Play Core Native SDK
Prima di scaricare, devi accettare i seguenti Termini e condizioni.
Termini e condizioni
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.
Esegui una delle seguenti operazioni:
- Installa Android Studio versione 4.0 o successive. Utilizza l'interfaccia utente di SDK Manager per installare la piattaforma SDK Android versione 10.0 (livello API 29).
- Installa gli strumenti da riga di comando dell'SDK Android
e utilizza
sdkmanagerper installare la piattaforma SDK Android versione 10.0 (livello API 29).
Prepara Android Studio per lo sviluppo nativo utilizzando lo SDK Manager per installare l'ultima versione di CMake e dell'Android Native Development Kit (NDK). Per ulteriori informazioni sulla creazione o sull'importazione di progetti nativi, consulta la guida introduttiva all'NDK.
Scarica il file ZIP ed estrailo insieme al progetto.
Link di download Dimensioni Checksum SHA-256 54,8 MiB 008b8fedc6179a6dc6ccc21af75591afc7036f78f3d5559d844f1b923934fef0 Aggiorna il file
build.gradledella tua app come mostrato di seguito:Alla moda
// 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")) ... }
Aggiorna i file
CMakeLists.txtdella tua app come mostrato di seguito: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 ...)
Raccolta dati
L'SDK nativo della libreria di base Play può raccogliere dati relativi alla versione per consentire a Google di migliorare il prodotto, tra cui:
- Nome del pacchetto dell'app
- Versione del pacchetto dell'app
- Versione dell'SDK nativo della libreria di base Play
Questi dati verranno raccolti quando carichi il pacchetto applicativo
su Play Console. Per disattivare questa procedura di raccolta dei dati, rimuovi l'importazione $playcoreDir/playcore-native-metadata.jar nel file build.gradle.
Tieni presente che questa raccolta di dati relativa al tuo utilizzo dell'SDK nativo della libreria di base Play e all'utilizzo dei dati raccolti da parte di Google è separata e indipendente dalla raccolta delle dipendenze delle librerie dichiarate in Gradle da parte di Google quando carichi il pacchetto dell'app su Play Console.
Dopo aver integrato l'SDK nativo della libreria di base Play nel tuo progetto, includi la seguente riga nei file che contengono chiamate API:
#include "play/app_update.h"
Inizializzare l'API per gli aggiornamenti in-app
Ogni volta che utilizzi l'API per gli aggiornamenti in-app, inizializzala prima chiamando la
AppUpdateManager_init() funzione, come mostrato nell'esempio seguente creato
con android_native_app_glue.h:
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.
}
}
Verificare la disponibilità di aggiornamenti
Prima di richiedere un aggiornamento, verifica se è disponibile un aggiornamento per la tua
app. AppUpdateManager_requestInfo() avvia una richiesta asincrona che
raccoglie le informazioni necessarie per avviare il flusso di aggiornamento in-app in un secondo momento. La funzione restituisce APP_UPDATE_NO_ERROR se la richiesta viene avviata correttamente.
AppUpdateErrorCode error_code = AppUpdateManager_requestInfo()
if (error_code == APP_UPDATE_NO_ERROR) {
// The request has successfully started, check the result using
// AppUpdateManager_getInfo.
}
Puoi monitorare il processo in corso e il risultato della richiesta utilizzando
AppUpdateManager_getInfo(). Oltre al codice di errore, questa funzione
restituisce una struttura opaca AppUpdateInfo, che puoi utilizzare per recuperare
informazioni sulla richiesta di aggiornamento. Ad esempio, potresti voler chiamare questa funzione in ogni ciclo di gioco finché non restituisce un risultato non nullo per info:
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
}
...
}
Verificare l'obsolescenza dell'aggiornamento
Oltre a verificare se è disponibile un aggiornamento, potresti anche voler controllare quanto tempo è trascorso dall'ultima volta che l'utente ha ricevuto una notifica di un aggiornamento tramite il Play Store. In questo modo, puoi decidere se avviare un aggiornamento flessibile o immediato. Ad esempio, potresti attendere alcuni giorni prima di inviare una notifica all'utente con un aggiornamento flessibile e alcuni giorni dopo prima di richiedere un aggiornamento immediato.
Utilizza AppUpdateInfo_getClientVersionStalenessDays() per verificare il numero di
giorni trascorsi da quando l'aggiornamento è diventato disponibile tramite il Play Store:
int32_t staleness_days = AppUpdateInfo_getClientVersionStalenessDays(info);
Verificare la priorità dell'aggiornamento
L'API Google Play Developer ti consente di impostare la priorità di ogni aggiornamento. In questo modo, la tua app può decidere con quale forza consigliare un aggiornamento all'utente. Ad esempio, considera la seguente strategia per impostare la priorità dell'aggiornamento:
- Miglioramenti secondari dell'interfaccia utente: aggiornamento a bassa priorità; non richiedere un aggiornamento flessibile né un aggiornamento immediato. Aggiorna solo quando l'utente non interagisce con la tua app.
- Miglioramenti del rendimento: aggiornamento a media priorità; richiedi un aggiornamento flessibile.
- Aggiornamento della sicurezza critico: aggiornamento a priorità elevata; richiedi un aggiornamento immediato.
Per determinare la priorità, Google Play utilizza un valore intero compreso tra 0 e 5, dove 0 è il valore predefinito e 5 è la priorità più alta. Per impostare la priorità di un
aggiornamento, utilizza il inAppUpdatePriority campo in Edits.tracks.releases
nell'API Google Play Developer. Tutte le versioni appena aggiunte nella release sono considerate con la stessa priorità della release. La priorità può essere impostata solo durante il lancio di una nuova uscita e non può essere modificata in un secondo momento.
Imposta la priorità utilizzando l'API Google Play Developer, come descritto nella documentazione dell'API Play Developer. Specifica la priorità dell'aggiornamento in-app nella
Edit.tracks risorsa passata nel Edit.tracks: update metodo.
L'esempio seguente mostra il rilascio di un'app con codice di versione 88 e inAppUpdatePriority 5:
{ "releases": [{ "versionCodes": ["88"], "inAppUpdatePriority": 5, "status": "completed" }] }
Nel codice dell'app, puoi controllare il livello di priorità di un determinato aggiornamento utilizzando
AppUpdateInfo_getPriority():
int32_t priority = AppUpdateInfo_getPriority(info);
Avviare un aggiornamento
Dopo aver confermato che è disponibile un aggiornamento, puoi richiederlo utilizzando
AppUpdateManager_requestStartUpdate(). Prima di richiedere un aggiornamento, recupera
un oggetto AppUpdateInfo aggiornato e crea un oggetto AppUpdateOptions
per configurare il flusso di aggiornamento. Un oggetto AppUpdateOptions definisce le opzioni per un flusso di aggiornamento in-app, incluso se l'aggiornamento deve essere flessibile o immediato.
L'esempio seguente crea un oggetto AppUpdateOptions per un flusso di aggiornamento flessibile:
// Creates an AppUpdateOptions configuring a flexible in-app update flow.
AppUpdateOptions* options;
AppUpdateErrorCode error_code = AppUpdateOptions_createOptions(APP_UPDATE_TYPE_FLEXIBLE, &options);
L'esempio seguente crea un oggetto AppUpdateOptions per un flusso di aggiornamento immediato:
// Creates an AppUpdateOptions configuring an immediate in-app update flow.
AppUpdateOptions* options;
AppUpdateErrorCode error_code = AppUpdateOptions_createOptions(APP_UPDATE_TYPE_IMMEDIATE, &options);
L'oggetto AppUpdateOptions contiene anche un campo AllowAssetPackDeletion
che definisce se l'aggiornamento è autorizzato a cancellare i pacchetti di asset in caso di
spazio sul dispositivo limitato. Questo campo è impostato su false per impostazione predefinita, ma puoi utilizzare
il metodo AppUpdateOptions_setAssetPackDeletionAllowed() per impostarlo su
true invece:
bool allow = true;
AppUpdateErrorCode error_code = AppUpdateOptions_setAssetPackDeletionAllowed(options, allow);
Dopo aver recuperato un oggetto AppUpdateInfo aggiornato e un oggetto AppUpdateOptions configurato correttamente, chiama AppUpdateManager_requestStartUpdate() per richiedere in modo asincrono un flusso di aggiornamento, passando un oggetto jobject di attività Android per il parametro finale.
AppUpdateErrorCode request_error_code =
AppUpdateManager_requestStartUpdate(info, options, app->activity->clazz);
Per liberare risorse, rilascia le istanze di AppUpdateInfo e
AppUpdateOptions di cui non hai più bisogno chiamando
AppUpdateInfo_destroy() e AppUpdateOptions_destroy(),
rispettivamente.
AppUpdateInfo_destroy(info);
AppUpdateOptions_destroy(options);
Per un flusso di aggiornamento immediato, Google Play mostra una pagina di conferma dell'utente. Quando l'utente accetta la richiesta, Google Play scarica e installa automaticamente l'aggiornamento in primo piano, quindi riavvia l'app alla versione aggiornata se l'installazione va a buon fine.
Per un flusso di aggiornamento flessibile, puoi continuare a richiedere oggetti AppUpdateInfo
aggiornati per tenere traccia dello stato attuale dell'aggiornamento mentre l'utente continua a
interagire con l'app. Al termine del download, devi
attivare il completamento dell'aggiornamento chiamando
AppUpdateManager_requestCompleteUpdate(), come mostrato nell'esempio
seguente:
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.
}
}
Libera le risorse chiamando la AppUpdateManager_destroy() funzione
dopo che l'app ha terminato di utilizzare l'API.
Gestione degli errori
Questa sezione descrive le soluzioni per gli errori comuni indicati da valori specifici
AppUpdateErrorCode:
- Un codice di errore
-110, APP_UPDATE_INITIALIZATION_NEEDEDindica che l'API non è stata inizializzata correttamente. ChiamaAppUpdateManager_init()per inizializzare l'API. - Un codice di errore
-4, APP_UPDATE_INVALID_REQUESTindica che alcuni parametri della richiesta del flusso di aggiornamento non sono validi. Verifica che gli oggettiAppUpdateInfoeAppUpdateOptionsnon siano nulli e siano formattati correttamente. - Un codice di errore
-5, APP_UPDATE_UNAVAILABLEindica che non è disponibile alcun aggiornamento applicabile. Assicurati che la versione di destinazione abbia lo stesso nome del pacchetto, ID applicazione e chiave di firma. Se è disponibile un aggiornamento, svuota la cache dell'app e chiamaAppUpdateManager_requestAppUpdateInfo()di nuovo per aggiornareAppUpdateInfo. - Un codice di errore
-6, APP_UPDATE_NOT_ALLOWEDindica che il tipo di aggiornamento indicato dall'oggettoAppUpdateOptionnon è consentito. Prima di avviare il flusso di aggiornamento, verifica se l'oggettoAppUpdateInfoindica che il tipo di aggiornamento è consentito.
Passaggi successivi
Testa gli aggiornamenti in-app della tua app per verificare che l'integrazione funzioni correttamente.