Panoramica delle trasmissioni

Le app per Android inviano e ricevono messaggi di trasmissione dal sistema Android e da altre app per Android, in modo simile al pattern di progettazione publish-subscribe. In genere, il sistema e le app inviano trasmissioni quando si verificano determinati eventi. Ad esempio, il sistema Android invia trasmissioni quando si verificano vari eventi di sistema, come l'avvio del sistema o la ricarica del dispositivo. Le app inviano anche trasmissioni personalizzate, ad esempio per notificare ad altre app qualcosa che potrebbe interessarle (ad esempio, il download di nuovi dati).

Le app possono registrarsi per ricevere trasmissioni specifiche. Quando viene inviata una trasmissione, il sistema la indirizza automaticamente alle app che hanno sottoscritto la ricezione di quel particolare tipo di trasmissione.

In generale, le trasmissioni possono essere utilizzate come sistema di messaggistica tra le app e al di fuori del normale flusso utente. Tuttavia, devi fare attenzione a non abusare dell'opportunità di rispondere alle trasmissioni ed eseguire job in background che possono contribuire a rallentare le prestazioni del sistema.

Informazioni sulle trasmissioni di sistema

Il sistema invia automaticamente le trasmissioni quando si verificano vari eventi di sistema, ad esempio quando il sistema passa alla modalità aereo e viceversa. Tutte le app sottoscritte ricevono queste trasmissioni.

L'oggetto Intent racchiude l'annuncio. La stringa action identifica l'evento che si è verificato, ad esempio android.intent.action.AIRPLANE_MODE. L'intent potrebbe includere anche informazioni aggiuntive raggruppate nel relativo campo extra. Ad esempio, l'intent della modalità aereo include un extra booleano che indica se la modalità aereo è attiva o meno.

Per saperne di più su come leggere gli intent e ottenere la stringa dell'azione da un intent, consulta Intent e filtri di intent.

Azioni di trasmissione di sistema

Per un elenco completo delle azioni di annuncio di sistema, consulta il file BROADCAST_ACTIONS.TXT nell'SDK Android. A ogni azione di trasmissione è associato un campo costante. Ad esempio, il valore della costante ACTION_AIRPLANE_MODE_CHANGED è android.intent.action.AIRPLANE_MODE. La documentazione per ogni azione di trasmissione è disponibile nel campo costante associato.

Modifiche alle trasmissioni di sistema

Man mano che la piattaforma Android si evolve, cambia periodicamente il comportamento delle trasmissioni di sistema. Tieni presente le seguenti modifiche per supportare tutte le versioni di Android.

Android 16

In Android 16, l'ordine di pubblicazione delle trasmissioni che utilizzano l'android:priority attributo o IntentFilter.setPriority() in processi diversi non sarà garantito. Le priorità di trasmissione vengono rispettate solo all'interno dello stesso processo dell'applicazione, anziché in tutti i processi.

Inoltre, le priorità di trasmissione vengono automaticamente limitate all'intervallo (SYSTEM_LOW_PRIORITY + 1, SYSTEM_HIGH_PRIORITY - 1). Solo i componenti di sistema possono impostare SYSTEM_LOW_PRIORITY, SYSTEM_HIGH_PRIORITY come priorità di trasmissione.

Android 14

Mentre le app sono in uno stato di cache, il sistema ottimizza la pubblicazione delle trasmissioni per l'integrità del sistema. Ad esempio, il sistema posticipa le trasmissioni di sistema meno importanti , come ACTION_SCREEN_ON, mentre l'app è in stato di cache. Una volta che l'app passa dallo stato di cache a un ciclo di vita del processo attivo, il sistema pubblica tutte le trasmissioni posticipate.

Le trasmissioni importanti che sono dichiarate nel manifest rimuovono temporaneamente le app dallo stato di cache per la pubblicazione.

Android 9

A partire da Android 9 (livello API 28), la NETWORK_STATE_CHANGED_ACTION trasmissione non riceve informazioni sulla posizione dell'utente o dati che consentono l'identificazione personale.

Se la tua app è installata su un dispositivo con Android 9.0 (livello API 28) o versioni successive, il sistema non include SSID, BSSID, informazioni sulla connessione o risultati della scansione nelle trasmissioni Wi-Fi. Per ottenere queste informazioni, chiama getConnectionInfo() invece.

Android 8.0

A partire da Android 8.0 (livello API 26), il sistema impone ulteriori limitazioni ai ricevitori dichiarati nel manifest.

Se la tua app ha come target Android 8.0 o versioni successive, non puoi utilizzare il manifest per dichiarare un ricevitore per la maggior parte delle trasmissioni implicite (trasmissioni che non hanno come target specifico la tua app). Puoi comunque utilizzare un ricevitore registrato nel contesto quando l'utente utilizza attivamente la tua app.

Android 7.0

Android 7.0 (livello API 24) e versioni successive non inviano le seguenti trasmissioni di sistema:

Inoltre, le app che hanno come target Android 7.0 e versioni successive devono registrare la CONNECTIVITY_ACTION trasmissione utilizzando registerReceiver(BroadcastReceiver, IntentFilter). La dichiarazione di un ricevitore nel manifest non funziona.

Ricevere trasmissioni

Le app possono ricevere trasmissioni in due modi: tramite ricevitori registrati nel contesto e ricevitori dichiarati nel manifest.

Ricevitori registrati nel contesto

I ricevitori registrati nel contesto ricevono le trasmissioni finché il contesto di registrazione è valido. In genere, questo avviene tra le chiamate a registerReceiver e unregisterReceiver. Il contesto di registrazione diventa non valido anche quando il sistema distrugge il contesto corrispondente. Ad esempio, se ti registri in un contesto Activity, ricevi le trasmissioni finché l'attività rimane attiva. Se ti registri con il contesto dell'applicazione, ricevi le trasmissioni finché l'app è in esecuzione.

Per registrare un ricevitore con un contesto:

  1. Nel file build a livello di modulo dell'app, includi la versione 1.9.0 o successive di la libreria AndroidX Core:

    Groovy

    dependencies {
        def core_version = "1.18.0"
    
        // Java language implementation
        implementation "androidx.core:core:$core_version"
        // Kotlin
        implementation "androidx.core:core-ktx:$core_version"
    
        // To use RoleManagerCompat
        implementation "androidx.core:core-role:1.1.0"
    
        // To use the Animator APIs
        implementation "androidx.core:core-animation:1.0.0"
        // To test the Animator APIs
        androidTestImplementation "androidx.core:core-animation-testing:1.0.0"
    
        // Optional - To enable APIs that query the performance characteristics of GMS devices.
        implementation "androidx.core:core-performance:1.0.0"
    
        // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google
        implementation "androidx.core:core-google-shortcuts:1.1.0"
    
        // Optional - to support backwards compatibility of RemoteViews
        implementation "androidx.core:core-remoteviews:1.1.0"
    
        // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12
        implementation "androidx.core:core-splashscreen:1.2.0"
    }

    Kotlin

    dependencies {
        val core_version = "1.18.0"
    
        // Java language implementation
        implementation("androidx.core:core:$core_version")
        // Kotlin
        implementation("androidx.core:core-ktx:$core_version")
    
        // To use RoleManagerCompat
        implementation("androidx.core:core-role:1.1.0")
    
        // To use the Animator APIs
        implementation("androidx.core:core-animation:1.0.0")
        // To test the Animator APIs
        androidTestImplementation("androidx.core:core-animation-testing:1.0.0")
    
        // Optional - To enable APIs that query the performance characteristics of GMS devices.
        implementation("androidx.core:core-performance:1.0.0")
    
        // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google
        implementation("androidx.core:core-google-shortcuts:1.1.0")
    
        // Optional - to support backwards compatibility of RemoteViews
        implementation("androidx.core:core-remoteviews:1.1.0")
    
        // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12
        implementation("androidx.core:core-splashscreen:1.2.0")
    }
  2. Crea un'istanza di BroadcastReceiver:

    Kotlin

    val myBroadcastReceiver = MyBroadcastReceiver()
    

    Java

    MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();
    
  3. Crea un'istanza di IntentFilter:

    Kotlin

    val filter = IntentFilter("com.example.snippets.ACTION_UPDATE_DATA")
    

    Java

    IntentFilter filter = new IntentFilter("com.example.snippets.ACTION_UPDATE_DATA");
    
  4. Scegli se il broadcast receiver deve essere esportato e visibile ad altre app sul dispositivo. Se questo ricevitore è in ascolto delle trasmissioni inviate dal sistema o da altre app, anche altre app di tua proprietà, utilizza il flag RECEIVER_EXPORTED. Se invece questo ricevitore è in ascolto solo delle trasmissioni inviate dalla tua app, utilizza il flag RECEIVER_NOT_EXPORTED.

    Kotlin

    val listenToBroadcastsFromOtherApps = false
    val receiverFlags = if (listenToBroadcastsFromOtherApps) {
        ContextCompat.RECEIVER_EXPORTED
    } else {
        ContextCompat.RECEIVER_NOT_EXPORTED
    }
    

    Java

    boolean listenToBroadcastsFromOtherApps = false;
    int receiverFlags = listenToBroadcastsFromOtherApps
            ? ContextCompat.RECEIVER_EXPORTED
            : ContextCompat.RECEIVER_NOT_EXPORTED;
    
  5. Registra il ricevitore chiamando registerReceiver():

    Kotlin

    ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags)
    

    Java

    ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags);
    
  6. Per interrompere la ricezione delle trasmissioni, chiama unregisterReceiver(android.content.BroadcastReceiver). Assicurati di annullare la registrazione del ricevitore quando non ne hai più bisogno o il contesto non è più valido.

Annullare la registrazione del broadcast receiver

Mentre il broadcast receiver è registrato, mantiene un riferimento al contesto con cui l'hai registrato. Ciò può potenzialmente causare perdite se l'ambito registrato del ricevitore supera l'ambito del ciclo di vita del contesto. Ad esempio, questo può verificarsi quando registri un ricevitore nell'ambito di un'attività, ma ti dimentichi di annullare la registrazione quando il sistema distrugge l'attività. Pertanto, annulla sempre la registrazione del broadcast receiver.

Kotlin

class MyActivity : ComponentActivity() {
    private val myBroadcastReceiver = MyBroadcastReceiver()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...
        ContextCompat.registerReceiver(this, myBroadcastReceiver, filter, receiverFlags)
        setContent { MyApp() }
    }

    override fun onDestroy() {
        super.onDestroy()
        // When you forget to unregister your receiver here, you're causing a leak!
        this.unregisterReceiver(myBroadcastReceiver)
    }
}

Java

class MyActivity extends ComponentActivity {
    MyBroadcastReceiver myBroadcastReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // ...
        ContextCompat.registerReceiver(this, myBroadcastReceiver, filter, receiverFlags);
        // Set content
    }
}

Registrare i ricevitori nell'ambito più piccolo

Il broadcast receiver deve essere registrato solo quando sei effettivamente interessato al risultato. Scegli l'ambito del ricevitore più piccolo possibile:

  • LifecycleResumeEffect o metodi del ciclo di vita onResume/onPause dell'attività: il broadcast receiver riceve gli aggiornamenti solo quando l'app è in stato di ripresa.
  • LifecycleStartEffect o metodi del ciclo di vita onStart/onStop dell'attività: il broadcast receiver riceve gli aggiornamenti solo quando l'app è in stato di ripresa.
  • DisposableEffect: il broadcast receiver riceve gli aggiornamenti solo quando il componibile si trova nell'albero di composizione. Questo ambito non è collegato all'ambito del ciclo di vita dell'attività. Valuta la possibilità di registrare il ricevitore nel contesto dell'applicazione. Questo perché il componibile potrebbe teoricamente sopravvivere all'ambito del ciclo di vita dell'attività e causare una perdita di memoria dell'attività.
  • onCreate/onDestroy dell'attività: il broadcast receiver riceve gli aggiornamenti mentre l'attività è in stato di creazione. Assicurati di annullare la registrazione in onDestroy() e non in onSaveInstanceState(Bundle) perché potrebbe non essere chiamato.
  • Un ambito personalizzato: ad esempio, puoi registrare un ricevitore nell'ambito di ViewModel, in modo che sopravviva alla ricreazione dell'attività. Assicurati di utilizzare il contesto dell'applicazione per registrare il ricevitore, poiché il ricevitore può sopravvivere all'ambito del ciclo di vita dell'attività e causare una perdita di memoria dell'attività.

Creare un componibile stateful e stateless

Compose ha componibili stateful e stateless. La registrazione o l'annullamento della registrazione di un broadcast receiver all'interno di un componibile lo rende stateful. Il componibile non è una funzione deterministica che esegue il rendering degli stessi contenuti quando vengono passati gli stessi parametri. Lo stato interno può cambiare in base alle chiamate al broadcast receiver registrato.

Come best practice in Compose, ti consigliamo di dividere i componibili in versioni stateful e stateless. Pertanto, ti consigliamo di spostare la creazione del broadcast receiver da un componibile per renderlo stateless:

@Composable
fun MyStatefulScreen() {
    val myBroadcastReceiver = remember { MyBroadcastReceiver() }
    val context = LocalContext.current
    LifecycleStartEffect(true) {
        // ...
        ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, flags)
        onStopOrDispose { context.unregisterReceiver(myBroadcastReceiver) }
    }
    MyStatelessScreen()
}

@Composable
fun MyStatelessScreen() {
    // Implement your screen
}

Ricevitori dichiarati nel manifest

Se dichiari un broadcast receiver nel manifest, il sistema avvia l'app quando viene inviata la trasmissione. Se l'app non è già in esecuzione, il sistema la avvia.

Per dichiarare un broadcast receiver nel manifest:

  1. Specifica l'elemento <receiver> nel manifest dell'app.

    <!-- If this receiver listens for broadcasts sent from the system or from
         other apps, even other apps that you own, set android:exported to "true". -->
    <receiver android:name=".MyBroadcastReceiver" android:exported="false">
        <intent-filter>
            <action android:name="com.example.snippets.ACTION_UPDATE_DATA" />
        </intent-filter>
    </receiver>
    

    I filtri di intent specificano le azioni di trasmissione a cui è sottoscritto il ricevitore.

  2. Crea una sottoclasse di BroadcastReceiver e implementa onReceive(Context, Intent). Il broadcast receiver nell'esempio seguente registra e visualizza i contenuti della trasmissione:

    Kotlin

    class MyBroadcastReceiver : BroadcastReceiver() {
    
        @Inject
        lateinit var dataRepository: DataRepository
    
        override fun onReceive(context: Context, intent: Intent) {
            if (intent.action == "com.example.snippets.ACTION_UPDATE_DATA") {
                val data = intent.getStringExtra("com.example.snippets.DATA") ?: "No data"
                // Do something with the data, for example send it to a data repository:
                dataRepository.updateData(data)
            }
        }
    }
    

    Java

    public static class MyBroadcastReceiver extends BroadcastReceiver {
    
        @Inject
        DataRepository dataRepository;
    
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Objects.equals(intent.getAction(), "com.example.snippets.ACTION_UPDATE_DATA")) {
                String data = intent.getStringExtra("com.example.snippets.DATA");
                // Do something with the data, for example send it to a data repository:
                if (data != null) { dataRepository.updateData(data); }
            }
        }
    }
    

Il gestore dei pacchetti di sistema registra il ricevitore quando l'app viene installata. Il ricevitore diventa quindi un punto di ingresso separato nell'app, il che significa che il sistema può avviare l'app e pubblicare la trasmissione se l'app non è in esecuzione.

Il sistema crea un nuovo BroadcastReceiver oggetto componente per gestire ogni trasmissione che riceve. Questo oggetto è valido solo per la durata di la chiamata a onReceive(Context, Intent). Una volta che il codice restituisce questo metodo, il sistema considera il componente non più attivo.

Effetti sullo stato del processo

Il funzionamento o meno di BroadcastReceiver influisce sul processo contenuto, che può alterare la probabilità di eliminazione del sistema. Un processo in primo piano esegue il metodo onReceive() di un ricevitore. Il sistema esegue il processo tranne in caso di pressione di memoria estrema.

Il sistema disattiva BroadcastReceiver dopo onReceive(). L'importanza del processo host del ricevitore dipende dai componenti dell'app. Se questo processo ospita solo un ricevitore dichiarato nel manifest, il sistema potrebbe eliminarlo dopo onReceive() per liberare risorse per altri processi più critici. Questo è comune per le app con cui l'utente non ha interagito o non ha interagito di recente.

Pertanto, i broadcast receiver non devono avviare thread in background a lunga esecuzione. Il sistema può interrompere il processo in qualsiasi momento dopo onReceive() per recuperare memoria, terminando il thread creato. Per mantenere attivo il processo, pianifica un JobService dal ricevitore utilizzando JobScheduler in modo che il sistema sappia che il processo è ancora in esecuzione. La panoramica del lavoro in background fornisce ulteriori dettagli.

Inviare trasmissioni

Android offre due modi per le app di inviare trasmissioni:

  • Il metodo sendOrderedBroadcast(Intent, String) invia le trasmissioni a un ricevitore alla volta. Man mano che ogni ricevitore viene eseguito a turno, può propagare un risultato al ricevitore successivo. Può anche interrompere completamente la trasmissione in modo che non raggiunga altri ricevitori. Puoi controllare l'ordine di esecuzione dei ricevitori all'interno dello stesso processo dell'app. Per farlo, utilizza l'attributo android:priority del filtro di intent corrispondente. I ricevitori con la stessa priorità vengono eseguiti in un ordine arbitrario.
  • Il metodo sendBroadcast(Intent) invia le trasmissioni a tutti i ricevitori in un ordine non definito. Questa è chiamata trasmissione normale. È più efficiente, ma significa che i ricevitori non possono leggere i risultati di altri ricevitori, propagare i dati ricevuti dalla trasmissione o interrompere la trasmissione.

Il seguente snippet di codice mostra come inviare una trasmissione creando un intent e chiamando sendBroadcast(Intent).

Kotlin

val intent = Intent("com.example.snippets.ACTION_UPDATE_DATA").apply {
    putExtra("com.example.snippets.DATA", newData)
    setPackage("com.example.snippets")
}
context.sendBroadcast(intent)

Java

Intent intent = new Intent("com.example.snippets.ACTION_UPDATE_DATA");
intent.putExtra("com.example.snippets.DATA", newData);
intent.setPackage("com.example.snippets");
context.sendBroadcast(intent);

L'annuncio è racchiuso in un Intent oggetto. La stringa action dell'intent deve fornire la sintassi del nome del pacchetto Java dell'app e identificare in modo univoco l'evento di trasmissione. Puoi allegare informazioni aggiuntive all' intent con putExtra(String, Bundle). Puoi anche limitare una trasmissione a un insieme di app nella stessa organizzazione chiamando setPackage(String) su l'intent.

Limitare le trasmissioni con le autorizzazioni

Le autorizzazioni ti consentono di limitare le trasmissioni all'insieme di app che dispongono di determinate autorizzazioni. Puoi applicare limitazioni al mittente o al ricevitore di una trasmissione.

Inviare trasmissioni con le autorizzazioni

Quando chiami sendBroadcast(Intent, String) o sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) , puoi specificare un parametro di autorizzazione. Solo i ricevitori che hanno richiesto questa autorizzazione con il tag <uses-permission> nel manifest possono ricevere la trasmissione. Se l'autorizzazione è pericolosa, devi concederla prima che il ricevitore possa ricevere la trasmissione. Ad esempio, il seguente codice invia una trasmissione con un'autorizzazione:

Kotlin

context.sendBroadcast(intent, android.Manifest.permission.ACCESS_COARSE_LOCATION)

Java

context.sendBroadcast(intent, android.Manifest.permission.ACCESS_COARSE_LOCATION);

Per ricevere la trasmissione, l'app di ricezione deve richiedere l'autorizzazione nel seguente modo:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Puoi specificare un'autorizzazione di sistema esistente, ad esempio BLUETOOTH_CONNECT o definire un'autorizzazione personalizzata con l'elemento <permission>. Per informazioni sulle autorizzazioni e sulla sicurezza in generale, consulta le Autorizzazioni di sistema.

Ricevere trasmissioni con le autorizzazioni

Se specifichi un parametro di autorizzazione quando registri un broadcast receiver (con registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) o nel <receiver> tag nel manifest), solo i broadcaster che hanno richiesto l'autorizzazione con il <uses-permission> tag nel loro manifest possono inviare un intent al ricevitore. Se l'autorizzazione è pericolosa, deve essere concessa anche al broadcaster.

Ad esempio, supponiamo che l'app di ricezione abbia un ricevitore dichiarato nel manifest come segue:

<!-- If this receiver listens for broadcasts sent from the system or from
     other apps, even other apps that you own, set android:exported to "true". -->
<receiver
    android:name=".MyBroadcastReceiverWithPermission"
    android:permission="android.permission.ACCESS_COARSE_LOCATION"
    android:exported="true">
    <intent-filter>
        <action android:name="com.example.snippets.ACTION_UPDATE_DATA" />
    </intent-filter>
</receiver>

Oppure l'app di ricezione ha un ricevitore registrato nel contesto come segue:

Kotlin

ContextCompat.registerReceiver(
    context, myBroadcastReceiver, filter,
    android.Manifest.permission.ACCESS_COARSE_LOCATION,
    null, // scheduler that defines thread, null means run on main thread
    receiverFlags
)

Java

ContextCompat.registerReceiver(
        context, myBroadcastReceiver, filter,
        android.Manifest.permission.ACCESS_COARSE_LOCATION,
        null, // scheduler that defines thread, null means run on main thread
        receiverFlags
);

Per poter inviare trasmissioni a questi ricevitori, l'app di invio deve richiedere l'autorizzazione nel seguente modo:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Considerazioni sulla sicurezza

Di seguito sono riportate alcune considerazioni sulla sicurezza per l'invio e la ricezione di trasmissioni:

  • Se molte app hanno registrato la ricezione della stessa trasmissione nel manifest, il sistema potrebbe avviare molte app, con un impatto significativo sulle prestazioni del dispositivo e sull'esperienza utente. Per evitare questo problema, preferisci utilizzare la registrazione del contesto rispetto alla dichiarazione del manifest. A volte, il sistema Android stesso impone l'utilizzo di ricevitori registrati nel contesto. Ad esempio, la trasmissione CONNECTIVITY_ACTION viene pubblicata solo sui ricevitori registrati nel contesto.

  • Non trasmettere informazioni sensibili utilizzando un intent implicito. Qualsiasi app può leggere le informazioni se si registra per ricevere la trasmissione. Esistono tre modi per controllare chi può ricevere le tue trasmissioni:

    • Puoi specificare un'autorizzazione quando invii una trasmissione.
    • In Android 4.0 (livello API 14) e versioni successive, puoi specificare un pacchetto con setPackage(String) quando invii una trasmissione. Il sistema limita la trasmissione all'insieme di app che corrispondono al pacchetto.
  • Quando registri un ricevitore, qualsiasi app può inviare trasmissioni potenzialmente dannose al ricevitore della tua app. Esistono diversi modi per limitare le trasmissioni ricevute dalla tua app:

    • Puoi specificare un'autorizzazione quando registri un broadcast receiver.
    • Per i ricevitori dichiarati nel manifest, puoi impostare l'attributo android:exported su "false" nel manifest. Il ricevitore non riceve trasmissioni da origini esterne all'app.
  • Lo spazio dei nomi per le azioni di trasmissione è globale. Assicurati che i nomi delle azioni e le altre stringhe siano scritte in uno spazio dei nomi di tua proprietà. In caso contrario, potresti inavvertitamente entrare in conflitto con altre app.

  • Poiché il metodo onReceive(Context, Intent) di un ricevitore viene eseguito sul thread principale, deve essere eseguito e restituito rapidamente. Se devi eseguire un lavoro a lunga esecuzione, fai attenzione a generare thread o avviare servizi in background perché il sistema può eliminare l'intero processo dopo la restituzione di onReceive(). Per saperne di più, consulta Effetto sullo stato del processo Per eseguire un lavoro a lunga esecuzione, ti consigliamo di:

    • Chiamare goAsync() nel metodo onReceive() del ricevitore e passare BroadcastReceiver.PendingResult a un thread in background. In questo modo la trasmissione rimane attiva dopo la restituzione di onReceive(). Tuttavia, anche con questo approccio il sistema si aspetta che tu completi la trasmissione molto rapidamente (in meno di 10 secondi). Ti consente di spostare il lavoro su un altro thread per evitare di bloccare il thread principale.
    • Pianificare un job con il JobScheduler. Per saperne di più, consulta Pianificazione intelligente dei job.
  • Non avviare attività dai broadcast receiver perché l'esperienza utente è fastidiosa, soprattutto se sono presenti più ricevitori. In alternativa, valuta la possibilità di mostrare una notifica.