Wecker stellen

Mit Alarmen (basierend auf der Klasse 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:

  1. Der erste Alarm wird innerhalb des angegebenen Zeitfensters ab der angegebenen Triggerzeit ausgelöst.
  2. 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() und postDelayed(). 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 und flexInterval (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

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:

  1. 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.
  2. 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

Die Option heißt „Erlauben, Wecker und Erinnerungen einzurichten“.
Abbildung 1: Seite „Spezieller App-Zugriff“ > „Wecker und Erinnerungen“ in den Systemeinstellungen, auf der Nutzer Ihrer App erlauben können, genaue Wecker zu stellen.

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:

  1. Erklären Sie dem Nutzer in der Benutzeroberfläche Ihrer App, warum Ihre App genaue Alarme planen muss.
  2. 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:

  1. Legen Sie die Berechtigung RECEIVE_BOOT_COMPLETED im Manifest Ihrer Anwendung fest. Dadurch kann Ihre App den ACTION_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"/>
  2. 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.
            }
        }
    }
  3. 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 von setRepeating(). Wenn Sie setInexactRepeating() 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über setRepeating(), 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.