Configura la pubblicazione on demand

I moduli delle funzionalità ti consentono di separare determinate funzionalità e risorse dal modulo di base della tua app e includerle nel tuo app bundle. Tramite Play Feature Delivery, gli utenti possono, ad esempio, scaricare e installare in un secondo momento questi componenti on demand dopo aver già installato l'APK di base della tua app.

Ad esempio, considera un'app di messaggistica che include funzionalità per acquisire e inviare messaggi con immagini, ma solo una piccola percentuale di utenti invia messaggi con immagini. Potrebbe essere opportuno includere la messaggistica con immagini come modulo delle funzionalità scaricabile. In questo modo, il download iniziale dell'app è più piccolo per tutti gli utenti e solo quelli che inviano messaggi con immagini devono scaricare questo componente aggiuntivo.

Tieni presente che questo tipo di modularizzazione richiede più impegno e possibilmente il refactoring del codice esistente della tua app, quindi valuta attentamente quali funzionalità della tua app trarrebbero il massimo vantaggio dall'essere disponibili per gli utenti su richiesta. Per comprendere meglio i casi d'uso e le linee guida ottimali per le funzionalità on demand, leggi le best practice per l'esperienza utente per la consegna on demand.

Se vuoi modularizzare gradualmente le funzionalità dell'app nel tempo, senza attivare opzioni di pubblicazione avanzate, come la pubblicazione on demand, configura la pubblicazione al momento dell'installazione.

Questa pagina ti aiuta ad aggiungere un modulo delle funzionalità al progetto dell'app e a configurarlo per la distribuzione on demand. Prima di iniziare, assicurati di utilizzare Android Studio 3.5 o versioni successive e il plug-in Android per Gradle 3.5.0 o versioni successive.

Configurare un nuovo modulo per la consegna on demand

Il modo più semplice per creare un nuovo modulo delle funzionalità è utilizzare Android Studio 3.5 o versioni successive. Poiché i moduli delle funzionalità hanno una dipendenza intrinseca dal modulo dell'app di base, puoi aggiungerli solo a progetti di app esistenti.

Per aggiungere un modulo di funzionalità al progetto dell'app utilizzando Android Studio, procedi nel seguente modo:

  1. Se non l'hai ancora fatto, apri il progetto dell'app nell'IDE.
  2. Seleziona File > Nuovo > Nuovo modulo dalla barra dei menu.
  3. Nella finestra di dialogo Crea nuovo modulo, seleziona Modulo di funzionalità dinamica e fai clic su Avanti.
  4. Nella sezione Configura il nuovo modulo, completa quanto segue:
    1. Seleziona il modulo dell'applicazione di base per il progetto dell'app dal menu a discesa.
    2. Specifica un nome del modulo. L'IDE utilizza questo nome per identificare il modulo come un sottoprogetto Gradle nel file delle impostazioni di Gradle. Quando crei il tuo app bundle, Gradle utilizza l'ultimo elemento del nome del sottoprogetto per inserire l'attributo <manifest split> nel manifest del modulo delle funzionalità.
    3. Specifica il nome del pacchetto del modulo. Per impostazione predefinita, Android Studio suggerisce un nome del pacchetto che combina il nome del pacchetto radice del modulo base e il nome del modulo specificato nel passaggio precedente.
    4. Seleziona il livello API minimo che vuoi che il modulo supporti. Questo valore deve corrispondere a quello del modulo base.
  5. Fai clic su Avanti.
  6. Nella sezione Opzioni di download dei moduli, completa quanto segue:

    1. Specifica il titolo del modulo utilizzando un massimo di 50 caratteri. La piattaforma utilizza questo titolo per identificare il modulo per gli utenti quando, ad esempio, conferma se l'utente vuole scaricare il modulo. Per questo motivo, il modulo di base dell'app deve includere il titolo del modulo come risorsa stringa, che puoi tradurre. Quando crei il modulo utilizzando Android Studio, l'IDE aggiunge la risorsa stringa al modulo di base e inserisce la seguente voce nel manifest del modulo di funzionalità:

      <dist:module
          ...
          dist:title="@string/feature_title">
      </dist:module>
      
    2. Nel menu a discesa sotto Inclusione al momento dell'installazione, seleziona Non includere il modulo al momento dell'installazione. Android Studio inserisce quanto segue nel manifest del modulo per riflettere la tua scelta:

      <dist:module ... >
        <dist:delivery>
            <dist:on-demand/>
        </dist:delivery>
      </dist:module>
      
    3. Seleziona la casella accanto a Unione se vuoi che questo modulo sia disponibile per i dispositivi con sistema operativo Android 4.4 (livello API 20) e versioni precedenti e incluso negli APK multipli. Ciò significa che puoi attivare il comportamento on demand per questo modulo e disattivare la fusione per ometterlo dai dispositivi che non supportano il download e l'installazione di APK suddivisi. Android Studio inserisce quanto segue nel manifest del modulo per riflettere la tua scelta:

      <dist:module ...>
          <dist:fusing dist:include="true | false" />
      </dist:module>
      
  7. Fai clic su Fine.

Dopo che Android Studio ha terminato la creazione del modulo, esamina i suoi contenuti dal riquadro Progetto (seleziona Visualizza > Finestre degli strumenti > Progetto dalla barra dei menu). Il codice, le risorse e l'organizzazione predefiniti devono essere simili a quelli del modulo dell'app standard.

Successivamente, dovrai implementare la funzionalità di installazione on demand utilizzando la libreria Play Feature Delivery.

Includere la libreria Play Feature Delivery nel progetto

Prima di iniziare, devi aggiungere la libreria Play Feature Delivery al tuo progetto.

Richiedere un modulo on demand

Quando la tua app deve utilizzare un modulo delle funzionalità, può richiederne uno mentre è in primo piano tramite la classe SplitInstallManager. Quando effettua una richiesta, l'app deve specificare il nome del modulo come definito dall'elemento split nel manifest del modulo di destinazione. Quando crei un modulo delle funzionalità utilizzando Android Studio, il sistema di build utilizza il nome del modulo che fornisci per inserire questa proprietà nel manifest del modulo in fase di compilazione. Per saperne di più, leggi informazioni sui manifest dei moduli delle funzionalità.

Ad esempio, considera un'app con un modulo on demand per acquisire e inviare messaggi con immagini utilizzando la fotocamera del dispositivo e questo modulo on demand specifica split="pictureMessages" nel relativo manifest. Il seguente esempio utilizza SplitInstallManager per richiedere il modulo pictureMessages (insieme a un modulo aggiuntivo per alcuni filtri promozionali):

Kotlin

// Creates an instance of SplitInstallManager.
val splitInstallManager = SplitInstallManagerFactory.create(context)

// Creates a request to install a module.
val request =
    SplitInstallRequest
        .newBuilder()
        // You can download multiple on demand modules per
        // request by invoking the following method for each
        // module you want to install.
        .addModule("pictureMessages")
        .addModule("promotionalFilters")
        .build()

splitInstallManager
    // Submits the request to install the module through the
    // asynchronous startInstall() task. Your app needs to be
    // in the foreground to submit the request.
    .startInstall(request)
    // You should also be able to gracefully handle
    // request state changes and errors. To learn more, go to
    // the section about how to Monitor the request state.
    .addOnSuccessListener { sessionId -> ... }
    .addOnFailureListener { exception ->  ... }

Java

// Creates an instance of SplitInstallManager.
SplitInstallManager splitInstallManager =
    SplitInstallManagerFactory.create(context);

// Creates a request to install a module.
SplitInstallRequest request =
    SplitInstallRequest
        .newBuilder()
        // You can download multiple on demand modules per
        // request by invoking the following method for each
        // module you want to install.
        .addModule("pictureMessages")
        .addModule("promotionalFilters")
        .build();

splitInstallManager
    // Submits the request to install the module through the
    // asynchronous startInstall() task. Your app needs to be
    // in the foreground to submit the request.
    .startInstall(request)
    // You should also be able to gracefully handle
    // request state changes and errors. To learn more, go to
    // the section about how to Monitor the request state.
    .addOnSuccessListener(sessionId -> { ... })
    .addOnFailureListener(exception -> { ... });

Quando la tua app richiede un modulo on demand, la libreria Play Feature Delivery utilizza una strategia "fire-and-forget". ovvero invia la richiesta di download del modulo alla piattaforma, ma non monitora se l'installazione è andata a buon fine. Per far avanzare il percorso dell'utente dopo l'installazione o gestire gli errori in modo controllato, assicurati di monitorare lo stato della richiesta.

Nota:è possibile richiedere un modulo funzionale già installato sul dispositivo. L'API considera immediatamente la richiesta come completata se rileva che il modulo è già installato. Inoltre, dopo l'installazione di un modulo, Google Play lo mantiene aggiornato automaticamente. ovvero, quando carichi una nuova versione dell'app bundle, la piattaforma aggiorna tutti gli APK installati che appartengono alla tua app. Per ulteriori informazioni, leggi Gestire gli aggiornamenti delle app.

Per accedere al codice e alle risorse del modulo, la tua app deve attivare SplitCompat. Tieni presente che SplitCompat non è richiesto per le app istantanee per Android.

Posticipare l'installazione dei moduli on demand

Se non hai bisogno che la tua app scarichi e installi immediatamente un modulo on demand, puoi posticipare l'installazione a quando l'app è in background. Ad esempio, se vuoi precaricare del materiale promozionale per il lancio successivo della tua app.

Puoi specificare un modulo da scaricare in un secondo momento utilizzando il metodo deferredInstall(), come mostrato di seguito. A differenza di SplitInstallManager.startInstall(), la tua app non deve essere in primo piano per avviare una richiesta di installazione posticipata.

Kotlin

// Requests an on demand module to be downloaded when the app enters
// the background. You can specify more than one module at a time.
splitInstallManager.deferredInstall(listOf("promotionalFilters"))

Java

// Requests an on demand module to be downloaded when the app enters
// the background. You can specify more than one module at a time.
splitInstallManager.deferredInstall(Arrays.asList("promotionalFilters"));

Le richieste di installazioni posticipate vengono elaborate secondo il criterio del "best effort" e non puoi monitorarne l'avanzamento. Pertanto, prima di provare ad accedere a un modulo specificato per l'installazione differita, devi verificare che il modulo sia stato installato. Se hai bisogno che il modulo sia disponibile immediatamente, utilizza SplitInstallManager.startInstall() per richiederlo, come mostrato nella sezione precedente.

Monitorare lo stato della richiesta

Per poter aggiornare una barra di avanzamento, attivare un intent dopo l'installazione o gestire correttamente un errore di richiesta, devi ascoltare gli aggiornamenti di stato dell'attività asincrona SplitInstallManager.startInstall(). Prima di poter iniziare a ricevere aggiornamenti per la tua richiesta di installazione, registra un listener e ottieni l'ID sessione per la richiesta, come mostrato di seguito.

Kotlin

// Initializes a variable to later track the session ID for a given request.
var mySessionId = 0

// Creates a listener for request status updates.
val listener = SplitInstallStateUpdatedListener { state ->
    if (state.sessionId() == mySessionId) {
      // Read the status of the request to handle the state update.
    }
}

// Registers the listener.
splitInstallManager.registerListener(listener)

...

splitInstallManager
    .startInstall(request)
    // When the platform accepts your request to download
    // an on demand module, it binds it to the following session ID.
    // You use this ID to track further status updates for the request.
    .addOnSuccessListener { sessionId -> mySessionId = sessionId }
    // You should also add the following listener to handle any errors
    // processing the request.
    .addOnFailureListener { exception ->
        // Handle request errors.
    }

// When your app no longer requires further updates, unregister the listener.
splitInstallManager.unregisterListener(listener)

Java

// Initializes a variable to later track the session ID for a given request.
int mySessionId = 0;

// Creates a listener for request status updates.
SplitInstallStateUpdatedListener listener = state -> {
    if (state.sessionId() == mySessionId) {
      // Read the status of the request to handle the state update.
    }
};

// Registers the listener.
splitInstallManager.registerListener(listener);

...

splitInstallManager
    .startInstall(request)
    // When the platform accepts your request to download
    // an on demand module, it binds it to the following session ID.
    // You use this ID to track further status updates for the request.
    .addOnSuccessListener(sessionId -> { mySessionId = sessionId; })
    // You should also add the following listener to handle any errors
    // processing the request.
    .addOnFailureListener(exception -> {
        // Handle request errors.
    });

// When your app no longer requires further updates, unregister the listener.
splitInstallManager.unregisterListener(listener);

Gestire gli errori delle richieste

Tieni presente che l'installazione on demand dei moduli delle funzionalità a volte può non riuscire, proprio come l'installazione dell'app non sempre va a buon fine. L'installazione non riuscita può essere dovuta a problemi come spazio di archiviazione del dispositivo insufficiente, assenza di connettività di rete o mancato accesso dell'utente al Google Play Store. Per suggerimenti su come gestire queste situazioni in modo ottimale dal punto di vista dell'utente, consulta le nostre linee guida UX per la consegna on demand.

A livello di codice, devi gestire gli errori di download o installazione di un modulo utilizzando addOnFailureListener(), come mostrato di seguito:

Kotlin

splitInstallManager
    .startInstall(request)
    .addOnFailureListener { exception ->
        when ((exception as SplitInstallException).errorCode) {
            SplitInstallErrorCode.NETWORK_ERROR -> {
                // Display a message that requests the user to establish a
                // network connection.
            }
            SplitInstallErrorCode.ACTIVE_SESSIONS_LIMIT_EXCEEDED -> checkForActiveDownloads()
            ...
        }
    }

fun checkForActiveDownloads() {
    splitInstallManager
        // Returns a SplitInstallSessionState object for each active session as a List.
        .sessionStates
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                // Check for active sessions.
                for (state in task.result) {
                    if (state.status() == SplitInstallSessionStatus.DOWNLOADING) {
                        // Cancel the request, or request a deferred installation.
                    }
                }
            }
        }
}

Java

splitInstallManager
    .startInstall(request)
    .addOnFailureListener(exception -> {
        switch (((SplitInstallException) exception).getErrorCode()) {
            case SplitInstallErrorCode.NETWORK_ERROR:
                // Display a message that requests the user to establish a
                // network connection.
                break;
            case SplitInstallErrorCode.ACTIVE_SESSIONS_LIMIT_EXCEEDED:
                checkForActiveDownloads();
            ...
    });

void checkForActiveDownloads() {
    splitInstallManager
        // Returns a SplitInstallSessionState object for each active session as a List.
        .getSessionStates()
        .addOnCompleteListener( task -> {
            if (task.isSuccessful()) {
                // Check for active sessions.
                for (SplitInstallSessionState state : task.getResult()) {
                    if (state.status() == SplitInstallSessionStatus.DOWNLOADING) {
                        // Cancel the request, or request a deferred installation.
                    }
                }
            }
        });
}

La tabella seguente descrive gli stati di errore che la tua app potrebbe dover gestire:

Codice di errore Descrizione Azione suggerita
ACTIVE_SESSIONS_LIMIT_EXCEEDED La richiesta viene rifiutata perché esiste almeno una richiesta esistente attualmente in download. Controlla se sono presenti richieste ancora in fase di download, come mostrato nell'esempio precedente.
MODULE_UNAVAILABLE Google Play non riesce a trovare il modulo richiesto in base alla versione installata corrente dell'app, del dispositivo e dell'account Google Play dell'utente. Se l'utente non ha accesso al modulo, inviagli una notifica.
INVALID_REQUEST Google Play ha ricevuto la richiesta, ma non è valida. Verifica che le informazioni incluse nella richiesta siano complete e accurate.
SESSION_NOT_FOUND Non è stata trovata alcuna sessione per un determinato ID sessione. Se stai cercando di monitorare lo stato di una richiesta in base al relativo ID sessione, assicurati che l'ID sessione sia corretto.
API_NOT_AVAILABLE La libreria Play Feature Delivery non è supportata sul dispositivo attuale. ovvero il dispositivo non è in grado di scaricare e installare funzionalità on demand. Per i dispositivi con Android 4.4 (livello API 20) o versioni precedenti, devi includere i moduli delle funzionalità al momento dell'installazione utilizzando la proprietà manifest dist:fusing. Per saperne di più, leggi informazioni sul manifest del modulo di funzionalità.
NETWORK_ERROR La richiesta non è andata a buon fine a causa di un errore di rete. Chiedi all'utente di stabilire una connessione di rete o di passare a un'altra rete.
ACCESS_DENIED L'app non è in grado di registrare la richiesta a causa di autorizzazioni insufficienti. Ciò si verifica in genere quando l'app è in background. Prova a effettuare la richiesta quando l'app torna in primo piano.
INCOMPATIBLE_WITH_EXISTING_SESSION La richiesta contiene uno o più moduli che sono già stati richiesti ma non sono ancora stati installati. Crea una nuova richiesta che non includa moduli già richiesti dalla tua app oppure attendi il completamento dell'installazione di tutti i moduli attualmente richiesti prima di riprovare a inviare la richiesta.

Tieni presente che la richiesta di un modulo già installato non comporta un errore.

SERVICE_DIED Il servizio responsabile della gestione della richiesta non è più attivo. Riprova a inviare la richiesta.

Il tuo SplitInstallStateUpdatedListener riceve un SplitInstallSessionState con questo codice di errore, stato FAILED e ID sessione -1.

INSUFFICIENT_STORAGE Il dispositivo non dispone di spazio di archiviazione libero sufficiente per installare il modulo della funzionalità. Informa l'utente che non ha spazio di archiviazione sufficiente per installare questa funzionalità.
SPLITCOMPAT_VERIFICATION_ERROR, SPLITCOMPAT_EMULATION_ERROR, SPLITCOMPAT_COPY_ERROR SplitCompat non è riuscito a caricare il modulo delle funzionalità. Questi errori dovrebbero risolversi automaticamente dopo il successivo riavvio dell'app.
PLAY_STORE_NOT_FOUND L'app Play Store non è installata sul dispositivo. Comunica all'utente che per scaricare questa funzionalità è necessaria l'app Play Store.
APP_NOT_OWNED L'app non è stata installata da Google Play e la funzionalità non può essere scaricata. Questo errore può verificarsi solo per le installazioni posticipate. Se vuoi che l'utente acquisisca l'app su Google Play, utilizza startInstall(), che può ottenere la conferma dell'utente necessaria.
INTERNAL_ERROR Si è verificato un errore interno in Play Store. Riprova a inviare la richiesta.

Se un utente richiede il download di un modulo on demand e si verifica un errore, valuta la possibilità di mostrare una finestra di dialogo che offre due opzioni all'utente: Riprova (che tenta di nuovo la richiesta) e Annulla (che abbandona la richiesta). Per ulteriore supporto, devi fornire anche un link alla Guida che indirizzi gli utenti al Centro assistenza Google Play.

Gestire gli aggiornamenti di stato

Dopo aver registrato un listener e registrato l'ID sessione per la richiesta, utilizza StateUpdatedListener.onStateUpdate() per gestire le modifiche dello stato, come mostrato di seguito.

Kotlin

override fun onStateUpdate(state : SplitInstallSessionState) {
    if (state.status() == SplitInstallSessionStatus.FAILED
        && state.errorCode() == SplitInstallErrorCode.SERVICE_DIED) {
       // Retry the request.
       return
    }
    if (state.sessionId() == mySessionId) {
        when (state.status()) {
            SplitInstallSessionStatus.DOWNLOADING -> {
              val totalBytes = state.totalBytesToDownload()
              val progress = state.bytesDownloaded()
              // Update progress bar.
            }
            SplitInstallSessionStatus.INSTALLED -> {

              // After a module is installed, you can start accessing its content or
              // fire an intent to start an activity in the installed module.
              // For other use cases, see access code and resources from installed modules.

              // If the request is an on demand module for an Android Instant App
              // running on Android 8.0 (API level 26) or higher, you need to
              // update the app context using the SplitInstallHelper API.
            }
        }
    }
}

Java

@Override
public void onStateUpdate(SplitInstallSessionState state) {
    if (state.status() == SplitInstallSessionStatus.FAILED
        && state.errorCode() == SplitInstallErrorCode.SERVICE_DIES) {
       // Retry the request.
       return;
    }
    if (state.sessionId() == mySessionId) {
        switch (state.status()) {
            case SplitInstallSessionStatus.DOWNLOADING:
              int totalBytes = state.totalBytesToDownload();
              int progress = state.bytesDownloaded();
              // Update progress bar.
              break;

            case SplitInstallSessionStatus.INSTALLED:

              // After a module is installed, you can start accessing its content or
              // fire an intent to start an activity in the installed module.
              // For other use cases, see access code and resources from installed modules.

              // If the request is an on demand module for an Android Instant App
              // running on Android 8.0 (API level 26) or higher, you need to
              // update the app context using the SplitInstallHelper API.
        }
    }
}

Gli stati possibili della richiesta di installazione sono descritti nella tabella seguente.

Stato richiesta Descrizione Azione suggerita
IN ATTESA La richiesta è stata accettata e il download dovrebbe iniziare a breve. Inizializza i componenti della UI, ad esempio una barra di avanzamento, per fornire all'utente un feedback sul download.
REQUIRES_USER_CONFIRMATION Il download richiede la conferma dell'utente. Questo stato si verifica più comunemente se l'app non è stata installata tramite Google Play. Chiedi all'utente di confermare il download della funzionalità tramite Google Play. Per saperne di più, vai alla sezione su come ottenere la conferma dell'utente.
DOWNLOAD Il download è in corso. Se fornisci una barra di avanzamento per il download, utilizza i metodi SplitInstallSessionState.bytesDownloaded() e SplitInstallSessionState.totalBytesToDownload() per aggiornare la UI (vedi l'esempio di codice sopra questa tabella).
SCARICATO Il dispositivo ha scaricato il modulo, ma l'installazione non è ancora iniziata. Le app devono attivare SplitCompat per accedere ai moduli scaricati ed evitare di visualizzare questo stato. Questo è necessario per accedere al codice e alle risorse del modulo delle funzionalità.
INSTALLAZIONE Il dispositivo sta installando il modulo. Aggiorna la barra di avanzamento. Questo stato è in genere breve.
INSTALLATA Il modulo è installato sul dispositivo. Codice di accesso e risorsa nel modulo per continuare il percorso dell'utente.

Se il modulo è per un'app istantanea Android in esecuzione su Android 8.0 (livello API 26) o versioni successive, devi utilizzare splitInstallHelper per aggiornare i componenti dell'app con il nuovo modulo.

OPERAZIONE NON RIUSCITA La richiesta non è andata a buon fine prima che il modulo fosse installato sul dispositivo. Chiedere all'utente di riprovare a effettuare la richiesta o di annullarla.
ANNULLAMENTO IN CORSO Il dispositivo sta annullando la richiesta. Per saperne di più, vai alla sezione su come annullare una richiesta di installazione.
CANCELLATO La richiesta è stata annullata.

Ottenere la conferma dell'utente

In alcuni casi, Google Play potrebbe richiedere la conferma dell'utente prima di soddisfare una richiesta di download. Ad esempio, se la tua app non è stata installata da Google Play o se stai tentando un download di grandi dimensioni tramite i dati mobili. In questi casi, lo stato della richiesta indica REQUIRES_USER_CONFIRMATION e la tua app deve ottenere la conferma dell'utente prima che il dispositivo possa scaricare e installare i moduli nella richiesta. Per ottenere la conferma, la tua app deve chiedere all'utente quanto segue:

Kotlin

override fun onSessionStateUpdate(state: SplitInstallSessionState) {
    if (state.status() == SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION) {
        // Displays a confirmation for the user to confirm the request.
        splitInstallManager.startConfirmationDialogForResult(
          state,
          // an activity result launcher registered via registerForActivityResult
          activityResultLauncher)
    }
    ...
 }

Java

@Override void onSessionStateUpdate(SplitInstallSessionState state) {
    if (state.status() == SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION) {
        // Displays a confirmation for the user to confirm the request.
        splitInstallManager.startConfirmationDialogForResult(
          state,
          // an activity result launcher registered via registerForActivityResult
          activityResultLauncher);
    }
    ...
 }

Puoi registrare un launcher di risultati di attività utilizzando il contratto ActivityResultContracts.StartIntentSenderForResult integrato. Consulta API Activity Result.

Lo stato della richiesta viene aggiornato in base alla risposta dell'utente:

  • Se l'utente accetta la conferma, lo stato della richiesta cambia in PENDING e il download procede.
  • Se l'utente rifiuta la conferma, lo stato della richiesta cambia in CANCELED.
  • Se l'utente non effettua una selezione prima che la finestra di dialogo venga chiusa, lo stato della richiesta rimane REQUIRES_USER_CONFIRMATION. La tua app può chiedere di nuovo all'utente di completare la richiesta.

Per ricevere una richiamata con la risposta dell'utente, puoi eseguire l'override di ActivityResultCallback come mostrato di seguito.

Kotlin

registerForActivityResult(StartIntentSenderForResult()) { result: ActivityResult -> {
        // Handle the user's decision. For example, if the user selects "Cancel",
        // you may want to disable certain functionality that depends on the module.
    }
}

Java

registerForActivityResult(
    new ActivityResultContracts.StartIntentSenderForResult(),
    new ActivityResultCallback<ActivityResult>() {
        @Override
        public void onActivityResult(ActivityResult result) {
            // Handle the user's decision. For example, if the user selects "Cancel",
            // you may want to disable certain functionality that depends on the module.
        }
    });

Annullare una richiesta di installazione

Se la tua app deve annullare una richiesta prima dell'installazione, può richiamare il metodo cancelInstall() utilizzando l'ID sessione della richiesta, come mostrato di seguito.

Kotlin

splitInstallManager
    // Cancels the request for the given session ID.
    .cancelInstall(mySessionId)

Java

splitInstallManager
    // Cancels the request for the given session ID.
    .cancelInstall(mySessionId);

Moduli di accesso

Per accedere al codice e alle risorse di un modulo scaricato dopo il download, la tua app deve attivare la libreria SplitCompat sia per la tua app sia per ogni attività nei moduli delle funzionalità che la tua app scarica.

Tuttavia, devi tenere presente che la piattaforma presenta le seguenti limitazioni all'accesso ai contenuti di un modulo per un determinato periodo di tempo (giorni, in alcuni casi) dopo il download del modulo:

  • La piattaforma non può applicare nuove voci del manifest introdotte dal modulo.
  • La piattaforma non può accedere alle risorse del modulo per i componenti dell'interfaccia utente di sistema, come le notifiche. Se devi utilizzare immediatamente queste risorse, valuta la possibilità di includerle nel modulo base della tua app.

Attiva SplitCompat

Affinché la tua app possa accedere al codice e alle risorse di un modulo scaricato, devi attivare SplitCompat utilizzando solo uno dei metodi descritti nelle sezioni seguenti.

Dopo aver attivato SplitCompat per la tua app, devi anche attivare SplitCompat per ogni attività nei moduli delle funzionalità a cui vuoi che la tua app abbia accesso.

Dichiarare SplitCompatApplication nel manifest

Il modo più semplice per attivare SplitCompat è dichiarare SplitCompatApplication come sottoclasse di Application nel manifest della tua app, come mostrato di seguito:

<application
    ...
    android:name="com.google.android.play.core.splitcompat.SplitCompatApplication">
</application>

Dopo l'installazione dell'app su un dispositivo, puoi accedere automaticamente al codice e alle risorse dei moduli delle funzionalità scaricati.

Richiamare SplitCompat in fase di runtime

Puoi anche attivare SplitCompat in attività o servizi specifici in fase di runtime. L'attivazione di SplitCompat in questo modo è necessaria per avviare le attività incluse nei moduli delle funzionalità. Per farlo, esegui l'override di attachBaseContext come mostrato di seguito.

Se hai una classe Application personalizzata, fai in modo che estenda SplitCompatApplication per attivare SplitCompat per la tua app, come mostrato di seguito:

Kotlin

class MyApplication : SplitCompatApplication() {
    ...
}

Java

public class MyApplication extends SplitCompatApplication {
    ...
}

SplitCompatApplication esegue semplicemente l'override di ContextWrapper.attachBaseContext() per includere SplitCompat.install(Context applicationContext). Se non vuoi che il tuo corso Application si estenda SplitCompatApplication, puoi ignorare il metodo attachBaseContext() manualmente, come segue:

Kotlin

override fun attachBaseContext(base: Context) {
    super.attachBaseContext(base)
    // Emulates installation of future on demand modules using SplitCompat.
    SplitCompat.install(this)
}

Java

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    // Emulates installation of future on demand modules using SplitCompat.
    SplitCompat.install(this);
}

Se il tuo modulo on demand è compatibile sia con le app istantanee sia con le app installate, puoi richiamare SplitCompat in modo condizionale, come segue:

Kotlin

override fun attachBaseContext(base: Context) {
    super.attachBaseContext(base)
    if (!InstantApps.isInstantApp(this)) {
        SplitCompat.install(this)
    }
}

Java

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    if (!InstantApps.isInstantApp(this)) {
        SplitCompat.install(this);
    }
}

Attivare SplitCompat per le attività del modulo

Dopo aver attivato SplitCompat per l'app di base, devi attivarlo per ogni attività che l'app scarica in un modulo delle funzionalità. Per farlo, utilizza il metodo SplitCompat.installActivity() come segue:

Kotlin

override fun attachBaseContext(base: Context) {
    super.attachBaseContext(base)
    // Emulates installation of on demand modules using SplitCompat.
    SplitCompat.installActivity(this)
}

Java

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    // Emulates installation of on demand modules using SplitCompat.
    SplitCompat.installActivity(this);
}

Componenti di accesso definiti nei moduli delle funzionalità

Avviare un'attività definita in un modulo delle funzionalità

Puoi avviare le attività definite nei moduli delle funzionalità utilizzando startActivity() dopo aver attivato SplitCompat.

Kotlin

startActivity(Intent()
  .setClassName("com.package", "com.package.module.MyActivity")
  .setFlags(...))

Java

startActivity(new Intent()
  .setClassName("com.package", "com.package.module.MyActivity")
  .setFlags(...));

Il primo parametro di setClassName è il nome del pacchetto dell'app, mentre il secondo è il nome completo della classe dell'attività.

Quando hai un'attività in un modulo delle funzionalità scaricato on demand, devi abilitare SplitCompat nell'attività.

Avvia un servizio definito in un modulo della funzionalità

Puoi avviare i servizi definiti nei moduli delle funzionalità utilizzando startService() dopo aver attivato SplitCompat.

Kotlin

startService(Intent()
  .setClassName("com.package", "com.package.module.MyService")
  .setFlags(...))

Java

startService(new Intent()
  .setClassName("com.package", "com.package.module.MyService")
  .setFlags(...));

Esportare un componente definito in un modulo delle funzionalità

Non devi includere i componenti Android esportati all'interno dei moduli opzionali.

Il sistema di build unisce le voci del manifest di tutti i moduli nel modulo base. Se un modulo opzionale contiene un componente esportato, questo sarà accessibile anche prima dell'installazione del modulo e può causare un arresto anomalo a causa del codice mancante quando viene richiamato da un'altra app.

Questo non è un problema per i componenti interni, a cui si accede solo tramite l'app, quindi l'app può verificare che il modulo sia installato prima di accedere al componente.

Se hai bisogno di un componente esportato e vuoi che i suoi contenuti si trovino in un modulo opzionale, valuta l'implementazione di un pattern proxy. Puoi farlo aggiungendo un componente proxy esportato nella base; quando viene eseguito l'accesso, il componente proxy può verificare la presenza del modulo che contiene i contenuti. Se il modulo è presente, il componente proxy può avviare il componente interno dal modulo tramite un Intent, trasmettendo l'intent dall'app chiamante. Se il modulo non è presente, il componente può scaricare il modulo o restituire un messaggio di errore appropriato all'app chiamante.

Accedere al codice e alle risorse dai moduli installati

Se attivi SplitCompat per il contesto dell'applicazione di base e le attività nel modulo delle funzionalità, puoi utilizzare il codice e le risorse di un modulo delle funzionalità come se facessero parte dell'APK di base, una volta installato il modulo facoltativo.

Codice di accesso di un altro modulo

Accedere al codice di base da un modulo

Il codice all'interno del modulo base può essere utilizzato direttamente da altri moduli. Non devi fare nulla di speciale, ti basta importare e utilizzare le classi che ti servono.

Accedere al codice di un modulo da un altro modulo

Non è possibile accedere staticamente a un oggetto o a una classe all'interno di un modulo direttamente da un altro modulo, ma è possibile accedervi indirettamente utilizzando la reflection.

Devi fare attenzione alla frequenza con cui si verifica questo problema, a causa dei costi di rendimento della riflessione. Per i casi d'uso complessi, utilizza framework di iniezione delle dipendenze come Dagger 2 per garantire una singola chiamata di reflection per la durata dell'applicazione.

Per semplificare le interazioni con l'oggetto dopo l'istanza, è consigliabile definire un'interfaccia nel modulo di base e la relativa implementazione nel modulo delle funzionalità. Ad esempio:

Kotlin

// In the base module
interface MyInterface {
  fun hello(): String
}

// In the feature module
object MyInterfaceImpl : MyInterface {
  override fun hello() = "Hello"
}

// In the base module, where we want to access the feature module code
val stringFromModule = (Class.forName("com.package.module.MyInterfaceImpl")
    .kotlin.objectInstance as MyInterface).hello();

Java

// In the base module
public interface MyInterface {
  String hello();
}

// In the feature module
public class MyInterfaceImpl implements MyInterface {
  @Override
  public String hello() {
    return "Hello";
  }
}

// In the base module, where we want to access the feature module code
String stringFromModule =
   ((MyInterface) Class.forName("com.package.module.MyInterfaceImpl").getConstructor().newInstance()).hello();

Accedere a risorse e asset da un modulo diverso

Una volta installato un modulo, puoi accedere alle risorse e agli asset al suo interno nel modo standard, con due avvertenze:

  • Se accedi a una risorsa da un modulo diverso, il modulo non avrà accesso all'identificatore della risorsa, anche se è comunque possibile accedervi per nome. Tieni presente che il pacchetto da utilizzare per fare riferimento alla risorsa è il pacchetto del modulo in cui è definita la risorsa.
  • Se vuoi accedere ad asset o risorse che si trovano in un modulo appena installato da un altro modulo installato della tua app, devi farlo utilizzando il contesto dell'applicazione. Il contesto del componente che sta tentando di accedere alle risorse non verrà ancora aggiornato. In alternativa, puoi ricreare il componente (ad esempio chiamando Activity.recreate()) o reinstallare SplitCompat dopo l'installazione del modulo della funzionalità.

Caricare il codice nativo in un'app utilizzando la distribuzione on demand

Ti consigliamo di utilizzare ReLinker per caricare tutte le tue librerie native quando utilizzi la distribuzione on demand dei moduli delle funzionalità. ReLinker risolve un problema di caricamento delle librerie native dopo l'installazione di un modulo delle funzionalità. Puoi scoprire di più su ReLinker nei suggerimenti JNI di Android.

Carica il codice nativo da un modulo facoltativo

Una volta installata una suddivisione, ti consigliamo di caricare il relativo codice nativo tramite ReLinker. Per le app istantanee devi utilizzare questo metodo speciale.

Se utilizzi System.loadLibrary() per caricare il codice nativo e la tua libreria nativa ha una dipendenza da un'altra libreria nel modulo, devi caricare manualmente prima l'altra libreria. Se utilizzi ReLinker, l'operazione equivalente è Relinker.recursively().loadLibrary().

Se utilizzi dlopen() nel codice nativo per caricare una libreria definita in un modulo opzionale, non funzionerà con i percorsi relativi delle librerie. La soluzione migliore è recuperare il percorso assoluto della libreria dal codice Java tramite ClassLoader.findLibrary() e poi utilizzarlo nella chiamata dlopen(). Esegui questa operazione prima di inserire il codice nativo o utilizza una chiamata JNI dal codice nativo a Java.

Accedere alle app istantanee Android installate

Dopo che un modulo di app istantanea per Android viene segnalato come INSTALLED, puoi accedere al relativo codice e alle relative risorse utilizzando un contesto dell'app aggiornato. Un contesto creato dall'app prima di installare un modulo (ad esempio, uno già memorizzato in una variabile) non contiene i contenuti del nuovo modulo. ma un contesto aggiornato sì. Questo può essere ottenuto, ad esempio, utilizzando createPackageContext.

Kotlin

// Generate a new context as soon as a request for a new module
// reports as INSTALLED.
override fun onStateUpdate(state: SplitInstallSessionState ) {
    if (state.sessionId() == mySessionId) {
        when (state.status()) {
            ...
            SplitInstallSessionStatus.INSTALLED -> {
                val newContext = context.createPackageContext(context.packageName, 0)
                // If you use AssetManager to access your app’s raw asset files, you’ll need
                // to generate a new AssetManager instance from the updated context.
                val am = newContext.assets
            }
        }
    }
}

Java

// Generate a new context as soon as a request for a new module
// reports as INSTALLED.
@Override
public void onStateUpdate(SplitInstallSessionState state) {
    if (state.sessionId() == mySessionId) {
        switch (state.status()) {
            ...
            case SplitInstallSessionStatus.INSTALLED:
                Context newContext = context.createPackageContext(context.getPackageName(), 0);
                // If you use AssetManager to access your app’s raw asset files, you’ll need
                // to generate a new AssetManager instance from the updated context.
                AssetManager am = newContext.getAssets();
        }
    }
}

Android Instant Apps su Android 8.0 e versioni successive

Quando richiedi un modulo on demand per un'app istantanea Android su Android 8.0 (livello API 26) e versioni successive, dopo che una richiesta di installazione viene segnalata come INSTALLED, devi aggiornare l'app con il contesto del nuovo modulo tramite una chiamata a SplitInstallHelper.updateAppInfo(Context context). In caso contrario, l'app non è ancora a conoscenza del codice e delle risorse del modulo. Dopo aver aggiornato i metadati dell'app, devi caricare i contenuti del modulo durante il successivo evento del thread principale richiamando un nuovo Handler, come mostrato di seguito:

Kotlin

override fun onStateUpdate(state: SplitInstallSessionState ) {
    if (state.sessionId() == mySessionId) {
        when (state.status()) {
            ...
            SplitInstallSessionStatus.INSTALLED -> {
                // You need to perform the following only for Android Instant Apps
                // running on Android 8.0 (API level 26) and higher.
                if (BuildCompat.isAtLeastO()) {
                    // Updates the app’s context with the code and resources of the
                    // installed module.
                    SplitInstallHelper.updateAppInfo(context)
                    Handler().post {
                        // Loads contents from the module using AssetManager
                        val am = context.assets
                        ...
                    }
                }
            }
        }
    }
}

Java

@Override
public void onStateUpdate(SplitInstallSessionState state) {
    if (state.sessionId() == mySessionId) {
        switch (state.status()) {
            ...
            case SplitInstallSessionStatus.INSTALLED:
            // You need to perform the following only for Android Instant Apps
            // running on Android 8.0 (API level 26) and higher.
            if (BuildCompat.isAtLeastO()) {
                // Updates the app’s context with the code and resources of the
                // installed module.
                SplitInstallHelper.updateAppInfo(context);
                new Handler().post(new Runnable() {
                    @Override public void run() {
                        // Loads contents from the module using AssetManager
                        AssetManager am = context.getAssets();
                        ...
                    }
                });
            }
        }
    }
}

Caricare librerie C/C++

Se vuoi caricare librerie C/C++ da un modulo che il dispositivo ha già scaricato in un'app istantanea, utilizza SplitInstallHelper.loadLibrary(Context context, String libName), come mostrato di seguito:

Kotlin

override fun onStateUpdate(state: SplitInstallSessionState) {
    if (state.sessionId() == mySessionId) {
        when (state.status()) {
            SplitInstallSessionStatus.INSTALLED -> {
                // Updates the app’s context as soon as a module is installed.
                val newContext = context.createPackageContext(context.packageName, 0)
                // To load C/C++ libraries from an installed module, use the following API
                // instead of System.load().
                SplitInstallHelper.loadLibrary(newContext, my-cpp-lib)
                ...
            }
        }
    }
}

Java

public void onStateUpdate(SplitInstallSessionState state) {
    if (state.sessionId() == mySessionId) {
        switch (state.status()) {
            case SplitInstallSessionStatus.INSTALLED:
                // Updates the app’s context as soon as a module is installed.
                Context newContext = context.createPackageContext(context.getPackageName(), 0);
                // To load C/C++ libraries from an installed module, use the following API
                // instead of System.load().
                SplitInstallHelper.loadLibrary(newContext, my-cpp-lib);
                ...
        }
    }
}

Limitazioni note

  • Non è possibile utilizzare Android WebView in un'attività che accede a risorse o asset da un modulo opzionale. Ciò è dovuto a un'incompatibilità tra WebView e SplitCompat nel livello API Android 28 e precedenti.
  • Non puoi memorizzare nella cache gli oggetti ApplicationInfo di Android, i relativi contenuti o gli oggetti che li contengono all'interno della tua app. Devi sempre recuperare questi oggetti in base alle necessità da un contesto dell'app. La memorizzazione nella cache di questi oggetti potrebbe causare l'arresto anomalo dell'app durante l'installazione di un modulo delle funzionalità.

Gestire i moduli installati

Per controllare quali moduli delle funzionalità sono attualmente installati sul dispositivo, puoi chiamare SplitInstallManager.getInstalledModules(), che restituisce un Set<String> dei nomi dei moduli installati, come mostrato di seguito.

Kotlin

val installedModules: Set<String> = splitInstallManager.installedModules

Java

Set<String> installedModules = splitInstallManager.getInstalledModules();

Disinstallare moduli

Puoi richiedere al dispositivo di disinstallare i moduli richiamando SplitInstallManager.deferredUninstall(List<String> moduleNames), come mostrato di seguito.

Kotlin

// Specifies two feature modules for deferred uninstall.
splitInstallManager.deferredUninstall(listOf("pictureMessages", "promotionalFilters"))

Java

// Specifies two feature modules for deferred uninstall.
splitInstallManager.deferredUninstall(Arrays.asList("pictureMessages", "promotionalFilters"));

Le disinstallazioni dei moduli non avvengono immediatamente. ovvero il dispositivo le disinstalla in background in base alle necessità per risparmiare spazio di archiviazione. Puoi verificare che il dispositivo abbia eliminato un modulo richiamando SplitInstallManager.getInstalledModules() e controllando il risultato, come descritto nella sezione precedente.

Scaricare risorse linguistiche aggiuntive

Con gli app bundle, i dispositivi scaricano solo il codice e le risorse necessari per eseguire l'app. Pertanto, per le risorse linguistiche, il dispositivo di un utente scarica solo le risorse linguistiche dell'app che corrispondono a una o più lingue attualmente selezionate nelle impostazioni del dispositivo.

Se vuoi che la tua app abbia accesso a risorse linguistiche aggiuntive, ad esempio per implementare un selettore lingua in-app, puoi utilizzare la libreria Play Feature Delivery per scaricarle on demand. La procedura è simile a quella di download di un modulo delle funzionalità, come mostrato di seguito.

Kotlin

// Captures the user’s preferred language and persists it
// through the app’s SharedPreferences.
sharedPrefs.edit().putString(LANGUAGE_SELECTION, "fr").apply()
...

// Creates a request to download and install additional language resources.
val request = SplitInstallRequest.newBuilder()
        // Uses the addLanguage() method to include French language resources in the request.
        // Note that country codes are ignored. That is, if your app
        // includes resources for “fr-FR” and “fr-CA”, resources for both
        // country codes are downloaded when requesting resources for "fr".
        .addLanguage(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
        .build()

// Submits the request to install the additional language resources.
splitInstallManager.startInstall(request)

Java

// Captures the user’s preferred language and persists it
// through the app’s SharedPreferences.
sharedPrefs.edit().putString(LANGUAGE_SELECTION, "fr").apply();
...

// Creates a request to download and install additional language resources.
SplitInstallRequest request =
    SplitInstallRequest.newBuilder()
        // Uses the addLanguage() method to include French language resources in the request.
        // Note that country codes are ignored. That is, if your app
        // includes resources for “fr-FR” and “fr-CA”, resources for both
        // country codes are downloaded when requesting resources for "fr".
        .addLanguage(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
        .build();

// Submits the request to install the additional language resources.
splitInstallManager.startInstall(request);

La richiesta viene gestita come se fosse una richiesta di un modulo delle funzionalità. ovvero puoi monitorare lo stato della richiesta come faresti normalmente.

Se la tua app non richiede immediatamente le risorse linguistiche aggiuntive, puoi posticipare l'installazione a quando l'app è in background, come mostrato di seguito.

Kotlin

splitInstallManager.deferredLanguageInstall(
    Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))

Java

splitInstallManager.deferredLanguageInstall(
    Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)));

Accedere alle risorse linguistiche scaricate

Per accedere alle risorse della lingua scaricate, la tua app deve eseguire il metodo SplitCompat.installActivity() all'interno del metodo attachBaseContext() di ogni attività che richiede l'accesso a queste risorse, come mostrato di seguito.

Kotlin

override fun attachBaseContext(base: Context) {
  super.attachBaseContext(base)
  SplitCompat.installActivity(this)
}

Java

@Override
protected void attachBaseContext(Context base) {
  super.attachBaseContext(base);
  SplitCompat.installActivity(this);
}

Per ogni attività per cui vuoi utilizzare le risorse della lingua scaricate dalla tua app, aggiorna il contesto di base e imposta una nuova impostazione internazionale tramite il relativo Configuration:

Kotlin

override fun attachBaseContext(base: Context) {
  val configuration = Configuration()
  configuration.setLocale(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
  val context = base.createConfigurationContext(configuration)
  super.attachBaseContext(context)
  SplitCompat.install(this)
}

Java

@Override
protected void attachBaseContext(Context base) {
  Configuration configuration = new Configuration();
  configuration.setLocale(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)));
  Context context = base.createConfigurationContext(configuration);
  super.attachBaseContext(context);
  SplitCompat.install(this);
}

Affinché queste modifiche abbiano effetto, devi ricreare la tua attività dopo che la nuova lingua è stata installata e pronta per l'uso. Puoi utilizzare il metodo Activity#recreate().

Kotlin

when (state.status()) {
  SplitInstallSessionStatus.INSTALLED -> {
      // Recreates the activity to load resources for the new language
      // preference.
      activity.recreate()
  }
  ...
}

Java

switch (state.status()) {
  case SplitInstallSessionStatus.INSTALLED:
      // Recreates the activity to load resources for the new language
      // preference.
      activity.recreate();
  ...
}

Disinstallare risorse linguistiche aggiuntive

Come per i moduli delle funzionalità, puoi disinstallare le risorse aggiuntive in qualsiasi momento. Prima di richiedere una disinstallazione, ti consigliamo di determinare quali lingue sono attualmente installate, come segue.

Kotlin

val installedLanguages: Set<String> = splitInstallManager.installedLanguages

Java

Set<String> installedLanguages = splitInstallManager.getInstalledLanguages();

Puoi quindi decidere quali lingue disinstallare utilizzando il metodo deferredLanguageUninstall(), come mostrato di seguito.

Kotlin

splitInstallManager.deferredLanguageUninstall(
    Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))

Java

splitInstallManager.deferredLanguageUninstall(
    Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)));

Testare localmente le installazioni dei moduli

La libreria Play Feature Delivery ti consente di testare localmente la capacità della tua app di eseguire le seguenti operazioni senza connettersi al Play Store:

Questa pagina descrive come eseguire il deployment degli APK suddivisi della tua app sul dispositivo di test in modo che Play Feature Delivery utilizzi automaticamente questi APK per simulare la richiesta, il download e l'installazione dei moduli dal Play Store.

Anche se non è necessario apportare modifiche alla logica dell'app, devi soddisfare i seguenti requisiti:

  • Scarica e installa l'ultima versione di bundletool. Devi utilizzare bundletool per creare un nuovo insieme di APK installabili dal bundle dell'app.

Creare un insieme di APK

Se non l'hai ancora fatto, crea gli APK suddivisi della tua app nel seguente modo:

  1. Crea un app bundle per la tua app utilizzando uno dei seguenti metodi:
  2. Utilizza bundletool per generare un insieme di APK per tutte le configurazioni dei dispositivi con il seguente comando:

    bundletool build-apks --local-testing
      --bundle my_app.aab
      --output my_app.apks
    

Il flag --local-testing include i metadati nei manifest degli APK che consentono alla libreria Play Feature Delivery di utilizzare gli APK suddivisi locali per testare l'installazione dei moduli delle funzionalità senza connettersi al Play Store.

Esegui il deployment dell'app sul dispositivo

Dopo aver creato un insieme di APK utilizzando il flag --local-testing, utilizza bundletool per installare la versione base dell'app e trasferire gli APK aggiuntivi nella memoria locale del dispositivo. Puoi eseguire entrambe le azioni con il seguente comando:

bundletool install-apks --apks my_app.apks

Ora, quando avvii l'app e completi il flusso utente per scaricare e installare un modulo delle funzionalità, la libreria Play Feature Delivery utilizza gli APK che bundletool trasferiti nella memoria locale del dispositivo.

Simulare un errore di rete

Per simulare le installazioni dei moduli dal Play Store, la libreria Play Feature Delivery utilizza un'alternativa a SplitInstallManager, chiamata FakeSplitInstallManager, per richiedere il modulo. Quando utilizzi bundletool con il flag --local-testing per creare un insieme di APK ed eseguirne il deployment sul dispositivo di test, vengono inclusi metadati che indicano alla libreria Play Feature Delivery di passare automaticamente alle chiamate API della tua app per richiamare FakeSplitInstallManager anziché SplitInstallManager.

FakeSplitInstallManager include un flag booleano che puoi attivare per simulare un errore di rete la prossima volta che la tua app richiede l'installazione di un modulo. Per accedere a FakeSplitInstallManager nei test, puoi ottenere un'istanza utilizzando FakeSplitInstallManagerFactory, come mostrato di seguito:

Kotlin

// Creates an instance of FakeSplitInstallManager with the app's context.
val fakeSplitInstallManager = FakeSplitInstallManagerFactory.create(context)
// Tells Play Feature Delivery Library to force the next module request to
// result in a network error.
fakeSplitInstallManager.setShouldNetworkError(true)

Java

// Creates an instance of FakeSplitInstallManager with the app's context.
FakeSplitInstallManager fakeSplitInstallManager =
    FakeSplitInstallManagerFactory.create(context);
// Tells Play Feature Delivery Library to force the next module request to
// result in a network error.
fakeSplitInstallManager.setShouldNetworkError(true);