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 Alarm verwenden, um einen Vorgang mit langer Ausführungszeit zu starten, z. B. einen Dienst einmal am Tag zu starten, um eine Wettervorhersage herunterzuladen.

Wecker haben folgende Eigenschaften:

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

  • Sie können sie in Verbindung mit Übertragungsempfängern verwenden, um Jobs oder WorkRequests für andere Vorgänge zu planen.

  • Sie funktionieren außerhalb Ihrer Anwendung. Sie können sie also verwenden, um Ereignisse oder Aktionen auszulösen, auch wenn Ihre Anwendung nicht ausgeführt wird und das Gerät selbst im Ruhemodus ist.

  • Sie helfen Ihnen, den Ressourcenbedarf Ihrer App zu minimieren. Sie können Vorgänge planen, ohne sich auf Timer oder kontinuierlich ausgeführte Dienste verlassen zu müssen.

Ungenauen Wecker stellen

Wenn eine App einen ungenauen Wecker einstellt, wird der Wecker irgendwann in der Zukunft ausgelöst. Ungenau terminierte Wecker bieten gewisse Garantien hinsichtlich des Zeitpunkts der Weckerauslösung, wobei Einschränkungen zum Energiesparen wie der Stromsparmodus berücksichtigt werden.

Entwickler können die folgenden API-Garantien nutzen, um den Zeitpunkt der Zustellung ungenauer Wecker 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 ruft das System den Wecker innerhalb einer Stunde nach der angegebenen Auslösezeit auf, sofern keine Einschränkungen zum Energiesparen wie der Energiesparmodus oder der Stromsparmodus gelten.

Wecker in einem bestimmten Zeitfenster auslösen

Wenn Ihre App setWindow() aufruft, wird der Wecker nie vor der angegebenen Auslösezeit ausgelöst. Sofern keine Energiesparbeschränkungen gelten, wird der Alarm 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 den Aufruf eines ungenauen Alarms mit Zeitfenster um mindestens 10 Minuten verzögern. Aus diesem Grund werden windowLengthMillis-Parameterwerte unter 600000 in der Regel auf 600000 gekürzt. Das System kann kleinere Zeitfenster berücksichtigen, insbesondere wenn der Alarm in naher Zukunft ausgelöst werden soll.

Wiederkehrenden Wecker in ungefähr regelmäßigen Abständen auslösen

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

  1. Der erste Alarm wird innerhalb des angegebenen Zeitfensters ausgelöst, beginnend mit der angegebenen Auslösezeit.
  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 Alarm einstellen

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

In den meisten Apps können Aufgaben und Ereignisse mit ungenauen Weckern geplant werden, um mehrere häufige Anwendungsfälle abzudecken. Wenn die Hauptfunktion Ihrer App von einem zeitgenauen Alarm abhängt, z. B. bei einer Wecker- oder Kalender-App, können Sie stattdessen einen exakten Alarm verwenden.

Anwendungsfälle, für die möglicherweise keine exakten Alarme erforderlich sind

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

Zeitplanungsvorgänge während der Lebensdauer Ihrer Anwendung planen
Die Klasse Handler enthält mehrere gute Methoden für die Verarbeitung von Zeitvorgängen, z. B. für die Ausführung einer Aufgabe alle n Sekunden, während die 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, regelmäßige 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 sich das System im inaktiven Zustand befindet)
Verwende einen ungenauen Alarm. Rufen Sie dazu setAndAllowWhileIdle() auf.
Vom Nutzer angegebene Aktion, die nach einer bestimmten Zeit ausgeführt werden soll
Verwende einen ungenauen Alarm. Rufen Sie dazu set() auf.
Benutzerdefinierte Aktion, die innerhalb eines bestimmten Zeitfensters ausgeführt werden kann
Verwende einen ungenauen Alarm. Rufen Sie dazu setWindow() auf. Wenn deine App auf Android 12 oder höher ausgerichtet ist, beträgt die kleinste zulässige Fensterlänge 10 Minuten.

Möglichkeiten, einen exakten Alarm einzustellen

Ihre App kann mit einer der folgenden Methoden exakte Alarme einstellen. Diese Methoden sind so sortiert, dass die Methoden weiter unten in der Liste zeitkritischere Aufgaben erfüllen, aber mehr Systemressourcen erfordern.

setExact()

Löst einen Wecker zu einem fast genauen Zeitpunkt in der Zukunft aus, solange keine anderen Energiesparmaßnahmen aktiv sind.

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

setExactAndAllowWhileIdle()

Löst einen Alarm zu einem fast genauen Zeitpunkt in der Zukunft aus, auch wenn Energiesparmaßnahmen aktiv sind.

setAlarmClock()

Wecker zu einer genauen Uhrzeit in der Zukunft auslösen. Da diese Alarme für Nutzer gut sichtbar sind, wird ihre Auslieferungszeit vom System nie angepasst. Das System identifiziert diese Alarme als die wichtigsten und verlässt bei Bedarf den Energiesparmodus, um die Alarme auszugeben.

Systemressourcenverbrauch

Wenn das System von Ihrer App festgelegte genaue Wecker auslöst, verbraucht das Gerät viele Ressourcen, z. B. Akkuleistung, insbesondere im Energiesparmodus. Außerdem kann das System diese Anfragen nicht einfach im Batch verarbeiten, um Ressourcen effizienter zu nutzen.

Es wird dringend empfohlen, nach Möglichkeit einen ungenauen Wecker zu erstellen. Wenn Sie längere Aufgaben ausführen möchten, planen Sie diese mit WorkManager oder JobScheduler über die BroadcastReceiver Ihres Weckers. Wenn du Aufgaben ausführen möchtest, während sich das Gerät im Stromsparmodus befindet, erstelle mit setAndAllowWhileIdle() einen ungenauen Alarm und starte einen Job über den Alarm.

Erklärung zur Berechtigung „Exakter Alarm“ abgeben

Wenn deine App auf Android 12 oder höher ausgerichtet ist, musst du den speziellen App-Zugriff „Wecker und Erinnerungen“ einholen. 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 deine App auf Android 13 (API-Level 33) oder höher ausgerichtet ist, kannst du entweder die Berechtigung SCHEDULE_EXACT_ALARM oder USE_EXACT_ALARM deklarieren.

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

Sowohl die Berechtigung SCHEDULE_EXACT_ALARM als auch die Berechtigung USE_EXACT_ALARM signalisieren dieselben Funktionen, werden jedoch unterschiedlich gewährt und unterstützen unterschiedliche Anwendungsfälle. Ihre App sollte exakte Alarme verwenden und entweder die Berechtigung SCHEDULE_EXACT_ALARM oder USE_EXACT_ALARM 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
  • Breiteres Spektrum an Anwendungsfällen
  • Apps sollten prüfen, ob die Berechtigung 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 einen Sicherungs- und Wiederherstellungsvorgang 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 exakte Alarm mit einem OnAlarmListener-Objekt festgelegt wird, z. B. mit der setExact API, ist die Berechtigung SCHEDULE_EXACT_ALARM nicht erforderlich.

Berechtigung „SCHEDULE_EXACT_ALARM“ verwenden

Im Gegensatz zu USE_EXACT_ALARM muss die Berechtigung SCHEDULE_EXACT_ALARM vom Nutzer gewährt werden. Sowohl der Nutzer als auch das System können die Berechtigung SCHEDULE_EXACT_ALARM widerrufen.

Wenn du prüfen möchtest, ob deiner App die Berechtigung gewährt wurde, rufe canScheduleExactAlarms() auf, bevor du versuchst, einen exakten Alarm einzurichten. Wenn die Berechtigung SCHEDULE_EXACT_ALARM für Ihre App widerrufen wird, wird die 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 deiner App die Berechtigung SCHEDULE_EXACT_ALARMS gewährt wird, sendet das System ihr den Broadcast ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED. Ihre App sollte einen Übertragungsempfänger implementieren, der Folgendes tut:

  1. Bestätigt, dass Ihre App weiterhin den speziellen App-Zugriff hat. Rufen Sie dazu canScheduleExactAlarms() auf. Diese Prüfung schützt Ihre App für den Fall, dass der Nutzer Ihrer App die Berechtigung erteilt und sie dann fast sofort wieder widerruft.
  2. Alle exakten Alarme, die Ihre App benötigt, werden basierend auf ihrem aktuellen Status neu geplant. Diese Logik sollte der Logik ähneln, die Ihre App verwendet, wenn sie den Broadcast ACTION_BOOT_COMPLETED empfängt.

Nutzer um die Berechtigung SCHEDULE_EXACT_ALARM bitten

Die Option heißt „Erlauben, Wecker und Erinnerungen einzurichten“.
Abbildung 1: Seite für den speziellen App-Zugriff „Wecker und Erinnerungen“ in den Systemeinstellungen, auf der Nutzer Ihrer App erlauben können, genaue Wecker einzustellen.

Bei Bedarf kannst du Nutzer zum Bildschirm Wecker und Erinnerungen in den Systemeinstellungen weiterleiten, wie in Abbildung 1 dargestellt. Führen Sie dazu folgende Schritte aus:

  1. Erkläre dem Nutzer in der Benutzeroberfläche deiner App, warum deine App genaue Wecker planen muss.
  2. Rufen Sie einen Intent auf, der die Intent-Aktion ACTION_REQUEST_SCHEDULE_EXACT_ALARM enthält.

Wiederkehrenden Wecker stellen

Wiederkehrende Alarme ermöglichen es dem System, Ihre App nach einem wiederkehrenden Zeitplan zu benachrichtigen.

Ein schlecht konzipierter Alarm kann den Akku entladen und die Server erheblich belasten. Aus diesem Grund sind unter Android 4.4 (API-Level 19) und höher alle sich wiederholenden Wecker ungenaue Wecker.

Ein wiederkehrender Wecker hat die folgenden Eigenschaften:

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

  • Einen Triggerzeitpunkt. Wenn die von Ihnen angegebene Auslösezeit in der Vergangenheit liegt, wird der Alarm sofort ausgelöst.

  • Das Intervall des Alarms. Beispiel: einmal am Tag, jede Stunde oder alle 5 Minuten.

  • Ein Pending Intent, der ausgelöst wird, wenn der Wecker ausgelöst wird. Wenn du einen zweiten Wecker mit demselben Pending Intent einstellst, wird der ursprüngliche Wecker ersetzt.

Wenn du einen PendingIntent() abbrechen möchtest, übergib FLAG_NO_CREATE an PendingIntent.getService(), um eine Instanz des Intents abzurufen (falls vorhanden). Übergib 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);
}

Alarmtyp auswählen

Eine der ersten Überlegungen bei der Verwendung eines sich wiederholenden Alarms ist, welcher Typ verwendet werden soll.

Es gibt zwei allgemeine Uhrentypen für Wecker: „Verstrichene Echtzeit“ und „Echtzeituhr“ (RTC). Bei der verstrichenen Echtzeit wird die „Zeit seit dem Systemstart“ als Referenz verwendet, während die Echtzeituhr die UTC-Zeit (Wanduhr) verwendet. Das bedeutet, dass die verstrichene Echtzeit sich für das Festlegen eines Alarms eignet, der auf dem Verstreichen von Zeit basiert (z. B. ein Alarm, der alle 30 Sekunden ausgelöst wird), da sie nicht von der Zeitzone oder dem Gebietsschema beeinflusst wird. Der Echtzeituhrtyp eignet sich besser für Wecker, die von der aktuellen Spracheinstellung 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 eine Zeitabhängigkeit hat. Beispielsweise, wenn es nur ein begrenztes Zeitfenster für einen bestimmten Vorgang gibt. Wenn du nicht die Wakeup-Version deines Weckertyps verwendest, werden alle wiederkehrenden Wecker ausgelöst, wenn dein Gerät das nächste Mal aktiv ist.

Wenn der Wecker einfach in einem bestimmten Intervall ausgelöst werden soll (z. B. jede halbe Stunde), verwende 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 uhrzeitbasierten Echtzeituhrtypen 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-Weckertyps lässt sich außerdem nicht gut skalieren, wie oben beschrieben. Wir empfehlen, nach Möglichkeit einen Alarm vom Typ „elapsed real time“ zu verwenden.

Hier ist die Liste der Typen:

  • ELAPSED_REALTIME: Löst den ausstehenden Intent basierend auf der Zeit aus, die seit dem Start des Geräts vergangen ist, 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: Aktiviert das Gerät und löst den ausstehenden Intent aus, nachdem die angegebene Zeit seit dem Gerätestart verstrichen ist.

  • RTC: Löst den ausstehenden Intent zur angegebenen Zeit aus, weckt das Gerät aber nicht auf.

  • RTC_WAKEUP: Aktiviert das Gerät, um den ausstehenden Intent zum angegebenen Zeitpunkt auszulösen.

Beispiele für Alarme, die auf der verstrichenen Echtzeit basieren

Hier einige Beispiele für die Verwendung von ELAPSED_REALTIME_WAKEUP:

Wecken Sie das Gerät auf, um den Alarm in 30 Minuten und danach alle 30 Minuten auszulösen:

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

Wecken Sie das Gerät auf, um in einer Minute einen einmaligen (nicht wiederkehrenden) Alarm 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 auf, 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 genau um 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 ist, 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 geschont.

Vermeiden Sie nach Möglichkeit die Verwendung exakter Alarme. Für die wenigen Apps, die strenge Zeitanforderungen haben, können Sie jedoch einen exakten Alarm einstellen, 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.

Wecker ausschalten

Je nach App kann es sinnvoll sein, eine Funktion zum Abbrechen des Alarms einzubinden. Wenn du einen Alarm abbrechen möchtest, rufe cancel() im Alarm Manager auf und übergib den PendingIntent, der 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 Wecker abgebrochen, wenn ein Gerät heruntergefahren wird. Um dies zu verhindern, können Sie Ihre Anwendung so gestalten, dass ein sich wiederholender Wecker automatisch neu gestartet wird, wenn der Nutzer das Gerät neu startet. So wird sichergestellt, dass der AlarmManager seine Aufgabe weiterhin ausführt, ohne dass der Nutzer den Alarm manuell neu starten muss.

Gehe dazu so vor:

  1. Legen Sie die Berechtigung RECEIVE_BOOT_COMPLETED im Manifest Ihrer Anwendung fest. Dadurch kann deine App den ACTION_BOOT_COMPLETED empfangen, der nach dem Booten 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 die Nachricht 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 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 der Boot-Empfänger im Manifest auf android:enabled="false" festgelegt ist. Das bedeutet, dass der Empfänger nur aufgerufen wird, wenn die Anwendung ihn explizit aktiviert. Dadurch wird verhindert, dass der Boot-Empfänger unnötig aufgerufen wird. So kannst du einen Empfänger aktivieren (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 du den Empfänger auf diese Weise aktivierst, bleibt er aktiviert, auch wenn der Nutzer das Gerät neu startet. Mit anderen Worten: Wenn der Empfänger programmatisch aktiviert wird, wird die Manifesteinstellung überschrieben, auch nach einem Neustart. Der Empfänger bleibt aktiviert, bis er von Ihrer App deaktiviert wird. So kannst du einen Empfänger deaktivieren (z. B. wenn der Nutzer einen Wecker abbricht):

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

Wecker auslösen, während sich das Gerät im Stromsparmodus befindet

Geräte mit Android 6.0 (API-Level 23) unterstützen den Stromsparmodus, der die Akkulaufzeit des Geräts verlängert. Wecker werden nicht ausgelöst, wenn sich das Gerät im Stromsparmodus befindet. Alle geplanten Wecker werden verschoben, bis das Gerät den Stromsparmodus verlässt. Wenn du Aufgaben auch dann erledigen musst, wenn das Gerät inaktiv ist, gibt es mehrere Möglichkeiten:

  • Exakten Alarm stellen

  • 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 wiederkehrenden Weckers treffen, kann sich darauf auswirken, wie Ihre App Systemressourcen nutzt (oder missbraucht). Stellen Sie sich zum Beispiel 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 Last auf dem Server 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:

    • Führen Sie alle lokalen Aufgaben aus, wenn der Alarm ausgelöst wird. „Lokale Arbeit“ bedeutet alles, was keinen Server erreicht oder keine Daten vom Server erfordert.

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

  • Halten Sie die Häufigkeit von Alarmen so gering wie möglich.

  • Wecke das Gerät nicht unnötig auf. 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 sein muss.

    Verwenden Sie setInexactRepeating() anstelle von setRepeating(). Wenn Sie setInexactRepeating() verwenden, synchronisiert Android wiederkehrende Alarme aus mehreren Apps und löst sie gleichzeitig aus. Dadurch wird die Gesamtzahl der Aktivierungen des Geräts durch das System reduziert und der Akku geschont. Ab Android 4.4 (API-Level 19) sind alle sich wiederholenden Wecker ungenaue Wecker. setInexactRepeating() ist zwar eine Verbesserung gegenüber setRepeating(), kann aber dennoch einen Server überlasten, wenn jede Instanz einer Anwendung den Server ungefähr zur gleichen Zeit erreicht. Fügen Sie daher bei Netzwerkanfragen Ihren Weckern eine gewisse Zufälligkeit hinzu, wie bereits beschrieben.

  • Vermeiden Sie es nach Möglichkeit, den Alarm auf die Uhrzeit zu beziehen.

    Wiederkehrende Alarme, die auf einer genauen Auslösezeit basieren, lassen sich nicht gut skalieren. Verwenden Sie nach Möglichkeit ELAPSED_REALTIME. Die verschiedenen Alarmtypen werden im folgenden Abschnitt ausführlicher beschrieben.