Programmare sveglie

Gli allarmi (basati sulla classe AlarmManager) consentono di eseguire operazioni basate sul tempo al di fuori del ciclo di vita dell'applicazione. Ad esempio, puoi utilizzare un allarme per avviare un'operazione a lunga esecuzione, come l'avvio di un servizio una volta al giorno per scaricare le previsioni meteo.

Le sveglie hanno le seguenti caratteristiche:

  • Ti consentono di attivare gli intent a intervalli e/o orari prestabiliti.

  • Puoi utilizzarli insieme ai ricevitori di trasmissione per pianificare job o WorkRequests per eseguire altre operazioni.

  • Esse operano al di fuori della tua applicazione, quindi puoi utilizzarle per attivare eventi o azioni anche quando l'app non è in esecuzione e anche quando il dispositivo stesso è in sospensione.

  • Aiutano a ridurre al minimo i requisiti di risorse della tua app. Puoi pianificare le operazioni senza fare affidamento su timer o servizi in esecuzione continua.

Impostare una sveglia inesatta

Se un'app imposta una sveglia inesatta, il sistema lo fornisce in un determinato momento in futuro. Gli allarmi inesatti forniscono alcune garanzie riguardo ai tempi di invio delle sveglie, rispettando al contempo le restrizioni sul risparmio della batteria, come la funzionalità Sospensione.

Gli sviluppatori possono sfruttare le seguenti garanzie API per personalizzare i tempi di invio degli allarmi inesatti.

Impostare una sveglia dopo un orario specifico

Se l'app chiama set(), setInexactRepeating() o setAndAllowWhileIdle(), l'allarme non suona mai prima dell'ora di attivazione specificata.

Su Android 12 (livello API 31) e versioni successive, il sistema attiva l'allarme entro un'ora dal tempo di attivazione fornito, a meno che non siano in vigore limitazioni per il risparmio energetico, come Risparmio batteria o Sospensione.

Erogare una sveglia durante un intervallo di tempo

Se l'app chiama setWindow(), la sveglia non suona mai prima del tempo di attivazione specificato. A meno che non siano in vigore restrizioni relative al risparmio della batteria, l'allarme viene inviato entro l'intervallo di tempo specificato, a partire dall'orario di attivazione specificato.

Se la tua app ha come target Android 12 o versioni successive, il sistema può ritardare la chiamata di una sveglia inesatta con intervallo temporale di almeno 10 minuti. Per questo motivo, i valori parametro windowLengthMillis in 600000 sono tagliati a 600000.

Emetti una sveglia ricorrente a intervalli approssimativamente a intervalli regolari

Se l'app chiama setInexactRepeating(), il sistema richiama più sveglie:

  1. Il primo allarme viene attivato entro l'intervallo di tempo specificato, a partire dall'orario di attivazione specificato.
  2. Le sveglie successive solitamente suonano una volta trascorso il periodo di tempo specificato. L'intervallo di tempo tra due chiamate consecutive dell'allarme può variare.

Impostare una sveglia esatta

Il sistema attiva un allarme esatto in un momento preciso nel futuro.

La maggior parte delle app può programmare attività ed eventi utilizzando sveglie inesatte per completare diversi casi d'uso comuni. Se la funzionalità di base dell'app dipende da una sveglia impostata con precisione, ad esempio per un'app sveglia o un'app di calendario, puoi usare invece una sveglia esatta.

Casi d'uso che potrebbero non richiedere sveglie esatte

Il seguente elenco mostra i flussi di lavoro comuni che potrebbero non richiedere un allarme esatto:

Pianificazione delle operazioni di tempistica durante il ciclo di vita dell'app
La classe Handler include diversi metodi efficaci per gestire le operazioni relative alle tempistiche, ad esempio svolgere del lavoro ogni n secondi, mentre l'app è attiva: postAtTime() e postDelayed(). Tieni presente che queste API si basano sull'uptime del sistema e non sul tempo reale.
Operazioni in background pianificate, ad esempio l'aggiornamento dell'app e il caricamento dei log
WorkManager consente di pianificare lavori periodici sensibili alle tempistiche. Puoi fornire un intervallo di ripetizione e flexInterval (minimo 15 minuti) per definire un runtime granulare per il lavoro.
Azione specificata dall'utente che dovrebbe verificarsi dopo un intervallo di tempo specifico (anche se il sistema è in stato inattivo)
Usa una sveglia inesatta. In particolare, chiama setAndAllowWhileIdle().
Azione specificata dall'utente che deve verificarsi dopo un intervallo di tempo specifico
Usa una sveglia inesatta. In particolare, chiama set().
Azione specificata dall'utente che può verificarsi entro un periodo di tempo specificato
Usa una sveglia inesatta. In particolare, chiama setWindow(). Tieni presente che, se la tua app ha come target Android 12 o versioni successive, la durata minima della finestra consentita è 10 minuti.

Come impostare una sveglia esatta

La tua app può impostare sveglie esatte utilizzando uno dei seguenti metodi. Questi metodi sono ordinati in modo che quelli più vicini alla fine dell'elenco svolgano attività più critiche in termini di tempo, ma richiedono più risorse di sistema.

setExact()

Puoi attivare una sveglia in un momento quasi preciso, a condizione che non siano state applicate altre misure per il risparmio della batteria.

Utilizza questo metodo per impostare sveglie esatte, a meno che il lavoro dell'app non sia fondamentale per l'utente.

setExactAndAllowWhileIdle()

Puoi attivare una sveglia in futuro quasi preciso, anche se sono state applicate le misure per il risparmio della batteria.

setAlarmClock()

Richiamare una sveglia a un'ora precisa nel futuro. Poiché questi allarmi sono altamente visibili agli utenti, il sistema non regola mai i tempi di consegna. Il sistema identifica questi allarmi come i più critici e abbandona la modalità a basso consumo, se necessario, per erogare gli allarmi.

Consumo delle risorse di sistema

Quando il sistema attiva allarmi esatti impostati dall'app, il dispositivo consuma molte risorse, ad esempio la durata della batteria, soprattutto se è in modalità di risparmio energetico. Inoltre, il sistema non riesce a gestire facilmente queste richieste per usare le risorse in modo più efficiente.

Ti consigliamo vivamente di creare una sveglia inesatta ogni volta che possibile. Per prolungare l'esecuzione, programmalo utilizzando WorkManager o JobScheduler dal dispositivo BroadcastReceiver della sveglia. Per eseguire operazioni mentre il dispositivo è in modalità Sospensione, crea una sveglia inesatta utilizzando setAndAllowWhileIdle() e avvia un job dalla sveglia.

Dichiara l'autorizzazione per la sveglia esatta appropriata

Se la tua app ha come target Android 12 o versioni successive, devi ottenere l'accesso speciale per l'app "Sveglie e promemoria". A questo scopo, dichiara l'autorizzazione SCHEDULE_EXACT_ALARM nel file manifest della tua app, come mostrato nel seguente snippet di codice:

<manifest ...>
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
    <application ...>
        ...
    </application>
</manifest>

Se la tua app ha come target Android 13 (livello API 33) o versioni successive, puoi dichiarare l'autorizzazione SCHEDULE_EXACT_ALARM o USE_EXACT_ALARM.

<manifest ...>
    <uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
    <application ...>
        ...
    </application>
</manifest>

Sebbene le autorizzazioni SCHEDULE_EXACT_ALARM e USE_EXACT_ALARM segnalino le stesse funzionalità, vengono concesse in modo diverso e supportano casi d'uso diversi. La tua app deve usare sveglie esatte e dichiarare l'autorizzazione SCHEDULE_EXACT_ALARM o USE_EXACT_ALARM solo se una funzione rivolta agli utenti nell'app richiede azioni temporizzate in modo preciso.

USE_EXACT_ALARM

SCHEDULE_EXACT_ALARM

  • Concesso dall'utente
  • Un insieme più ampio di casi d'uso
  • Le app devono confermare che l'autorizzazione non è stata revocata

Utilizzo dell'autorizzazione SCHEDULE_EXACT_ALARM

A differenza di USE_EXACT_ALARM, l'autorizzazione SCHEDULE_EXACT_ALARM deve essere concessa dall'utente. Sia l'utente che il sistema possono revocare l'autorizzazione SCHEDULE_EXACT_ALARM.

Per verificare se l'autorizzazione è stata concessa alla tua app, chiama canScheduleExactAlarms() prima di provare a impostare una sveglia esatta. Se l'autorizzazione SCHEDULE_EXACT_ALARM viene revocata per la tua app, l'app si interrompe e tutte le future sveglie esatte vengono annullate. Ciò significa anche che il valore restituito da canScheduleExactAlarms() rimane valido per l'intero ciclo di vita della tua app.

Quando viene concessa l'autorizzazione SCHEDULE_EXACT_ALARMS alla tua app, il sistema le invia la trasmissione di ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED. La tua app deve implementare un ricevitore di trasmissione che:

  1. Conferma che l'app abbia ancora accesso speciale all'app. Per farlo, chiama il numero canScheduleExactAlarms(). Questo controllo protegge la tua app dal caso in cui l'utente concede l'autorizzazione all'app e poi la revoca quasi immediatamente dopo.
  2. Riprogramma tutte le sveglie esatte che la tua app ha bisogno, in base al suo stato attuale. Questa logica dovrebbe essere simile a quella che fa la tua app quando riceve la trasmissione ACTION_BOOT_COMPLETED.

Chiedi agli utenti di concedere l'autorizzazione SCHEDULE_EXACT_ALARM

L&#39;opzione è denominata &quot;Consenti l&#39;impostazione di sveglie e promemoria&quot;
Figura 1. Pagina di accesso speciale alle app "Sveglie e promemoria " nelle impostazioni di sistema, dove gli utenti possono consentire all'app di impostare sveglie esatte.

Se necessario, puoi indirizzare gli utenti alla schermata Sveglie e promemoria nelle impostazioni di sistema, come mostrato nella Figura 1. Per farlo, segui questi passaggi:

  1. Nella UI dell'app, spiega all'utente perché l'app deve programmare sveglie esatte.
  2. Richiama un intent che include l'azione dell'intent ACTION_REQUEST_SCHEDULE_EXACT_ALARM.

Impostare una sveglia ricorrente

La ripetizione delle sveglie consente al sistema di inviare notifiche all'app in base a una programmazione ricorrente.

Un allarme mal progettato può comportare il consumo della batteria e un carico notevole sui server. Per questo motivo, su Android 4.4 (livello API 19) e versioni successive, tutte le sveglie ripetute sono sveglie inesatte.

Una sveglia ricorrente ha le seguenti caratteristiche:

  • Un tipo di allarme. Per ulteriori informazioni, vedi Scegliere un tipo di sveglia.

  • Un'ora di attivazione. Se l'orario di attivazione specificato è già trascorso, l'allarme si attiva immediatamente.

  • L'intervallo della sveglia. ad esempio una volta al giorno, ogni ora oppure ogni 5 minuti.

  • Un intent in sospeso che si attiva quando viene attivato l'allarme. Quando imposti una seconda sveglia che utilizza lo stesso intent in sospeso, sostituisce la sveglia originale.

Per annullare un PendingIntent(), passa FLAG_NO_CREATE a PendingIntent.getService() per ottenere un'istanza dell'intent (se esistente), poi trasmettilo a AlarmManager.cancel()

Kotlin

val alarmManager =
    context.getSystemService(Context.ALARM_SERVICE) as? AlarmManager
val pendingIntent =
    PendingIntent.getService(context, requestId, intent,
                                PendingIntent.FLAG_NO_CREATE)
if (pendingIntent != null && alarmManager != null) {
  alarmManager.cancel(pendingIntent)
}

Java

AlarmManager alarmManager =
    (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent =
    PendingIntent.getService(context, requestId, intent,
                                PendingIntent.FLAG_NO_CREATE);
if (pendingIntent != null && alarmManager != null) {
  alarmManager.cancel(pendingIntent);
}

Scegli un tipo di sveglia

Una delle prime considerazioni da fare nell'utilizzo di una sveglia ricorrente è il tipo deve essere il tipo.

Esistono due tipi generali di orologio per le sveglie: "in tempo reale trascorso" e "orologio in tempo reale" (RTC). Il tempo reale trascorso utilizza il "tempo dall'avvio del sistema" come riferimento, mentre l'orologio in tempo reale utilizza il tempo UTC (orologio a parete). Ciò significa che il tempo reale trascorso è adatto per impostare una sveglia in base al tempo trascorso (ad esempio, una sveglia che si attiva ogni 30 secondi) poiché non è influenzata dal fuso orario o dalle impostazioni internazionali. Il tipo di orologio in tempo reale è più adatto per le sveglie che dipendono dalla lingua corrente.

Entrambi i tipi hanno una versione "riattivazione", che indica di riattivare la CPU del dispositivo se lo schermo è spento. Ciò garantisce che la sveglia si attivi all'ora programmata. Questo è utile se la tua app ha una dipendenza temporale. ad esempio se ha un periodo limitato per eseguire un'operazione particolare. Se non utilizzi la versione sveglia del tipo di sveglia, tutte le sveglie ripetute si attivano alla successiva attivazione del dispositivo.

Se vuoi semplicemente che la sveglia si attivi a un intervallo particolare (ad esempio ogni mezz'ora), utilizza uno dei tipi di tempo reale trascorso. In generale, questa è la scelta migliore.

Se vuoi che la sveglia si attivi a una determinata ora del giorno, scegli uno dei tipi di orologio in tempo reale basati sull'orologio. Tuttavia, tieni presente che questo approccio può presentare alcuni svantaggi. L'app potrebbe non essere tradotta correttamente in altre lingue e, se l'utente modifica l'impostazione dell'ora del dispositivo, potrebbe verificarsi un comportamento imprevisto nell'app. Inoltre, l'utilizzo di un tipo di sveglia con orologio in tempo reale non consente di scalare correttamente, come spiegato in precedenza. Ti consigliamo, se possibile, di utilizzare una sveglia "in tempo reale scaduta".

Ecco l'elenco dei tipi:

  • ELAPSED_REALTIME: attiva l'intent in sospeso in base al periodo di tempo dall'avvio del dispositivo, ma non lo riattiva. Il tempo trascorso include il tempo durante il quale il dispositivo è rimasto in sospensione.

  • ELAPSED_REALTIME_WAKEUP: riattiva il dispositivo e attiva l'intent in sospeso una volta trascorso il periodo di tempo specificato dall'avvio del dispositivo.

  • RTC: attiva l'intent in sospeso al momento specificato, ma non riattiva il dispositivo.

  • RTC_WAKEUP: riattiva il dispositivo per attivare l'intent in sospeso al momento specificato.

Esempi di sveglie in tempo reale passate

Ecco alcuni esempi di utilizzo di ELAPSED_REALTIME_WAKEUP

Riattiva il dispositivo per attivare l'allarme dopo 30 minuti e ogni 30 minuti dopo:

Kotlin

// Hopefully your alarm will have a lower frequency than this!
alarmMgr?.setInexactRepeating(
        AlarmManager.ELAPSED_REALTIME_WAKEUP,
        SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR,
        AlarmManager.INTERVAL_HALF_HOUR,
        alarmIntent
)

Java

// Hopefully your alarm will have a lower frequency than this!
alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
        SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR,
        AlarmManager.INTERVAL_HALF_HOUR, alarmIntent);

Riattiva il dispositivo per attivare una sveglia una tantum (non ripetitiva) in un minuto:

Kotlin

private var alarmMgr: AlarmManager? = null
private lateinit var alarmIntent: PendingIntent
...
alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent ->
    PendingIntent.getBroadcast(context, 0, intent, 0)
}

alarmMgr?.set(
        AlarmManager.ELAPSED_REALTIME_WAKEUP,
        SystemClock.elapsedRealtime() + 60 * 1000,
        alarmIntent
)

Java

private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
...
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
        SystemClock.elapsedRealtime() +
        60 * 1000, alarmIntent);

Esempi di sveglie in tempo reale con orologio

Ecco alcuni esempi di utilizzo di RTC_WAKEUP.

Attiva il dispositivo per attivare la sveglia intorno alle 14:00 e ripeti una volta al giorno alla stessa ora:

Kotlin

// Set the alarm to start at approximately 2:00 p.m.
val calendar: Calendar = Calendar.getInstance().apply {
    timeInMillis = System.currentTimeMillis()
    set(Calendar.HOUR_OF_DAY, 14)
}

// With setInexactRepeating(), you have to use one of the AlarmManager interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
alarmMgr?.setInexactRepeating(
        AlarmManager.RTC_WAKEUP,
        calendar.timeInMillis,
        AlarmManager.INTERVAL_DAY,
        alarmIntent
)

Java

// Set the alarm to start at approximately 2:00 p.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 14);

// With setInexactRepeating(), you have to use one of the AlarmManager interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
        AlarmManager.INTERVAL_DAY, alarmIntent);

Attiva il dispositivo per attivare l'allarme esattamente alle 8:30 e successivamente ogni 20 minuti:

Kotlin

private var alarmMgr: AlarmManager? = null
private lateinit var alarmIntent: PendingIntent
...
alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent ->
    PendingIntent.getBroadcast(context, 0, intent, 0)
}

// Set the alarm to start at 8:30 a.m.
val calendar: Calendar = Calendar.getInstance().apply {
    timeInMillis = System.currentTimeMillis()
    set(Calendar.HOUR_OF_DAY, 8)
    set(Calendar.MINUTE, 30)
}

// setRepeating() lets you specify a precise custom interval--in this case,
// 20 minutes.
alarmMgr?.setRepeating(
        AlarmManager.RTC_WAKEUP,
        calendar.timeInMillis,
        1000 * 60 * 20,
        alarmIntent
)

Java

private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
...
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

// Set the alarm to start at 8:30 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30);

// setRepeating() lets you specify a precise custom interval--in this case,
// 20 minutes.
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
        1000 * 60 * 20, alarmIntent);

Stabilisci la precisione della sveglia

Come descritto in precedenza, la scelta del tipo di allarme è spesso il primo passaggio nella creazione di una sveglia. Un'altra distinzione è quanto deve essere precisa la sveglia. Per la maggior parte delle app, setInexactRepeating() è la scelta giusta. Se utilizzi questo metodo, Android sincronizza più sveglie ripetute inesatte e le attiva contemporaneamente. In questo modo si riduce il consumo della batteria.

Se possibile, evita di utilizzare sveglie esatte. Tuttavia, per le app rare con requisiti di tempo rigidi, puoi impostare una sveglia esatta chiamando il numero setRepeating().

Con setInexactRepeating(), non puoi specificare un intervallo personalizzato come faresti con setRepeating(). Devi utilizzare una delle costanti di intervallo, ad esempio INTERVAL_FIFTEEN_MINUTES, INTERVAL_DAY e così via. Consulta AlarmManager per l'elenco completo.

Annulla una sveglia

A seconda dell'app, potresti includere la possibilità di annullare la sveglia. Per annullare una sveglia, chiama cancel() in Gestione sveglie, trasmettendo il PendingIntent che non vuoi più attivare. Ecco alcuni esempi:

Kotlin

// If the alarm has been set, cancel it.
alarmMgr?.cancel(alarmIntent)

Java

// If the alarm has been set, cancel it.
if (alarmMgr!= null) {
    alarmMgr.cancel(alarmIntent);
}

Avvia una sveglia al riavvio del dispositivo

Per impostazione predefinita, tutte le sveglie vengono annullate quando un dispositivo si spegne. Per evitare che ciò accada, puoi progettare l'applicazione in modo che riavvii automaticamente una sveglia ricorrente al riavvio del dispositivo. Questo garantisce che AlarmManager continui a svolgere la propria attività senza che l'utente debba riavviare manualmente l'allarme.

Proceda nel seguente modo:

  1. Imposta l'autorizzazione RECEIVE_BOOT_COMPLETED nel file manifest della tua applicazione. Ciò consente alla tua app di ricevere il messaggio ACTION_BOOT_COMPLETED che viene trasmesso al termine dell'avvio del sistema (questa operazione funziona solo se l'app è già stata avviata dall'utente almeno una volta):

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
  2. Implementa un BroadcastReceiver per ricevere la trasmissione:

    Kotlin

    class SampleBootReceiver : BroadcastReceiver() {
    
        override fun onReceive(context: Context, intent: Intent) {
            if (intent.action == "android.intent.action.BOOT_COMPLETED") {
                // Set the alarm here.
            }
        }
    }
    

    Java

    public class SampleBootReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
                // Set the alarm here.
            }
        }
    }
    
  3. Aggiungi il destinatario al file manifest dell'app con un filtro per intent che filtra in base all'azione ACTION_BOOT_COMPLETED:

    <receiver android:name=".SampleBootReceiver"
            android:enabled="false">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"></action>
        </intent-filter>
    </receiver>

    Tieni presente che nel manifest il ricevitore di avvio è impostato su android:enabled="false". Ciò significa che il destinatario non verrà chiamato a meno che l'applicazione non lo abiliti esplicitamente. Ciò evita che il ricevitore di avvio venga chiamato inutilmente. Puoi abilitare un ricevitore (ad esempio, se l'utente imposta un allarme) come segue:

    Kotlin

    val receiver = ComponentName(context, SampleBootReceiver::class.java)
    
    context.packageManager.setComponentEnabledSetting(
            receiver,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP
    )
    

    Java

    ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
    PackageManager pm = context.getPackageManager();
    
    pm.setComponentEnabledSetting(receiver,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP);
    

    Una volta abilitato il ricevitore in questo modo, rimarrà attivo, anche se l'utente riavvia il dispositivo. In altre parole, abilitare il ricevitore in modo programmatico esegue l'override dell'impostazione del manifest, anche tra i riavvii. Il destinatario rimarrà attivo finché l'app non lo disattiverà. Puoi disattivare un ricevitore (ad esempio, se l'utente annulla una sveglia) come segue:

    Kotlin

    val receiver = ComponentName(context, SampleBootReceiver::class.java)
    
    context.packageManager.setComponentEnabledSetting(
            receiver,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP
    )
    

    Java

    ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
    PackageManager pm = context.getPackageManager();
    
    pm.setComponentEnabledSetting(receiver,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP);
    

Richiamare le sveglie con il dispositivo in modalità Sospensione

I dispositivi con Android 6.0 (livello API 23) supportano la modalità Sospensione, che consente di prolungare la durata della batteria dei dispositivi. Le sveglie non si attivano quando il dispositivo è in modalità Sospensione Le sveglie programmate vengono differite fino a quando il dispositivo non esce dalla modalità Sospensione. Se devi completare il lavoro anche quando il dispositivo è inattivo, sono disponibili diverse opzioni:

  • Imposta una sveglia esatta.

  • Usa l'API WorkManager, creata per eseguire il lavoro in background. Puoi indicare che il sistema deve accelerare il lavoro in modo che il lavoro venga completato il prima possibile. Per ulteriori informazioni, consulta Pianificare le attività con WorkManager

Best practice

Ogni scelta che fai nella progettazione di una sveglia ricorrente può avere conseguenze sul modo in cui l'app utilizza (o utilizza in modo illecito) le risorse di sistema. Ad esempio, immagina un'app popolare che si sincronizza con un server. Se l'operazione di sincronizzazione si basa sull'ora di orologio e ogni istanza dell'app si sincronizza alle 23:00, il carico sul server potrebbe causare un'alta latenza o persino un "denial of service". Segui queste best practice per l'uso delle sveglie:

  • Aggiungi casualità (tremolio) a qualsiasi richiesta di rete attivata in seguito a un allarme ripetuto:

    • Eseguire operazioni locali quando viene attivato l'allarme. "Lavoro locale" significa tutto ciò che non contatta un server o non richiede i dati del server.

    • Allo stesso tempo, pianifica l'attivazione della sveglia contenente le richieste di rete in un periodo di tempo casuale.

  • Mantieni la frequenza della sveglia al minimo.

  • Non riattivare il dispositivo inutilmente (questo comportamento dipende dal tipo di sveglia, come descritto nella sezione Scegliere un tipo di sveglia).

  • Non rendere l'ora di attivazione della sveglia più precisa di quanto debba essere.

    Utilizza setInexactRepeating() anziché setRepeating(). Quando utilizzi setInexactRepeating(), Android sincronizza le sveglie ripetute da più app e le attiva contemporaneamente. In questo modo si riduce il numero totale di volte in cui il sistema deve riattivare il dispositivo, riducendo così il consumo della batteria. A partire da Android 4.4 (livello API 19), tutte le sveglie ripetute sono sveglie inesatte. Tieni presente che, anche se setInexactRepeating() rappresenta un miglioramento rispetto a setRepeating(), può comunque sovraccaricare un server se ogni istanza di un'app contatta il server più o meno contemporaneamente. Perciò, per le richieste di rete, aggiungi un po' di casualità agli allarmi, come spiegato in precedenza.

  • Se possibile, evita di basare la sveglia sull'ora dell'orologio.

    La ripetizione degli allarmi basati su un tempo di attivazione preciso non funziona correttamente. Se puoi, utilizza ELAPSED_REALTIME. I diversi tipi di allarme sono descritti più dettagliatamente nella sezione seguente.