AlarmManager
) können Sie zeitbasierte Vorgänge außerhalb der Lebensdauer Ihrer Anwendung ausführen.
Sie können beispielsweise einen Alarm verwenden, um einen Vorgang mit langer Ausführungszeit zu starten, z. B. einen Dienst einmal täglich zu starten, um eine Wettervorhersage herunterzuladen.
Alarme haben folgende Eigenschaften:
Damit können Sie Intents zu bestimmten Zeiten und/oder in bestimmten Intervallen auslösen.
Sie können sie in Verbindung mit Broadcast-Empfängern verwenden, um Jobs oder WorkRequests zu planen, um andere Vorgänge auszuführen.
Sie werden außerhalb Ihrer Anwendung ausgeführt. Sie können damit Ereignisse oder Aktionen auslösen, auch wenn Ihre App nicht ausgeführt wird und selbst wenn sich das Gerät im Ruhemodus befindet.
Sie helfen Ihnen, die Ressourcenanforderungen Ihrer App zu minimieren. Sie können Vorgänge planen, ohne auf Timer oder kontinuierlich ausgeführte Dienste angewiesen zu sein.
Ungenauen Wecker stellen
Wenn eine App einen ungenauen Alarm einstellt, wird der Alarm vom System irgendwann in der Zukunft ausgelöst. Ungenau definierte Wecker bieten einige Garantien hinsichtlich des Zeitpunkts der Weckerauslösung und berücksichtigen gleichzeitig Akku sparende Einschränkungen wie Doze.
Entwickler können die folgenden API-Garantien nutzen, um den Zeitpunkt der ungenauen Alarmzustellung anzupassen.
Wecker nach einer bestimmten Zeit auslösen
Wenn Ihre App set()
, setInexactRepeating()
oder setAndAllowWhileIdle()
aufruft, wird der Wecker nie vor der angegebenen Auslösezeit ausgelöst.
Unter Android 12 (API-Level 31) und höher wird der Alarm innerhalb einer Stunde nach der angegebenen Triggerzeit ausgelöst, sofern keine Energiesparbeschränkungen wie Energiesparmodus oder Doze aktiv sind.
Wecker in einem Zeitfenster auslösen
Wenn Ihre App setWindow()
aufruft, wird der Wecker nie vor der angegebenen Triggerzeit ausgelöst. Sofern keine Akku-Sparbeschränkungen gelten, wird der Alarm innerhalb des angegebenen Zeitfensters ab der angegebenen Triggerzeit ausgeliefert.
Wenn Ihre App auf Android 12 oder höher ausgerichtet ist, kann das System den Aufruf eines zeitgesteuerten ungenauen Alarms um mindestens 10 Minuten verzögern. Aus diesem Grund werden windowLengthMillis
-Parameterwerte unter 600000
auf 600000
begrenzt.
Wiederkehrenden Wecker in etwa regelmäßigen Abständen auslösen
Wenn Ihre App setInexactRepeating()
aufruft, löst das System mehrere Alarme aus:
- Der erste Alarm wird innerhalb des angegebenen Zeitfensters ab der angegebenen Triggerzeit ausgelöst.
- Nachfolgende Alarme werden in der Regel nach Ablauf des angegebenen Zeitfensters ausgelöst. Die Zeit zwischen zwei aufeinanderfolgenden Aufrufen des Alarms kann variieren.
Exakten Wecker stellen
Das System löst einen genauen Alarm zu einem bestimmten Zeitpunkt in der Zukunft aus.
Die meisten Apps können Aufgaben und Ereignisse mit ungenauen Weckern planen, um mehrere häufige Anwendungsfälle zu erfüllen. Wenn die Hauptfunktion Ihrer App von einem zeitgenauen Alarm abhängt, z. B. bei einer Wecker- oder Kalender-App, ist es in Ordnung, stattdessen einen exakten Alarm zu verwenden.
Anwendungsfälle, die möglicherweise keine exakten Alarme erfordern
In der folgenden Liste sind häufige Workflows aufgeführt, für die kein exakter Alarm erforderlich ist:
- Timing-Vorgänge während der Lebensdauer Ihrer App planen
- Die Klasse
Handler
enthält mehrere gute Methoden zum Verarbeiten von Zeitvorgängen, z. B. zum Ausführen einer Aufgabe alle n Sekunden, während Ihre App aktiv ist:postAtTime()
undpostDelayed()
. Diese APIs basieren auf der Systembetriebszeit und nicht auf der Echtzeit. - Geplante Aufgaben im Hintergrund, z. B. das Aktualisieren Ihrer App und das Hochladen von Protokollen
WorkManager
bietet eine Möglichkeit, zeitkritische periodische Aufgaben zu planen. Sie können ein Wiederholungsintervall undflexInterval
(mindestens 15 Minuten) angeben, um die Laufzeit des Jobs genauer zu definieren.- Vom Nutzer angegebene Aktion, die nach einer bestimmten Zeit ausgeführt werden soll (auch wenn sich das System im Leerlauf befindet)
- Einen ungenauen Alarm verwenden. Rufen Sie dazu
setAndAllowWhileIdle()
auf. - Vom Nutzer angegebene Aktion, die nach einer bestimmten Zeit ausgeführt werden soll
- Einen ungenauen Alarm verwenden. Rufen Sie dazu
set()
auf. - Vom Nutzer angegebene Aktion, die innerhalb eines bestimmten Zeitfensters ausgeführt werden kann
- Einen ungenauen Alarm verwenden. Rufen Sie dazu
setWindow()
auf. Wenn Ihre App auf Android 12 oder höher ausgerichtet ist, beträgt die kleinste zulässige Fensterlänge 10 Minuten.
Möglichkeiten zum Stellen eines exakten Weckers
Ihre App kann genaue Wecker mit einer der folgenden Methoden stellen. Diese Methoden sind so angeordnet, dass die Methoden, die sich weiter unten in der Liste befinden, zeitkritischere Aufgaben ausführen, aber mehr Systemressourcen benötigen.
setExact()
Einen Alarm zu einem fast genauen Zeitpunkt in der Zukunft auslösen, sofern keine anderen Maßnahmen zur Akkuoptimierung aktiv sind.
Verwenden Sie diese Methode, um exakte Alarme festzulegen, es sei denn, die Arbeit Ihrer App ist für den Nutzer zeitkritisch.
setExactAndAllowWhileIdle()
Einen Alarm zu einem nahezu präzisen Zeitpunkt in der Zukunft auslösen, auch wenn Energiesparmaßnahmen aktiv sind.
setAlarmClock()
Einen Wecker zu einer bestimmten Zeit in der Zukunft stellen. Da diese Benachrichtigungen für Nutzer gut sichtbar sind, wird ihre Zustellzeit vom System nie angepasst. Das System identifiziert diese Alarme als die wichtigsten und beendet bei Bedarf den Energiesparmodus, um sie zu senden.
Systemressourcenverbrauch
Wenn das System genaue Alarme auslöst, die von Ihrer App festgelegt wurden, verbraucht das Gerät viele Ressourcen, z. B. Akku, insbesondere wenn es sich in einem Energiesparmodus befindet. Außerdem kann das System diese Anfragen nicht einfach in Batches zusammenfassen, um Ressourcen effizienter zu nutzen.
Es wird dringend empfohlen, nach Möglichkeit einen ungenauen Alarm zu erstellen. Wenn Sie längere Aufgaben ausführen möchten, planen Sie sie über WorkManager
oder JobScheduler
über das BroadcastReceiver
Ihres Weckers. Wenn Sie Aufgaben ausführen möchten, während sich das Gerät im Doze-Modus befindet, erstellen Sie mit setAndAllowWhileIdle()
einen ungenauen Alarm und starten Sie einen Job über den Alarm.
Entsprechende Berechtigung „Exakter Alarm“ deklarieren
Wenn Ihre App auf Android 12 oder höher ausgerichtet ist, müssen Sie den speziellen App-Zugriff „Alarme & Erinnerungen“ erhalten. Dazu deklarieren Sie die Berechtigung SCHEDULE_EXACT_ALARM
in der Manifestdatei Ihrer App, wie im folgenden Code-Snippet gezeigt:
<manifest ...> <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/> <application ...> ... </application> </manifest>
Wenn Ihre App auf Android 13 (API‑Level 33) oder höher ausgerichtet ist, können Sie entweder die Berechtigung SCHEDULE_EXACT_ALARM
oder die Berechtigung USE_EXACT_ALARM
deklarieren.
<manifest ...> <uses-permission android:name="android.permission.USE_EXACT_ALARM"/> <application ...> ... </application> </manifest>
Die Berechtigungen SCHEDULE_EXACT_ALARM
und USE_EXACT_ALARM
signalisieren zwar dieselben Funktionen, werden aber unterschiedlich erteilt und unterstützen unterschiedliche Anwendungsfälle. Ihre App sollte exakte Alarme verwenden und entweder die Berechtigung SCHEDULE_EXACT_ALARM
oder USE_EXACT_ALARM
deklarieren, nur wenn eine für den Nutzer sichtbare Funktion in Ihrer App zeitgenaue Aktionen erfordert.
USE_EXACT_ALARM
- Automatisch gewährt
- Kann vom Nutzer nicht widerrufen werden
- Unterliegt einer bevorstehenden Google Play-Richtlinie
- Eingeschränkte Anwendungsfälle
SCHEDULE_EXACT_ALARM
- Vom Nutzer gewährt
- Größere Auswahl an Anwendungsfällen
- Apps sollten bestätigen, dass die Berechtigung nicht widerrufen wurde
Die Berechtigung SCHEDULE_EXACT_ALARM
wird bei Neuinstallationen von Apps, die auf Android 13 (API‑Level 33) und höher ausgerichtet sind, nicht vorab erteilt. Wenn ein Nutzer App-Daten über eine Sicherung und Wiederherstellung auf ein Gerät mit Android 14 überträgt, wird die Berechtigung SCHEDULE_EXACT_ALARM
auf dem neuen Gerät verweigert. Wenn eine vorhandene App diese Berechtigung jedoch bereits hat, wird sie vorab gewährt, wenn das Gerät auf Android 14 aktualisiert wird.
Hinweis: Wenn der genaue Alarm mit einem OnAlarmListener
-Objekt festgelegt wird, z. B. mit der setExact
-API, ist die Berechtigung SCHEDULE_EXACT_ALARM
nicht erforderlich.
Verwendung der Berechtigung SCHEDULE_EXACT_ALARM
Im Gegensatz zu USE_EXACT_ALARM
muss die Berechtigung SCHEDULE_EXACT_ALARM
vom Nutzer erteilt werden. Sowohl der Nutzer als auch das System können die Berechtigung SCHEDULE_EXACT_ALARM
widerrufen.
Rufen Sie canScheduleExactAlarms()
auf, bevor Sie versuchen, einen exakten Alarm einzurichten, um zu prüfen, ob die Berechtigung für Ihre App gewährt wurde. Wenn die Berechtigung SCHEDULE_EXACT_ALARM
für Ihre App widerrufen wird, wird Ihre App beendet und alle zukünftigen exakten Alarme werden abgebrochen. Das bedeutet auch, dass der von canScheduleExactAlarms()
zurückgegebene Wert für den gesamten Lebenszyklus Ihrer App gültig bleibt.
Wenn Ihrer App die Berechtigung SCHEDULE_EXACT_ALARMS
erteilt wird, sendet das System ihr den Broadcast ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED
. Ihre App sollte einen Broadcast-Receiver implementieren, der Folgendes ausführt:
- Bestätigt, dass Ihre App weiterhin den speziellen App-Zugriff hat. Rufen Sie dazu
canScheduleExactAlarms()
auf. Diese Prüfung schützt Ihre App vor dem Fall, dass der Nutzer Ihrer App die Berechtigung erteilt und sie dann fast sofort wieder entzieht. - Verschiebt alle genauen Weckrufe, die Ihre App benötigt, basierend auf dem aktuellen Status.
Diese Logik sollte der Logik entsprechen, die Ihre App verwendet, wenn sie den Broadcast
ACTION_BOOT_COMPLETED
empfängt.
Nutzer auffordern, die Berechtigung SCHEDULE_EXACT_ALARM
zu erteilen
Bei Bedarf können Sie Nutzer zu den Weckern und Erinnerungen in den Systemeinstellungen weiterleiten (siehe Abbildung 1). Führen Sie dazu folgende Schritte aus:
- Erklären Sie dem Nutzer in der Benutzeroberfläche Ihrer App, warum Ihre App genaue Alarme planen muss.
- Rufen Sie ein Intent auf, das die Intent-Aktion
ACTION_REQUEST_SCHEDULE_EXACT_ALARM
enthält.
Wiederkehrenden Wecker stellen
Wiederholende Weckrufe ermöglichen es dem System, Ihre App in regelmäßigen Abständen zu benachrichtigen.
Ein schlecht konzipierter Alarm kann den Akku entladen und die Server erheblich belasten. Aus diesem Grund sind alle sich wiederholenden Wecker unter Android 4.4 (API-Ebene 19) und höher ungenaue Wecker.
Ein sich wiederholender Wecker hat die folgenden Eigenschaften:
Einen Alarmtyp. Weitere Informationen finden Sie unter Alarmtyp auswählen.
Eine Triggerzeit. Wenn der von Ihnen angegebene Trigger-Zeitpunkt in der Vergangenheit liegt, wird der Alarm sofort ausgelöst.
Das Intervall des Weckers. Beispiele: einmal täglich, jede Stunde oder alle 5 Minuten.
Ein ausstehender Intent, der ausgelöst wird, wenn der Wecker klingelt. Wenn Sie einen zweiten Wecker mit demselben ausstehenden Intent stellen, wird der ursprüngliche Wecker ersetzt.
Wenn Sie einen PendingIntent()
abbrechen möchten, übergeben Sie FLAG_NO_CREATE
an PendingIntent.getService()
, um eine Instanz des Intents abzurufen (falls er vorhanden ist), und übergeben Sie diesen Intent dann an 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); }
Weckertyp auswählen
Eine der ersten Überlegungen bei der Verwendung eines sich wiederholenden Alarms ist, welcher Typ er sein soll.
Es gibt zwei allgemeine Uhrentypen für Wecker: „abgelaufene Echtzeit“ und „Echtzeituhr“ (RTC). Die verstrichene Echtzeit verwendet die „Zeit seit dem Systemstart“ als Referenz, während die Echtzeituhr die UTC-Zeit (Wanduhr) verwendet. Daher eignet sich die abgelaufene Echtzeit zum Stellen eines Alarms basierend auf dem Zeitablauf (z. B. ein Alarm, der alle 30 Sekunden ausgelöst wird), da sie nicht von Zeitzone oder Gebietsschema beeinflusst wird. Der Echtzeituhrtyp eignet sich besser für Alarme, die vom aktuellen Gebietsschema abhängen.
Beide Typen haben eine „Wakeup“-Version, die die CPU des Geräts aktiviert, wenn das Display ausgeschaltet ist. So wird sichergestellt, dass der Wecker zur geplanten Zeit ausgelöst wird. Das ist nützlich, wenn Ihre App zeitabhängig ist. Das kann z. B. der Fall sein, wenn für einen bestimmten Vorgang nur ein begrenzter Zeitraum zur Verfügung steht. Wenn Sie nicht die Weckversion Ihres Alarmtyps verwenden, werden alle sich wiederholenden Alarme ausgelöst, wenn Ihr Gerät das nächste Mal aktiviert wird.
Wenn der Alarm in einem bestimmten Intervall ausgelöst werden soll (z. B. alle halbe Stunde), verwenden Sie einen der Typen für die verstrichene Echtzeit. Im Allgemeinen ist dies die bessere Wahl.
Wenn der Alarm zu einer bestimmten Tageszeit ausgelöst werden soll, wählen Sie einen der Echtzeituhrtypen auf Grundlage der Uhr aus. Dieser Ansatz kann jedoch einige Nachteile haben. Die App lässt sich möglicherweise nicht gut in andere Sprachen übersetzen. Wenn der Nutzer die Zeiteinstellung des Geräts ändert, kann dies zu unerwartetem Verhalten in Ihrer App führen. Die Verwendung eines Echtzeituhr-Alarmtyps ist, wie oben beschrieben, auch nicht gut skalierbar. Wir empfehlen, nach Möglichkeit einen Alarm für die „abgelaufene Echtzeit“ zu verwenden.
Hier ist die Liste der Typen:
ELAPSED_REALTIME
: Löst den ausstehenden Intent basierend auf der Zeit seit dem Start des Geräts aus, weckt das Gerät aber nicht auf. Die verstrichene Zeit umfasst auch die Zeit, in der sich das Gerät im Ruhemodus befand.ELAPSED_REALTIME_WAKEUP
: Das Gerät wird aktiviert und der ausstehende Intent wird ausgelöst, nachdem die angegebene Zeit seit dem Gerätestart verstrichen ist.RTC
: Löst den ausstehenden Intent zur angegebenen Zeit aus, aktiviert das Gerät aber nicht.RTC_WAKEUP
: Weckt das Gerät auf, um den ausstehenden Intent zum angegebenen Zeitpunkt auszulösen.
Beispiele für Wecker mit abgelaufener Echtzeit
Hier einige Beispiele für die Verwendung von ELAPSED_REALTIME_WAKEUP
:
Wecke das Gerät auf, damit der Wecker in 30 Minuten und danach alle 30 Minuten klingelt:
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);
Gerät aktivieren, um einen einmaligen (nicht wiederholten) Alarm in einer Minute auszulösen:
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);
Beispiele für Echtzeituhr-Alarme
Hier einige Beispiele für die Verwendung von RTC_WAKEUP
:
Wecke das Gerät, um den Alarm um ca. 14:00 Uhr auszulösen, und wiederhole den Vorgang einmal täglich zur selben Zeit:
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);
Wecke das Gerät auf, um den Wecker um genau 8:30 Uhr und danach alle 20 Minuten auszulösen:
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);
Entscheiden, wie genau der Alarm sein muss
Wie bereits beschrieben, ist die Auswahl des Alarmtyps oft der erste Schritt beim Erstellen eines Alarms. Ein weiterer Unterschied besteht darin, wie genau der Alarm sein muss. Für die meisten Apps ist setInexactRepeating()
die richtige Wahl. Wenn Sie diese Methode verwenden, synchronisiert Android mehrere ungenaue sich wiederholende Alarme und löst sie gleichzeitig aus. Dadurch wird der Akku weniger belastet.
Verzichten Sie nach Möglichkeit auf exakte Alarme. Für die seltenen Apps, die strenge Zeitvorgaben haben, können Sie jedoch einen genauen Wecker stellen, indem Sie setRepeating()
aufrufen.
Mit setInexactRepeating()
können Sie kein benutzerdefiniertes Intervall angeben, wie es mit setRepeating()
möglich ist.
Sie müssen eine der Intervallkonstanten verwenden, z. B. INTERVAL_FIFTEEN_MINUTES
, INTERVAL_DAY
usw. Die vollständige Liste finden Sie unter AlarmManager
.
Einen Wecker ausschalten
Je nach App sollten Sie möglicherweise die Möglichkeit zum Abbrechen des Alarms einbauen.
Um einen Alarm abzubrechen, rufen Sie cancel()
im Alarm Manager auf und übergeben Sie die PendingIntent
, die nicht mehr ausgelöst werden soll. Beispiel:
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); }
Wecker starten, wenn das Gerät neu gestartet wird
Standardmäßig werden alle Alarme abgebrochen, wenn ein Gerät heruntergefahren wird.
Um dies zu verhindern, können Sie Ihre Anwendung so gestalten, dass ein sich wiederholender Alarm automatisch neu gestartet wird, wenn der Nutzer das Gerät neu startet. So wird sichergestellt, dass AlarmManager
seine Aufgabe fortsetzt, ohne dass der Nutzer den Wecker manuell neu starten muss.
Gehe dazu so vor:
Legen Sie die Berechtigung
RECEIVE_BOOT_COMPLETED
im Manifest Ihrer Anwendung fest. Dadurch kann Ihre App denACTION_BOOT_COMPLETED
-Broadcast empfangen, der nach dem Hochfahren des Systems gesendet wird. Das funktioniert nur, wenn die App bereits mindestens einmal vom Nutzer gestartet wurde:<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
Implementieren Sie einen
BroadcastReceiver
, um den Broadcast zu empfangen: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. } } }
Fügen Sie den Receiver mit einem Intent-Filter, der nach der Aktion
ACTION_BOOT_COMPLETED
filtert, in die Manifestdatei Ihrer App ein:<receiver android:name=".SampleBootReceiver" android:enabled="false"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"></action> </intent-filter> </receiver>
Beachten Sie, dass der Boot-Receiver im Manifest auf
android:enabled="false"
festgelegt ist. Das bedeutet, dass der Empfänger nicht aufgerufen wird, es sei denn, die Anwendung aktiviert ihn explizit. Dadurch wird verhindert, dass der Boot-Receiver unnötig aufgerufen wird. So aktivieren Sie einen Receiver (z. B. wenn der Nutzer einen Wecker stellt):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);
Wenn Sie den Empfänger auf diese Weise aktivieren, bleibt er aktiviert, auch wenn der Nutzer das Gerät neu startet. Mit anderen Worten: Durch das programmgesteuerte Aktivieren des Receivers wird die Manifesteinstellung überschrieben, auch nach Neustarts. Der Empfänger bleibt aktiviert, bis Ihre App ihn deaktiviert. Du kannst einen Empfänger deaktivieren (z. B. wenn der Nutzer einen Alarm abbrechen möchte), indem du Folgendes tust:
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);
Alarme auslösen, während sich das Gerät im Doze-Modus befindet
Geräte mit Android 6.0 (API-Level 23) unterstützen den Stromsparmodus, der die Akkulaufzeit des Geräts verlängert. Alarme werden nicht ausgelöst, wenn sich das Gerät im Inaktivmodus befindet. Alle geplanten Alarme werden aufgeschoben, bis das Gerät den Inaktivmodus verlässt. Wenn Sie Aufgaben erledigen müssen, auch wenn das Gerät im Leerlauf ist, haben Sie mehrere Möglichkeiten:
Stellen Sie einen genauen Wecker.
Verwenden Sie die WorkManager API, die für die Ausführung von Hintergrundaufgaben entwickelt wurde. Sie können angeben, dass das System Ihre Arbeit beschleunigen soll, damit sie so schnell wie möglich abgeschlossen wird. Weitere Informationen finden Sie unter Aufgaben mit WorkManager planen.
Best Practices
Jede Entscheidung, die Sie beim Entwerfen Ihres sich wiederholenden Alarms treffen, kann Auswirkungen darauf haben, wie Ihre App Systemressourcen nutzt (oder missbraucht). Stellen Sie sich beispielsweise eine beliebte App vor, die mit einem Server synchronisiert wird. Wenn der Synchronisierungsvorgang auf der Uhrzeit basiert und jede Instanz der App um 23:00 Uhr synchronisiert wird, kann die Serverlast zu einer hohen Latenz oder sogar zu einem „Denial of Service“ führen. Beachten Sie bei der Verwendung von Alarmen die folgenden Best Practices:
Fügen Sie allen Netzwerkanfragen, die durch einen sich wiederholenden Alarm ausgelöst werden, Zufälligkeit (Jitter) hinzu:
Lokale Aktionen ausführen, wenn der Alarm ausgelöst wird. „Lokale Arbeit“ bezieht sich auf alles, was keinen Serverzugriff erfordert oder keine Daten vom Server benötigt.
Gleichzeitig wird der Alarm, der die Netzwerkanfragen enthält, so geplant, dass er zu einem zufälligen Zeitpunkt ausgelöst wird.
Stelle die Alarmhäufigkeit so niedrig wie möglich ein.
Das Gerät soll nicht unnötig aktiviert werden. Dieses Verhalten wird durch den Alarmtyp bestimmt, wie unter Alarmtyp auswählen beschrieben.
Geben Sie für die Auslösezeit des Alarms keine genauere Zeit an als nötig.
Verwenden Sie
setInexactRepeating()
anstelle vonsetRepeating()
. Wenn SiesetInexactRepeating()
verwenden, synchronisiert Android sich wiederholende Wecker aus mehreren Apps und löst sie gleichzeitig aus. Dadurch muss das System das Gerät seltener aktivieren, was den Akku schont. Seit Android 4.4 (API-Level 19) sind alle sich wiederholenden Wecker ungenaue Wecker.setInexactRepeating()
ist zwar eine Verbesserung gegenübersetRepeating()
, kann aber einen Server überlasten, wenn jede Instanz einer App den Server etwa zur gleichen Zeit erreicht. Fügen Sie daher bei Netzwerkanfragen, wie bereits besprochen, etwas Zufälligkeit in Ihre Alarme ein.Vermeiden Sie es nach Möglichkeit, den Wecker auf die Uhrzeit zu stützen.
Wiederholte Wecker, die auf einer genauen Auslösezeit basieren, lassen sich nicht gut skalieren. Verwenden Sie
ELAPSED_REALTIME
, wenn möglich. Die verschiedenen Alarmtypen werden im folgenden Abschnitt genauer beschrieben.