Wecker stellen

Mit Weckern (basierend auf der Klasse AlarmManager) können Sie zeitbasierte Vorgänge außerhalb der Lebensdauer Ihrer Anwendung ausführen. Sie können beispielsweise einen Wecker verwenden, um einen langwierigen Vorgang zu starten, z. B. den Start eines Dienstes einmal täglich, um eine Wettervorhersage herunterzuladen.

Wecker haben folgende Eigenschaften:

  • Mit ihnen können Sie Intents zu festgelegten Zeiten und/oder Intervallen auslösen.

  • Sie können sie in Verbindung mit Broadcastempfängern verwenden, um Jobs oder WorkRequests zu planen, um andere Vorgänge auszuführen.

  • Sie werden außerhalb Ihrer Anwendung ausgeführt. So können Sie damit Ereignisse oder Aktionen auch dann auslösen, wenn Ihre App nicht ausgeführt wird und das Gerät selbst im Ruhemodus ist.

  • 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.

Wecker mit ungenauer Uhrzeit stellen

Wenn eine App einen ungenauen Wecker stellt, löst das System den Wecker irgendwann in der Zukunft aus. Ungenaue Wecker bieten einige Garantien hinsichtlich des Zeitpunkts der Weckzeit, wobei Akkusparfunktionen wie Doze berücksichtigt werden.

Entwickler können die folgenden API-Garantien nutzen, um das Timing der Übermittlung ungenauer Benachrichtigungen anzupassen.

Wecker nach einer bestimmten Zeit senden

Wenn Ihre App set(), setInexactRepeating() oder setAndAllowWhileIdle() aufruft, klingelt der Wecker nie vor der angegebenen Auslösezeit.

Unter Android 12 (API-Level 31) und höher ruft das System den Wecker innerhalb einer Stunde nach der angegebenen Auslösezeit auf, es sei denn, es gelten Einschränkungen für den Energiesparmodus, z. B. der Energiesparmodus oder Doze.

Wecker in einem bestimmten Zeitraum senden

Wenn Ihre App setWindow() aufruft, klingelt der Wecker nie vor der angegebenen Auslösezeit. Sofern keine Einschränkungen zur Akkuschonung gelten, wird der Wecker innerhalb des angegebenen Zeitfensters ab der angegebenen Auslösezeit ausgelöst.

Wenn Ihre App auf Android 12 oder höher ausgerichtet ist, kann das System die Auslösung eines ungenauen Weckers mit Zeitfenster um mindestens 10 Minuten verzögern. Aus diesem Grund werden windowLengthMillis-Parameterwerte unter 600000 auf 600000 zugeschnitten.

Wiederkehrenden Wecker in ungefähr regelmäßigen Abständen senden

Wenn Ihre App setInexactRepeating() aufruft, löst das System mehrere Benachrichtigungen aus:

  1. Der erste Wecker klingelt innerhalb des angegebenen Zeitfensters, beginnend mit der angegebenen Auslösezeit.
  2. Nachfolgende Wecker klingeln in der Regel nach Ablauf des festgelegten Zeitfensters. Die Zeit zwischen zwei aufeinanderfolgenden Aufrufen des Weckers kann variieren.

Genauen Wecker stellen

Das System löst zu einem genauen Zeitpunkt in der Zukunft einen genauen Alarm aus.

In den meisten Apps können Aufgaben und Ereignisse mithilfe von ungenauen Weckern geplant werden, um mehrere häufige Anwendungsfälle auszuführen. Wenn die Hauptfunktion Ihrer App von einem genau getakteten Wecker abhängt, z. B. bei einer Wecker- oder Kalender-App, ist es in Ordnung, stattdessen einen genauen Wecker zu verwenden.

Anwendungsfälle, für die keine genauen Alarme erforderlich sind

In der folgenden Liste sind gängige Workflows aufgeführt, für die möglicherweise kein genauer Alarm erforderlich ist:

Zeitliche Abläufe während der Lebensdauer Ihrer App planen
Die Klasse Handler bietet mehrere gute Methoden zur Verarbeitung von Zeitfunktionen, z. B. die Ausführung einer bestimmten Arbeit alle n Sekunden, während die App aktiv ist: postAtTime() und postDelayed(). Beachten Sie, dass diese APIs auf der System-Uptime und nicht auf Echtzeit basieren.
Geplante Aufgaben im Hintergrund, z. B. das Aktualisieren Ihrer App und das Hochladen von Protokollen
WorkManager bietet eine Möglichkeit, zeitlich sensible, wiederkehrende Aufgaben zu planen. Sie können ein Wiederholungsintervall und flexInterval (mindestens 15 Minuten) angeben, um eine detaillierte Laufzeit für die Arbeit zu definieren.
Vom Nutzer angegebene Aktion, die nach einer bestimmten Zeit ausgeführt werden soll (auch wenn das System im Ruhemodus ist)
Verwenden Sie einen ungefähren Wecker. Rufen Sie dazu setAndAllowWhileIdle() an.
Vom Nutzer angegebene Aktion, die nach einer bestimmten Zeit ausgeführt werden soll
Verwenden Sie einen ungefähren Wecker. Rufen Sie dazu set() an.
Vom Nutzer angegebene Aktion, die innerhalb eines bestimmten Zeitraums erfolgen kann
Verwenden Sie einen ungefähren Wecker. Rufen Sie dazu setWindow() an. Wenn Ihre App auf Android 12 oder höher ausgerichtet ist, beträgt die kürzeste zulässige Zeitspanne 10 Minuten.

Möglichkeiten zum Stellen eines genauen Weckers

Ihre App kann mit einer der folgenden Methoden genaue Wecker stellen. Diese Methoden sind so angeordnet, dass die am Ende der Liste eher zeitkritische Aufgaben erfüllen, aber mehr Systemressourcen verbrauchen.

setExact()

Sie können einen Wecker zu einer nahezu genauen Zeit in der Zukunft stellen, sofern keine anderen Maßnahmen zur Akkuschonung aktiv sind.

Verwenden Sie diese Methode, um genaue Wecker einzustellen, es sei denn, die Arbeit Ihrer App ist für den Nutzer zeitkritisch.

setExactAndAllowWhileIdle()

Sie können einen Wecker zu einer nahezu genauen Zeit in der Zukunft stellen, auch wenn Akkusparmaßnahmen aktiviert sind.

setAlarmClock()

Sie können einen Wecker für eine bestimmte Uhrzeit in der Zukunft stellen. Da diese Benachrichtigungen für Nutzer gut sichtbar sind, passt das System die Auslieferungszeit nie an. Das System identifiziert diese Benachrichtigungen als die wichtigsten und beendet bei Bedarf den Energiesparmodus, um sie zu senden.

Verbrauch von Systemressourcen

Wenn das System genau die Wecker auslöst, die Ihre App stellt, verbraucht das Gerät viele Ressourcen, z. B. Akkulaufzeit, insbesondere wenn es sich im Energiesparmodus befindet. Außerdem kann das System diese Anfragen nicht einfach in Batches verarbeiten, um die Ressourcen effizienter zu nutzen.

Es wird dringend empfohlen, nach Möglichkeit einen ungenauen Wecker zu erstellen. Wenn Sie eine längere Aufgabe ausführen möchten, planen Sie sie mit WorkManager oder JobScheduler über die BroadcastReceiver Ihres Weckers. Wenn Sie Aufgaben ausführen möchten, während das Gerät im Ruhemodus ist, erstellen Sie mit setAndAllowWhileIdle() einen ungefähren Wecker und starten Sie einen Job über den Wecker.

Entsprechende Berechtigung für exakte Alarme erklären

Wenn Ihre App auf Android 12 oder höher ausgerichtet ist, müssen Sie den speziellen App-Zugriff „Wecker und Erinnerungen“ anfordern. Deklarieren Sie dazu 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>

Obwohl sowohl die SCHEDULE_EXACT_ALARM- als auch die USE_EXACT_ALARM-Berechtigung dieselben Funktionen signalisieren, werden sie unterschiedlich gewährt und unterstützen unterschiedliche Anwendungsfälle. Ihre App sollte exakte Wecker verwenden und die Berechtigung SCHEDULE_EXACT_ALARM oder USE_EXACT_ALARM nur deklarieren, wenn eine für den Nutzer sichtbare Funktion in Ihrer App zeitgenaue Aktionen erfordert.

USE_EXACT_ALARM

SCHEDULE_EXACT_ALARM

  • Vom Nutzer gewährt
  • Mehr Anwendungsfälle
  • Apps müssen 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 gewährt. Wenn ein Nutzer App-Daten über einen Sicherungs- und Wiederherstellungsvorgang auf ein Gerät mit Android 14 überträgt, wird die Berechtigung SCHEDULE_EXACT_ALARM auf dem neuen Gerät abgelehnt. Wenn eine vorhandene App diese Berechtigung bereits hat, wird sie vorab gewährt, wenn das Gerät auf Android 14 aktualisiert wird.

Hinweis: Wenn der genaue Wecker 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.

Wenn Sie prüfen möchten, ob Ihre App die Berechtigung hat, rufen Sie canScheduleExactAlarms() auf, bevor Sie versuchen, einen genauen Wecker einzustellen. Wenn die Berechtigung SCHEDULE_EXACT_ALARM für Ihre App widerrufen wird, wird die App beendet und alle zukünftigen genauen Wecker werden abgesagt. 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 gewährt wird, sendet das System ihr die Übertragung ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED. Ihre App sollte einen Broadcast-Empfänger implementieren, der Folgendes tut:

  1. Prüft, ob 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 gewährt und sie dann fast unmittelbar danach widerruft.
  2. Alle Wecker, die Ihre App benötigt, werden basierend auf ihrem aktuellen Status neu geplant. Diese Logik sollte der Logik in Ihrer App ähneln, wenn sie die Übertragung von ACTION_BOOT_COMPLETED empfängt.

Nutzer um die Berechtigung SCHEDULE_EXACT_ALARM bitten

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

Falls erforderlich, können Sie Nutzer zu dem Bildschirm Wecker und Erinnerungen in den Systemeinstellungen weiterleiten, wie in Abbildung 1 dargestellt. Gehen Sie dazu so vor:

  1. Erläutern Sie Nutzern in der Benutzeroberfläche Ihrer App, warum Ihre App genaue Wecker stellen muss.
  2. Rufen Sie einen Intent auf, der die Intent-Aktion ACTION_REQUEST_SCHEDULE_EXACT_ALARM enthält.

Wiederkehrenden Wecker stellen

Mit wiederkehrenden Weckern kann das System Ihre App in regelmäßigen Abständen benachrichtigen.

Ein schlecht konzipierter Wecker kann den Akku belasten und die Server erheblich beanspruchen. Aus diesem Grund sind unter Android 4.4 (API-Ebene 19) und höher alle Wecker mit Wiederholung ungenaue Wecker.

Ein wiederkehrender Wecker hat folgende Eigenschaften:

  • Ein Weckertyp. Weitere Informationen finden Sie unter Alarmtyp auswählen.

  • Einen Triggerzeitpunkt. Wenn der von Ihnen angegebene Triggerzeitpunkt in der Vergangenheit liegt, wird der Wecker sofort ausgelöst.

  • Intervall des Weckers. Beispiel: 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 stellen, der dieselbe ausstehende Absicht verwendet, wird der ursprüngliche Wecker ersetzt.

Wenn Sie eine PendingIntent() abbrechen möchten, übergeben Sie FLAG_NO_CREATE an PendingIntent.getService(), um eine Instanz des Intents abzurufen (falls vorhanden), und übergeben Sie diesen Intent dann an AlarmManager.cancel().

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)
}
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 wiederkehrenden Weckers ist, welche Art er haben sollte.

Es gibt zwei allgemeine Uhrentypen für Wecker: „Abgelaufene Echtzeit“ und „Echtzeituhr“ (Real Time Clock, RTC). Für die vergangene Echtzeit wird die „Zeit seit Systemstart“ als Referenz verwendet. Die Echtzeituhr verwendet die UTC-Zeit (Uhrzeit auf der Weltzeituhr). Das bedeutet, dass die vergangene Echtzeit zum Einstellen eines Weckers geeignet ist, der auf der Zeit basiert (z. B. ein Wecker, der alle 30 Sekunden klingelt), da er sich nicht von Zeitzone oder Gebietsschema beeinflusst lässt. Der Echtzeit-Uhrtyp eignet sich besser für Wecker, die vom aktuellen Gebietsschema abhängen.

Beide Typen haben eine „Aufweck“-Version, die die CPU des Geräts aufweckt, wenn das Display ausgeschaltet ist. So wird sichergestellt, dass der Wecker zur geplanten Zeit ausgelöst wird. Das ist nützlich, wenn Ihre App eine zeitliche Abhängigkeit hat. Beispielsweise, wenn für einen bestimmten Vorgang nur ein begrenzter Zeitraum zur Verfügung steht. Wenn Sie die Weckversion des Weckertyps nicht verwenden, werden alle wiederkehrenden Wecker ausgelöst, wenn Ihr Gerät das nächste Mal aktiv ist.

Wenn der Wecker einfach in einem bestimmten Intervall ausgelöst werden soll (z. B. alle halbe Stunde), verwenden Sie einen der Typen für die vergangene Echtzeit. Im Allgemeinen ist dies die bessere Wahl.

Wenn der Wecker zu einer bestimmten Tageszeit klingeln soll, wählen Sie einen der uhrbasierten Echtzeit-Uhrtypen aus. Dieser Ansatz kann jedoch einige Nachteile haben. Die App lässt sich möglicherweise nicht gut auf andere Sprachen übertragen. Wenn der Nutzer die Zeiteinstellung des Geräts ändert, kann dies zu unerwartetem Verhalten in Ihrer App führen. Die Verwendung eines Weckertyps mit Echtzeituhr ist außerdem nicht skalierbar, wie oben erläutert. Wir empfehlen, wenn möglich, einen Wecker mit Echtzeitfunktion zu verwenden.

Hier ist eine Liste der Typen:

  • ELAPSED_REALTIME: Der ausstehende Intent wird basierend auf der Zeit seit dem Start des Geräts ausgelöst, das Gerät wird jedoch nicht geweckt. Die verstrichene Zeit umfasst auch die Zeit, in der das Gerät inaktiv war.

  • ELAPSED_REALTIME_WAKEUP: Das Gerät wird geweckt und die ausstehende Intent wird ausgelöst, nachdem seit dem Start des Geräts die angegebene Zeit verstrichen ist.

  • RTC: Mit dieser Option wird der ausstehende Intent zum angegebenen Zeitpunkt ausgelöst, das Gerät wird jedoch nicht geweckt.

  • RTC_WAKEUP: Das Gerät wird aktiviert, um den ausstehenden Intent zur angegebenen Zeit auszuführen.

Beispiele für abgelaufene Wecker in Echtzeit

Hier einige Beispiele für die Verwendung von ELAPSED_REALTIME_WAKEUP:

So wecken Sie das Gerät, damit der Wecker in 30 Minuten und danach alle 30 Minuten klingelt:

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

So aktivieren Sie das Gerät, damit in einer Minute ein einmaliger (nicht wiederkehrender) Wecker ausgelöst wird:

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
)
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 Wecker mit Echtzeituhr

Hier einige Beispiele für die Verwendung von RTC_WAKEUP:

Wecken Sie das Gerät, damit der Wecker um etwa 14:00 Uhr ausgelöst wird. Wiederholen Sie dies einmal täglich zur selben Zeit:

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

So stellen Sie das Gerät so ein, dass der Wecker genau um 8:30 Uhr und danach alle 20 Minuten klingelt:

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
)
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 Wecker sein muss

Wie bereits beschrieben, ist die Auswahl des Weckertyps oft der erste Schritt beim Erstellen eines Weckers. Ein weiterer Unterschied besteht darin, wie genau Ihr Wecker sein muss. Für die meisten Apps ist setInexactRepeating() die richtige Wahl. Wenn Sie diese Methode verwenden, synchronisiert Android mehrere ungenaue Wecker und löst sie gleichzeitig aus. Dadurch wird der Akku weniger beansprucht.

Vermeiden Sie nach Möglichkeit die Verwendung exakter Wecker. Für seltene Apps mit strikten Zeitanforderungen 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. Eine vollständige Liste finden Sie unter AlarmManager.

Einen Wecker ausschalten

Je nach App sollten Sie die Möglichkeit zum Abbrechen des Weckers einschließen. Wenn Sie einen Wecker abbrechen möchten, rufen Sie cancel() auf dem Alarmmanager auf und geben Sie die PendingIntent an, die nicht mehr ausgelöst werden soll. Beispiel:

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

Wecker beim Neustart des Geräts starten

Standardmäßig werden alle Wecker abgebrochen, wenn ein Gerät heruntergefahren wird. Um dies zu verhindern, können Sie Ihre Anwendung so gestalten, dass ein wiederkehrender Wecker automatisch neu gestartet wird, wenn der Nutzer das Gerät neu startet. So wird sichergestellt, dass die AlarmManager ihre 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. So kann Ihre App die ACTION_BOOT_COMPLETED empfangen, die nach dem Hochfahren des Systems gesendet wird. Dies funktioniert nur, wenn die App bereits mindestens einmal vom Nutzer gestartet wurde:

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
  2. Implementiere eine BroadcastReceiver, um die Übertragung zu empfangen:

    class SampleBootReceiver : BroadcastReceiver() {

       
    override fun onReceive(context: Context, intent: Intent) {
           
    if (intent.action == "android.intent.action.BOOT_COMPLETED") {
               
    // Set the alarm here.
           
    }
       
    }
    }
    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 Empfänger der Manifestdatei Ihrer App mit einem Intent-Filter hinzu, der nach der Aktion ACTION_BOOT_COMPLETED filtert:

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

    Beachten Sie, dass im Manifest der Boot-Empfänger auf android:enabled="false" festgelegt ist. Das bedeutet, dass der Empfänger nur dann aufgerufen wird, wenn die Anwendung dies ausdrücklich zulässt. So wird verhindert, dass der Boot-Empfänger unnötig aufgerufen wird. So aktivieren Sie einen Empfänger (z. B. wenn der Nutzer einen Wecker stellt):

    val receiver = ComponentName(context, SampleBootReceiver::class.java)

    context
    .packageManager.setComponentEnabledSetting(
            receiver
    ,
           
    PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
           
    PackageManager.DONT_KILL_APP
    )
    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 so aktivieren, bleibt er aktiviert, auch wenn der Nutzer das Gerät neu startet. Mit anderen Worten: Wenn Sie den Empfänger programmgesteuert aktivieren, wird die Manifesteinstellung überschrieben, auch nach einem Neustart. Der Empfänger bleibt aktiviert, bis er von Ihrer App deaktiviert wird. So deaktivieren Sie einen Empfänger, z. B. wenn der Nutzer einen Wecker abbricht:

    val receiver = ComponentName(context, SampleBootReceiver::class.java)

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

    pm
    .setComponentEnabledSetting(receiver,
           
    PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
           
    PackageManager.DONT_KILL_APP);

Wecker aktivieren, während das Gerät im Ruhemodus ist

Geräte mit Android 6.0 (API-Level 23) unterstützen den Ruhemodus, mit dem sich die Akkulaufzeit des Geräts verlängern lässt. Wecker werden nicht ausgelöst, wenn sich das Gerät im Ruhemodus befindet. Geplante Wecker werden verschoben, bis das Gerät den Ruhemodus beendet. Wenn Sie Aufgaben auch dann erledigen müssen, wenn das Gerät inaktiv ist, haben Sie mehrere Möglichkeiten:

  • Stellen Sie einen genauen Wecker.

  • Verwenden Sie die WorkManager API, die für die Ausführung von Hintergrundarbeiten 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 des wiederkehrenden Weckers 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 die Synchronisierung auf der Uhrzeit basiert und jede Instanz der App um 23:00 Uhr synchronisiert wird, kann die Auslastung des Servers zu einer hohen Latenz oder sogar zu einem „Denial of Service“ führen. Beachten Sie bei der Verwendung von Weckern die folgenden Best Practices:

  • Fügen Sie allen Netzwerkanfragen, die durch einen sich wiederholenden Alarm ausgelöst werden, Zufälligkeit (Jitter) hinzu:

    • Wenn der Wecker klingelt, können Sie lokale Aktionen ausführen. „Lokale Arbeit“ bedeutet alles, was nicht auf einen Server zugreift oder die Daten vom Server benötigt.

    • Planen Sie gleichzeitig den Wecker, der die Netzwerkanfragen enthält, so, dass er zu einem zufälligen Zeitpunkt ausgelöst wird.

  • Begrenzen Sie die Häufigkeit der Wecker auf ein Minimum.

  • Das Gerät wird nicht unnötig geweckt. Dieses Verhalten wird durch den Weckertyp bestimmt, wie unter Weckertyp auswählen beschrieben.

  • Legen Sie die Auslösezeit des Weckers nicht genauer fest, als es nötig ist.

    Verwenden Sie setInexactRepeating() anstelle von setRepeating(). Wenn Sie setInexactRepeating() verwenden, synchronisiert Android wiederholte Wecker aus mehreren Apps und löst sie gleichzeitig aus. Dadurch wird die Gesamtzahl der Systemaufweckungen reduziert, was die Akkulaufzeit verlängert. Ab Android 4.4 (API-Level 19) sind alle wiederkehrenden Wecker ungenaue Wecker. Beachten Sie, dass setInexactRepeating() zwar eine Verbesserung gegenüber setRepeating() darstellt, aber dennoch einen Server überlasten kann, wenn alle Instanzen einer App den Server ungefähr zur selben Zeit aufrufen. Fügen Sie daher Ihren Benachrichtigungen für Netzwerkanfragen etwas Zufälligkeit hinzu, wie bereits erwähnt.

  • Vermeiden Sie nach Möglichkeit, den Wecker an der Uhrzeit auszurichten.

    Wiederholte Wecker, die auf einer genauen Auslösezeit basieren, lassen sich nicht gut skalieren. Verwenden Sie nach Möglichkeit ELAPSED_REALTIME. Die verschiedenen Arten von Benachrichtigungen werden im folgenden Abschnitt ausführlicher beschrieben.