Programmare sveglie

Sveglie (in base al AlarmManager classe) ti daranno la possibilità di eseguire le operazioni basate sul tempo al di fuori della durata della tua applicazione. Ad esempio, potresti utilizzare un allarme per avviare un'operazione a lunga esecuzione, come avviando un servizio una volta al giorno per scaricare una previsione meteo.

Gli allarmi hanno le seguenti caratteristiche:

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

  • Puoi usarli insieme ai broadcast receiver per programmare jobs o WorkRequests per eseguire altre operazioni.

  • Queste funzionano al di fuori della tua applicazione, quindi puoi usarle per attivare di eventi o azioni anche quando l'app non è in esecuzione e il dispositivo addormentato.

  • Ti aiutano a ridurre al minimo i requisiti di risorse della tua app. Puoi programmare senza dover fare affidamento su timer o servizi in esecuzione continua.

di Gemini Advanced.

Impostare una sveglia inesatta

Quando un'app imposta una sveglia inesatta, il sistema a un certo punto invia la sveglia in futuro. Gli allarmi inesatti forniscono alcune garanzie sulla tempistica di l'invio di un rilevatore rispettando le limitazioni relative al risparmio energetico Sospensione.

Gli sviluppatori possono sfruttare le garanzie API riportate di seguito per personalizzare le tempistiche alla consegna inesatta della sveglia.

Inviare una sveglia dopo un orario specifico

Se la tua app chiama set(), setInexactRepeating(), o setAndAllowWhileIdle(), l'allarme non si attiva mai prima dell'orario di attivazione specificato.

Su Android 12 (livello API 31) e versioni successive, il sistema attiva l'allarme entro uno ora del tempo di attivazione specificato, a meno che non siano previste restrizioni per il risparmio energetico come risparmio energetico o Sospensione.

Inviare una sveglia in un intervallo di tempo

Se l'app chiama il numero setWindow(), la sveglia non si attiva mai prima dell'ora fornita il tempo di attivazione. A meno che non ci siano restrizioni al consumo della batteria, l'allarme viene pubblicati nell'intervallo di tempo specificato, a partire dal trigger specificato nel tempo.

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

Inviare una sveglia ricorrente a intervalli circa regolari

Se la tua app chiama setInexactRepeating(), il sistema richiama più sveglie:

  1. La prima sveglia suona nell'intervallo di tempo specificato, a partire dal un determinato momento di attivazione.
  2. Le sveglie successive solitamente suonano dopo l'intervallo di tempo specificato trascorrano. Il tempo tra due chiamate consecutive della sveglia può variare.

Impostare una sveglia esatta

Il sistema attiva una sveglia esatta 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 il servizio principale dipende da una sveglia a tempo preciso, come nel caso di un'app sveglia o un'app di calendario, puoi scegliere di usare invece una sveglia esatta.

Casi d'uso che potrebbero non richiedere sveglie esatte

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

Pianificare le operazioni di sincronizzazione per l'intero ciclo di vita dell'app
Il corso Handler include diversi buoni per gestire le operazioni di temporizzazione, come l'esecuzione di determinate operazioni ogni n secondi mentre l'app è attiva: postAtTime() e postDelayed(). Tieni presente che queste API si basano sull'uptime del sistema e non in tempo reale.
Operazioni in background pianificate, ad esempio l'aggiornamento dell'app e il caricamento dei log
WorkManager consente di pianificare periodicamente eventi periodici al lavoro. Puoi fornire un intervallo di ripetizione e flexInterval (minimo 15 minuti) per per definire il runtime granulare per il lavoro.
Azione specificata dall'utente che dovrebbe verificarsi dopo un determinato periodo di tempo (anche se il sistema è in stato di inattività)
Usa una sveglia inesatta. In particolare, richiama setAndAllowWhileIdle()
Azione specificata dall'utente che deve avvenire dopo un intervallo di tempo specifico
Usa una sveglia inesatta. In particolare, richiama set()
Azione specificata dall'utente che può verificarsi entro un periodo di tempo specificato
Usa una sveglia inesatta. In particolare, richiama setWindow() Tieni presente che, se la tua app ha come target Android 12 o versioni successive, consentita è di 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 pubblichino critici in termini di tempo, ma richiedono più risorse di sistema.

setExact()

Consente di attivare una sveglia a un'ora quasi precisa in futuro, a condizione che le misure di risparmio energetico non sono attive.

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

setExactAndAllowWhileIdle()

Consente di attivare una sveglia a un'ora quasi precisa nel futuro, anche se a basso consumo misure correttive siano in vigore.

setAlarmClock()

Consente di attivare una sveglia a un'ora precisa nel futuro. Perché questi allarmi sono molto visibile agli utenti, il sistema non modifica mai i tempi di consegna. La il sistema identifica questi allarmi come i più critici e lascia a bassa potenza modalità d'allarme se necessario.

Consumo di risorse di sistema

Quando il sistema attiva sveglie esatte impostate dall'app, il dispositivo consuma molta risorse, ad esempio la durata della batteria, soprattutto se è una modalità di risparmio energetico. Inoltre, il sistema non può facilmente raggruppare queste richieste in batch per utilizzare le risorse in modo più efficiente.

Ti consigliamo vivamente di creare una sveglia inesatta ogni volta che possibile. Per lavorare più a lungo, programmalo utilizzando WorkManager oppure JobScheduler dalla tua sveglia BroadcastReceiver. Per svolgere il lavoro il dispositivo è in modalità Sospensione, crea una sveglia inesatta utilizzando setAndAllowWhileIdle(), e avviare un job dal rilevatore.

Dichiara l'autorizzazione Sveglia esatta appropriata

Se la tua app ha come target Android 12 o versioni successive, devi ottenere il Sveglie e promemoria" un accesso speciale alle app. Per farlo, dichiara SCHEDULE_EXACT_ALARM nel file manifest dell'app, come mostrato nello snippet di codice riportato di seguito:

<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 scegliere di: dichiarare la proprietà SCHEDULE_EXACT_ALARM o USE_EXACT_ALARM autorizzazione.

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

Sebbene sia l'autorizzazione SCHEDULE_EXACT_ALARM che quella USE_EXACT_ALARM indicano le stesse capacità, vengono concesse in modo diverso e supportano e casi d'uso specifici. L'app deve utilizzare sveglie esatte e dichiarare Autorizzazione SCHEDULE_EXACT_ALARM o USE_EXACT_ALARM, solo se rivolta all'utente nella tua app richiedono azioni temporizzate in modo preciso.

USE_EXACT_ALARM

SCHEDULE_EXACT_ALARM

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

L'autorizzazione SCHEDULE_EXACT_ALARM non è stata pre-concessa alle nuove installazioni di app destinate ad Android 13 (livello API 33) e versioni successive. Se un utente trasferisce l'app a un dispositivo con Android 14 tramite un'operazione di backup e ripristino, L'autorizzazione SCHEDULE_EXACT_ALARM verrà negata sul nuovo dispositivo. Tuttavia, se un'app esistente dispone già di questa autorizzazione, verrà pre-concessa quando upgrade dei dispositivi ad Android 14.

Nota: se la sveglia esatta è stata impostata utilizzando un OnAlarmListener: come con setExact nell'API, non è richiesta l'autorizzazione SCHEDULE_EXACT_ALARM.

Utilizzo dell'autorizzazione SCHEDULE_EXACT_ALARM

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

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

Quando alla tua app viene concessa l'autorizzazione SCHEDULE_EXACT_ALARMS, viene che il sistema invia ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED la trasmissione. L'app deve implementare una trasmissione ricevitore che esegue seguenti:

  1. Verifica che la tua app abbia ancora accesso speciale per le app. A questo scopo, chiama canScheduleExactAlarms() Questo controllo protegge la tua app dal caso in cui l'utente conceda all'app autorizzazione, la revoca quasi immediatamente dopo.
  2. Riprogramma tutte le sveglie esatte di cui la tua app ha bisogno, in base al suo stato attuale. Questa logica dovrebbe essere simile a quella dell'app quando riceve l'app ACTION_BOOT_COMPLETED la trasmissione.

Chiedi agli utenti di concedere l'autorizzazione SCHEDULE_EXACT_ALARM

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

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

  1. Nell'interfaccia utente dell'app, spiega all'utente perché quest'ultima deve programmare sveglie.
  2. Richiamare un intent che includa ACTION_REQUEST_SCHEDULE_EXACT_ALARM azione basata sull'intent.

Impostare una sveglia ricorrente

La ripetizione di sveglie consente al sistema di inviare una notifica all'app su un evento ricorrente programmazione.

Un rilevatore non progettato correttamente può causare un consumo eccessivo della batteria e un carico significativo server web. Per questo motivo, su Android 4.4 (livello API 19) e versioni successive, le sveglie ripetute sono sveglie inesatte.

Una sveglia ricorrente ha le seguenti caratteristiche:

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

  • Un'ora di attivazione. Se l'ora di attivazione specificata è nel passato, la sveglia si attiva immediatamente.

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

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

Per annullare un PendingIntent(), pass FLAG_NO_CREATE a PendingIntent.getService() per ottenere un'istanza dell'intent (se esistente), poi passalo 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);
}

Scegliere un tipo di sveglia

Una delle prime considerazioni da fare quando si utilizza una sveglia ricorrente è il tipo dovrebbe essere.

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

Entrambi i tipi hanno la funzione "sveglia" che indica di riattivare la CPU del dispositivo che lo schermo è spento. In questo modo ti assicuri che la sveglia si attivi all'ora programmata. È utile se la tua app ha una dipendenza di tempo. Ad esempio, se ha a una finestra limitata per eseguire una determinata operazione. Se non utilizzi versione riattivazione del tipo di sveglia, verranno attivate tutte le sveglie ripetute alla successiva riattivazione del dispositivo.

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

Se vuoi che la sveglia si attivi in una determinata ora del giorno, scegline una dei tipi di orologio in tempo reale basati sull'orologio. Tieni presente, tuttavia, che questo approccio presentano alcuni svantaggi. L'app potrebbe non tradurre correttamente in altre lingue e se Se l'utente modifica l'impostazione dell'ora del dispositivo, potrebbe verificarsi un comportamento imprevisto all'interno dell'app. Anche l'utilizzo di un tipo di sveglia con orologio in tempo reale non si adatta bene alla scala, di cui abbiamo parlato sopra. Ti consigliamo di utilizzare una query "in tempo reale trascorso" sveglia se puoi.

Ecco l'elenco dei tipi:

  • ELAPSED_REALTIME: Attiva l'intent in sospeso in base alla quantità di tempo trascorso da quando il dispositivo è stato si è avviato, ma non riattiva il dispositivo. La il tempo trascorso include il tempo di sospensione del dispositivo.

  • ELAPSED_REALTIME_WAKEUP: Consente di riattivare il dispositivo e attivare l'intent in sospeso dopo la durata specificata sia trascorso del tempo dall'avvio del dispositivo.

  • RTC: Attiva l'intent in sospeso all'ora specificata, ma non riattiva il dispositivo.

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

Esempi di sveglie in tempo reale trascorsi

Ecco alcuni esempi di utilizzo di ELAPSED_REALTIME_WAKEUP

Attiva il dispositivo per attivare l'allarme dopo 30 minuti, e ogni 30 minuti Dopodiché:

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 ripetuta) 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 orologio in tempo reale

Di seguito sono riportati alcuni esempi di utilizzo RTC_WAKEUP

Sveglia il dispositivo per attivare l'allarme alle 14:00 circa e ripeti il comando 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 ogni 20 minuti in seguito:

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);

Decidi quanto deve essere precisa la sveglia

Come descritto in precedenza, la scelta del tipo di allarme spesso è il primo passo creare una sveglia. Un'altra distinzione è il livello di precisione della sveglia in modo adeguato. Per la maggior parte delle app, setInexactRepeating() è la scelta giusta. Se utilizzi questo metodo, Android sincronizza più sveglie e incendi ripetuti inesatti contemporaneamente. In questo modo si riduce il consumo della batteria.

Se possibile, evita di utilizzare sveglie esatte. Tuttavia, per l'app rara che presenta requisiti di tempo, puoi impostare una sveglia esatta chiamando setRepeating()

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

Annulla una sveglia

A seconda dell'app, puoi includere la possibilità di annullare la sveglia. Per annullare una sveglia, chiama il numero cancel() su allarme, passando il Non ti interessa più PendingIntent per l'attivazione. Ad esempio:

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 la tua applicazione per riavviare automaticamente una sveglia ricorrente se l'utente riavvia il dispositivo. Questo garantisce che AlarmManager Continuare a svolgere l’attività senza che l’utente debba riavviare manualmente il rilevatore.

Procedi nel seguente modo:

  1. Imposta la RECEIVE_BOOT_COMPLETED nel file manifest dell'applicazione. In questo modo la tua app può ricevere ACTION_BOOT_COMPLETED trasmesso al termine dell'avvio del sistema (funziona solo se è già stata lanciata dall'utente almeno una volta):

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
  2. Implementare un modello 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 della tua app con un filtro per intent che i filtri nella ACTION_BOOT_COMPLETED azione:

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

    Nota che nel manifest, il ricevitore di avvio è impostato su android:enabled="false". Ciò significa che il destinatario non verranno chiamati a meno che l'applicazione non lo consenta esplicitamente. In questo modo di avvio del ricevitore da chiamate inutilmente. Puoi attivare un ricevitore (ad esempio, se l'utente imposta una sveglia) nel seguente modo:

    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 in questo modo il ricevitore, quest'ultimo rimarrà attivo, anche se l'utente consente di riavviare il dispositivo. In altre parole, abilitare in modo programmatico il ricevitore sostituisce l'impostazione del file manifest, anche tra i riavvii. Il destinatario rimarrà attiva finché l'app non la disattiva. Puoi disattivare un ricevitore (ad esempio, se l'utente annulla una sveglia) nel seguente modo:

    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 sveglie mentre il dispositivo è in modalità Sospensione

I dispositivi che eseguono Android 6.0 (livello API 23) supportano Sospensione che aiuta a prolungare la durata della batteria del dispositivo. Le sveglie non si attivano quando il dispositivo è in carica Modalità Sospensione Tutte le sveglie programmate vengono differite finché il dispositivo non esce dalla modalità Sospensione. Per completare il lavoro anche quando il dispositivo è inattivo, ci sono diverse opzioni disponibili:

  • Imposta una sveglia esatta.

  • Utilizzare l'API WorkManager, creata per eseguire lavoro in background. Puoi indicare che il sistema dovrebbe velocizzare il lavoro in modo affinché il lavoro termini il prima possibile. Per ulteriori informazioni, vedi Pianificare le attività con WorkManager

Best practice

Ogni scelta che fai nella progettazione di una sveglia ripetuta può avere conseguenze nel modo in cui la tua app usa (o viola) le risorse di sistema. Immagina ad esempio molto conosciuta che si sincronizza con un server. Se l'operazione di sincronizzazione è basata sull'orologio ora e ogni istanza dell'app si sincronizza alle 23.00, il carico potrebbe causare un'elevata latenza o persino "denial of service". Segui queste best practice per l'utilizzo delle sveglie:

  • Aggiungi casualità (jitter) a tutte le richieste di rete si attiva in seguito a una sveglia ripetuta:

    • Eseguire operazioni locali quando si attiva l'allarme. "Lavoro locale" significa tutto ciò che non raggiunge un server o non richiede i dati al server.

    • Allo stesso tempo, programma la sveglia che contiene le richieste di rete a in un periodo di tempo casuale.

  • Mantieni la frequenza della sveglia al minimo.

  • Non riattivare il dispositivo inutilmente (questo comportamento è determinato dal di sveglia, come descritto in Scegliere un tipo di sveglia.

  • Non rendere l'ora di attivazione della sveglia più precisa del dovuto.

    Utilizza le funzionalità di setInexactRepeating() anziché setRepeating(). Quando utilizzi setInexactRepeating(), Android sincronizza sveglie ripetute da più app e incendi contemporaneamente. In questo modo si riduce il numero totale di volte in cui il sistema deve riattivare il dispositivo, riducendo il consumo della batteria. A partire da Android 4.4 (Livello API 19), tutti i rilevatori ripetuti sono sveglia inesatta. Nota mentre setInexactRepeating() è un miglioramento rispetto setRepeating(), può comunque sovraccaricare un server se ogni istanza di un'app raggiunge il server all'incirca contemporaneamente. Di conseguenza, per le richieste di rete, aggiungi una certa casualità le sveglie, come spiegato in precedenza.

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

    Le sveglie ripetute basate su un tempo di attivazione preciso non vengono ridimensionate correttamente. Utilizza le funzionalità di ELAPSED_REALTIME se è possibile. Un'altra sveglia descritti più dettagliatamente nella sezione seguente.