AlarmManager) ti consentono di eseguire operazioni basate sul tempo al di fuori della durata della tua applicazione.
Ad esempio, puoi utilizzare una sveglia per avviare un'operazione a lunga esecuzione, come l'avvio di un servizio una volta al giorno per scaricare le previsioni del meteo.
Le sveglie hanno le seguenti caratteristiche:
Consentono di attivare gli intent a orari e/o intervalli prestabiliti.
Puoi utilizzarli insieme ai broadcast receiver per pianificare job o WorkRequest per eseguire altre operazioni.
Operano al di fuori della tua applicazione, quindi puoi utilizzarli per attivare eventi o azioni anche quando l'app non è in esecuzione e anche se il dispositivo è in modalità di sospensione.
Ti aiutano a ridurre al minimo i requisiti delle risorse della tua app. Puoi pianificare le operazioni senza fare affidamento su timer o servizi in esecuzione continua.
Imposta una sveglia non esatta
Quando un'app imposta una sveglia imprecisa, il sistema la attiva in un momento futuro. Le sveglie imprecise forniscono alcune garanzie in merito alla tempistica di attivazione della sveglia, rispettando al contempo le limitazioni per il risparmio della batteria, come Doze.
Gli sviluppatori possono sfruttare le seguenti garanzie dell'API per personalizzare la tempistica di attivazione degli allarmi imprecisi.
Attivare una sveglia dopo un'ora specifica
Se la tua app chiama set(),
setInexactRepeating()
o setAndAllowWhileIdle(),
la sveglia non suona mai prima dell'orario di attivazione fornito.
Su Android 12 (livello API 31) e versioni successive, il sistema attiva la sveglia entro un'ora dall'orario di attivazione fornito, a meno che non siano attive limitazioni per il risparmio della batteria, come il risparmio energetico o la modalità Sospensione.
Attivare una sveglia durante un intervallo di tempo
Se la tua app chiama setWindow(), la sveglia non suona mai prima dell'ora di attivazione
fornita. A meno che non siano in vigore limitazioni per il risparmio della batteria, la sveglia viene attivata entro la finestra temporale specificata, a partire dall'ora di attivazione indicata.
Se la tua app ha come target Android 12 o versioni successive, il sistema può ritardare
l'attivazione di una sveglia imprecisa con finestra temporale di almeno 10 minuti. Per questo motivo, i valori parametro windowLengthMillis inferiori a 600000 vengono in genere ritagliati su 600000. Il sistema potrebbe supportare finestre più piccole, soprattutto se
la sveglia è programmata per essere attivata nel prossimo futuro.
Attivare una sveglia ripetuta a intervalli approssimativamente regolari
Se la tua app chiama setInexactRepeating(),
il sistema attiva più sveglie:
- La prima sveglia suona entro la finestra temporale specificata, a partire dall'ora di attivazione specificata.
- Le sveglie successive di solito suonano dopo che è trascorso l'intervallo di tempo specificato. Il tempo tra due attivazioni consecutive dell'allarme può variare.
Imposta una sveglia esatta
Il sistema attiva una sveglia esatta in un momento preciso nel futuro.
La maggior parte delle app può pianificare attività ed eventi utilizzando allarmi imprecisi per completare diversi casi d'uso comuni. Se la funzionalità di base della tua app dipende da una sveglia temporizzata in modo preciso, ad esempio per un'app sveglia o un'app calendario, puoi utilizzare una sveglia esatta.
Casi d'uso che potrebbero non richiedere sveglie esatte
Di seguito sono riportati i flussi di lavoro comuni che potrebbero non richiedere una sveglia esatta:
- Pianificazione di operazioni di temporizzazione durante il ciclo di vita dell'app
- La classe
Handlerinclude diversi metodi validi per gestire le operazioni di temporizzazione, ad esempio l'esecuzione di un'attività ogni n secondi, mentre l'app è attiva:postAtTime()epostDelayed(). Tieni presente che queste API si basano sul tempo di attività del sistema e non sul tempo reale. - Operazioni programmate in background, come l'aggiornamento dell'app e il caricamento dei log
WorkManagerconsente di pianificare attività periodiche sensibili al fattore tempo. Puoi fornire un intervallo di ripetizione eflexInterval(minimo 15 minuti) per definire un runtime granulare per il lavoro.- Azione specificata dall'utente che deve essere eseguita dopo un periodo di tempo specifico (anche se il sistema è in stato di inattività)
- Utilizza una sveglia non esatta. In particolare, chiama
setAndAllowWhileIdle(). - Azione specificata dall'utente che deve essere eseguita dopo un determinato periodo di tempo
- Utilizza una sveglia non esatta. In particolare, chiama
set(). - Azione specificata dall'utente che può verificarsi entro un intervallo di tempo specificato
- Utilizza una sveglia non esatta. In particolare, chiama
setWindow(). Tieni presente che, se la tua app ha come target Android 12 o versioni successive, la durata minima consentita della finestra è di 10 minuti.
Modi per 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 gestiscano attività più urgenti, ma richiedano più risorse di sistema.
setExact()Attiva una sveglia in un momento quasi preciso nel futuro, a condizione che non siano in vigore altre misure di risparmio della batteria.
Utilizza questo metodo per impostare sveglie esatte, a meno che il lavoro della tua app non sia fondamentale per l'utente.
setExactAndAllowWhileIdle()Attiva una sveglia in un momento quasi preciso nel futuro, anche se sono attive misure di risparmio energetico.
setAlarmClock()Attivare una sveglia a un'ora precisa nel futuro. Poiché queste sveglie sono molto visibili agli utenti, il sistema non ne modifica mai l'orario di attivazione. Il sistema identifica queste sveglie come le più importanti e, se necessario, esce dalle modalità a basso consumo per attivarle.
Consumo di risorse di sistema
Quando il sistema attiva le sveglie esatte impostate dalla tua app, il dispositivo consuma molte risorse, ad esempio la batteria, soprattutto se è in modalità di risparmio energetico. Inoltre, il sistema non può raggruppare facilmente queste richieste per utilizzare le risorse in modo più efficiente.
Ti consigliamo vivamente di creare una sveglia non esatta ogni volta che è possibile. Per eseguire un lavoro più lungo, pianificalo utilizzando WorkManager o JobScheduler dal BroadcastReceiver della sveglia. Per eseguire il lavoro mentre
il dispositivo è in modalità di sospensione, crea una sveglia inesatta utilizzando
setAndAllowWhileIdle()
e avvia un job dalla sveglia.
Dichiara l'autorizzazione Sveglia esatta appropriata
Se la tua app ha come target Android 12 o versioni successive, devi ottenere l'accesso speciale per le app "Sveglie e promemoria". Per farlo, dichiara l'autorizzazione
SCHEDULE_EXACT_ALARM
nel file manifest dell'app, come mostrato nello snippet di codice seguente:
<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 entrambe 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 utilizzare le sveglie esatte e dichiarare l'autorizzazione SCHEDULE_EXACT_ALARM o USE_EXACT_ALARM solo se una funzione rivolta agli utenti della tua app richiede azioni temporizzate in modo preciso.
USE_EXACT_ALARM
- Concessa automaticamente
- Non può essere revocato dall'utente
- Soggetto a una norma di Google Play imminente
- Casi d'uso limitati
SCHEDULE_EXACT_ALARM
- Concessa dall'utente
- Insieme più ampio di casi d'uso
- Le app devono confermare che l'autorizzazione non è stata revocata
L'autorizzazione SCHEDULE_EXACT_ALARM non viene concessa preventivamente alle nuove installazioni di app che hanno come target Android 13 (livello API 33) e versioni successive. Se un utente trasferisce i dati dell'app
su 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 il dispositivo esegue l'upgrade ad Android 14.
Nota: se la sveglia esatta viene impostata utilizzando un oggetto OnAlarmListener, ad esempio con l'API setExact, l'autorizzazione SCHEDULE_EXACT_ALARM non è richiesta.
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 sia 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. Quando l'autorizzazione SCHEDULE_EXACT_ALARM viene revocata per la tua app, quest'ultima si arresta e tutte le sveglie esatte future vengono annullate. Ciò significa anche che il valore restituito da canScheduleExactAlarms() rimane valido per l'intero ciclo di vita della tua app.
Quando alla tua app viene concessa l'autorizzazione SCHEDULE_EXACT_ALARMS, il sistema le invia la trasmissione ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED. L'app deve implementare un broadcast receiver che esegua le seguenti operazioni:
- Conferma che la tua app dispone ancora dell'accesso speciale. Per farlo, chiama
canScheduleExactAlarms(). Questo controllo protegge la tua app nel caso in cui l'utente conceda l'autorizzazione all'app e poi la revochi quasi immediatamente. - Ripianifica le sveglie esatte necessarie per l'app, in base al suo stato attuale.
Questa logica dovrebbe essere simile a quella che l'app esegue quando riceve la trasmissione
ACTION_BOOT_COMPLETED.
Chiedi agli utenti di concedere l'autorizzazione SCHEDULE_EXACT_ALARM
Se necessario, puoi indirizzare gli utenti alla schermata Sveglie e promemoria nelle impostazioni di sistema, come mostrato nella Figura 1. Per farlo, segui questa procedura.
- Nell'interfaccia utente della tua app, spiega all'utente perché l'app deve programmare sveglie esatte.
- Richiama un intent che includa l'azione di intent
ACTION_REQUEST_SCHEDULE_EXACT_ALARM.
Imposta una sveglia ricorrente
Le sveglie ripetute consentono al sistema di inviare notifiche alla tua app in base a una pianificazione ricorrente.
Una sveglia progettata male può causare il consumo della batteria e un carico significativo sui server. Per questo motivo, su Android 4.4 (livello API 19) e versioni successive, tutte le sveglie ripetute sono sveglie imprecise.
Una sveglia ripetuta ha le seguenti caratteristiche:
Un tipo di allarme. Per saperne di più, consulta Scegli un tipo di allarme.
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 pending intent che si attiva quando viene attivata la sveglia. Quando imposti un secondo allarme che utilizza lo stesso pending intent, questo sostituisce l'allarme originale.
Per annullare un PendingIntent(), passa
FLAG_NO_CREATE
a PendingIntent.getService()
per ottenere un'istanza dell'intent (se esiste), quindi passa l'intent 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 allarme
Una delle prime considerazioni sull'utilizzo di una sveglia ripetuta è il tipo da utilizzare.
Esistono due tipi generali di orologi per le sveglie: "tempo reale trascorso" e "orologio in tempo reale" (RTC). Il tempo reale trascorso utilizza come riferimento il "tempo trascorso dall'avvio del sistema", mentre l'orologio in tempo reale utilizza l'ora UTC (orologio da parete). Ciò significa che il tempo reale trascorso è adatto per impostare una sveglia in base al passare del tempo (ad esempio, una sveglia che suona ogni 30 secondi), poiché non è influenzato dal fuso orario o dalle impostazioni internazionali. Il tipo di orologio in tempo reale è più adatto per le sveglie che dipendono dalle impostazioni internazionali correnti.
Entrambi i tipi hanno una versione "wakeup", che indica di riattivare la CPU del dispositivo se lo schermo è spento. In questo modo, la sveglia si attiva all'ora pianificata. Questa opzione è utile se la tua app ha una dipendenza temporale. Ad esempio, se ha una finestra limitata per eseguire una determinata operazione. Se non utilizzi la versione wakeup del tipo di sveglia, tutte le sveglie ripetute verranno attivate alla successiva attivazione del dispositivo.
Se hai semplicemente bisogno che la sveglia si attivi a un intervallo specifico (ad esempio, ogni mezz'ora), utilizza uno dei tipi di tempo reale trascorso. In generale, questa è la scelta migliore.
Se hai bisogno che la sveglia si attivi in un momento specifico della giornata, 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 bene in altre impostazioni internazionali e, se l'utente modifica l'impostazione dell'ora del dispositivo, potrebbe causare un comportamento imprevisto nell'app. Inoltre, l'utilizzo di un tipo di sveglia con orologio in tempo reale non è scalabile, come discusso sopra. Se possibile, ti consigliamo di utilizzare una sveglia "tempo reale trascorso".
Ecco l'elenco dei tipi:
ELAPSED_REALTIME: Attiva il pending intent in base al tempo trascorso dall'avvio del dispositivo, ma non lo riattiva. Il tempo trascorso include l'eventuale tempo in cui il dispositivo era in modalità di sospensione.ELAPSED_REALTIME_WAKEUP: attiva il dispositivo e attiva il pending intent dopo che è trascorso il periodo di tempo specificato dall'avvio del dispositivo.RTC: attiva il pending intent all'ora specificata, ma non riattiva il dispositivo.RTC_WAKEUP: attiva il dispositivo per attivare il pending intent all'ora specificata.
Esempi di sveglie con tempo reale trascorso
Ecco alcuni esempi di utilizzo di ELAPSED_REALTIME_WAKEUP
Attiva il dispositivo per attivare la sveglia tra 30 minuti e ogni 30 minuti successivi:
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);
Attiva il dispositivo per attivare una sveglia una tantum (non ripetuta) tra 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 con orologio in tempo reale
Ecco alcuni esempi di utilizzo di RTC_WAKEUP.
Riattiva il dispositivo per attivare la sveglia alle 14:00 circa 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);
Riattiva il dispositivo per attivare la sveglia esattamente alle 08:30 e ogni 20 minuti successivi:
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 il livello di precisione della sveglia
Come descritto in precedenza, la scelta del tipo di allarme è spesso il primo passaggio per la creazione di un allarme. Un'ulteriore distinzione riguarda la precisione con cui deve essere attivato l'allarme. Per la maggior parte delle app,
setInexactRepeating()
è la scelta giusta. Quando utilizzi questo metodo, Android sincronizza più sveglie ripetute imprecise e le attiva contemporaneamente. In questo modo, il consumo della batteria si riduce.
Se possibile, evita di utilizzare le sveglie esatte. Tuttavia, per le rare app che hanno requisiti di tempo rigidi, puoi impostare una sveglia esatta chiamando setRepeating().
Con setInexactRepeating(), non puoi specificare un intervallo personalizzato come puoi fare con setRepeating().
Devi utilizzare una delle costanti di intervallo, ad esempio INTERVAL_FIFTEEN_MINUTES, INTERVAL_DAY e così via. Per l'elenco completo, consulta AlarmManager.
Annullare una sveglia
A seconda dell'app, potresti voler includere la possibilità di annullare la sveglia.
Per annullare una sveglia, chiama cancel() su Alarm Manager, passando l'PendingIntent che non vuoi più attivare. 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); }
Avviare 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 ripetuta se l'utente riavvia il dispositivo. In questo modo, la AlarmManager continuerà a svolgere la sua attività senza che l'utente debba riavviare manualmente la sveglia.
Procedi nel modo seguente:
Imposta l'autorizzazione
RECEIVE_BOOT_COMPLETEDnel manifest dell'applicazione. In questo modo, l'app può ricevere l'intentACTION_BOOT_COMPLETEDche viene trasmesso dopo che il sistema ha terminato l'avvio (funziona solo se l'app è già stata avviata dall'utente almeno una volta):<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>Implementa un
BroadcastReceiverper 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. } } }
Aggiungi il ricevitore 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 broadcast receiver di avvio è impostato su
android:enabled="false". Ciò significa che il ricevitore non verrà chiamato a meno che l'applicazione non lo attivi esplicitamente. In questo modo, si evita che il broadcast receiver di avvio venga chiamato inutilmente. Puoi attivare un broadcast receiver (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 attivato il broadcast receiver in questo modo, rimarrà attivo anche se l'utente riavvia il dispositivo. In altre parole, l'attivazione programmatica del ricevitore esegue l'override dell'impostazione del manifest, anche dopo i riavvii. Il ricevitore rimarrà attivo finché non verrà disattivato dall'app. 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);
Attivare le sveglie mentre il dispositivo è in modalità Sospensione
I dispositivi con Android 6.0 (livello API 23) supportano la modalità Doze, che contribuisce a prolungare la durata della batteria del dispositivo. Le sveglie non si attivano quando il dispositivo è in modalità Sospensione Le sveglie programmate vengono posticipate 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.
Utilizza l'API WorkManager, progettata per eseguire il lavoro in background. Puoi indicare che il sistema deve accelerare il lavoro in modo che venga completato il prima possibile. Per saperne di più, consulta Pianifica le attività con WorkManager
Best practice
Ogni scelta che fai nella progettazione della sveglia ripetuta può avere conseguenze sul modo in cui la tua app utilizza (o abusa) delle risorse di sistema. Ad esempio, immagina un'app molto utilizzata che si sincronizza con un server. Se l'operazione di sincronizzazione si basa sull'orario e ogni istanza dell'app si sincronizza alle 23:00, il carico sul server potrebbe comportare una latenza elevata o addirittura un "denial of service". Segui queste best practice per l'utilizzo delle sveglie:
Aggiungi casualità (jitter) a tutte le richieste di rete che vengono attivate come risultato di una sveglia ripetuta:
Esegui qualsiasi operazione locale quando viene attivata la sveglia. Per "lavoro locale" si intende qualsiasi operazione che non richiede l'accesso a un server o i dati del server.
Allo stesso tempo, pianifica l'attivazione della sveglia che contiene le richieste di rete in un periodo di tempo casuale.
Riduci al minimo la frequenza degli allarmi.
Non attivare il dispositivo inutilmente (questo comportamento è determinato dal tipo di sveglia, come descritto in Scegli un tipo di sveglia).
Non rendere l'ora di attivazione della sveglia più precisa del necessario.
Utilizza
setInexactRepeating()anzichésetRepeating(). Quando utilizzisetInexactRepeating(), Android sincronizza le sveglie ripetute di 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 imprecise. Tieni presente che, sebbenesetInexactRepeating()sia un miglioramento rispetto asetRepeating(), può comunque sovraccaricare un server se ogni istanza di un'app raggiunge il server nello stesso momento. Pertanto, per le richieste di rete, aggiungi un po' di casualità alle sveglie, come discusso in precedenza.Se possibile, evita di basare l'allarme sull'ora.
Le sveglie ripetute basate su un'ora di attivazione precisa non sono scalabili. Utilizza
ELAPSED_REALTIMEse puoi. I diversi tipi di allarme sono descritti più dettagliatamente nella sezione seguente.