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önnten beispielsweise einen Alarm verwenden, um einen Vorgang mit langer Ausführungszeit zu starten, wie etwa einmal täglich einen Dienst starten, um eine Wettervorhersage herunterzuladen.

Alarme haben folgende Eigenschaften:

  • Damit lassen sich Intents zu bestimmten Zeiten und/oder Intervallen auslösen.

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

  • Sie werden außerhalb Ihrer Anwendung ausgeführt. Sie können also zum Auslösen von Ereignissen oder Aktionen verwendet werden, auch wenn Ihre App nicht ausgeführt wird und das Gerät selbst sich im Ruhemodus befindet.

  • Sie helfen Ihnen, den Ressourcenbedarf Ihrer App zu minimieren. Sie können Vorgänge planen, ohne auf Timer oder kontinuierlich laufende Dienste angewiesen zu sein.

Ungenauen Wecker stellen

Wenn eine App einen ungenauen Alarm stellt, löst das System den Alarm zu einem späteren Zeitpunkt aus. Ungenaue Alarme bieten einige Garantien für den Zeitpunkt der Alarmauslösung, während Einschränkungen wie der Stromsparmodus berücksichtigt werden.

Entwickler können die folgenden API-Garantien nutzen, um den Zeitpunkt der ungenauen Alarmzustellung anzupassen.

Nach einer bestimmten Zeit einen Alarm auslösen

Wenn Ihre App set(), setInexactRepeating() oder setAndAllowWhileIdle() aufruft, wird der Alarm nie vor der angegebenen Auslösungszeit ausgelöst.

Unter Android 12 (API-Level 31) und höher löst das System den Alarm innerhalb einer Stunde nach der festgelegten Auslösungszeit aus, es sei denn, es gelten Einschränkungen für den Energiesparmodus, z. B. der Energiesparmodus oder der Stromsparmodus.

Einen Alarm während eines bestimmten Zeitfensters auslösen

Wenn Ihre App setWindow() aufruft, wird der Alarm nie vor der angegebenen Auslösezeit ausgelöst. Sofern keine Einschränkungen zur Energiesparmodus gelten, wird der Alarm innerhalb des angegebenen Zeitfensters ab der angegebenen Auslösungszeit 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 auf 600000 beschränkt.

Einen sich wiederholenden Alarm in ungefähr regelmäßigen Intervallen auslösen

Wenn Ihre App setInexactRepeating() aufruft, ruft das System mehrere Alarme auf:

  1. Der erste Alarm wird innerhalb des angegebenen Zeitfensters ausgelöst, beginnend ab der angegebenen Auslösungszeit.
  2. Nachfolgende Alarme werden normalerweise nach Ablauf des angegebenen Zeitfensters ausgelöst. Die Zeit zwischen zwei aufeinanderfolgenden Alarmaufrufen kann variieren.

Genauen Wecker stellen

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

Die meisten Apps können Aufgaben und Ereignisse mit ungenauen Alarmen planen, um mehrere häufige Anwendungsfälle auszuführen. 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 Wecker zu verwenden.

Anwendungsfälle, bei denen möglicherweise kein exakter Alarm erforderlich ist

Die folgende Liste zeigt gängige Workflows, bei denen kein exakter Alarm erforderlich ist:

Zeitliche Vorgänge während der Lebensdauer Ihrer App planen
Die Klasse Handler umfasst mehrere gute Methoden zur Verarbeitung von Zeitvorgängen, z. B. postAtTime() und postDelayed() alle n Sekunden, während die App aktiv ist. Diese APIs basieren auf der Systemverfügbarkeit und nicht auf der Echtzeit.
Geplante Hintergrundarbeiten wie das Aktualisieren der App und das Hochladen von Protokollen
WorkManager bietet eine Möglichkeit, zeitabhängige regelmäßige Arbeiten 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 inaktiv ist)
Einen ungenauen Wecker verwenden. Rufen Sie insbesondere setAndAllowWhileIdle() auf.
Vom Nutzer angegebene Aktion, die nach einer bestimmten Zeit erfolgen soll
Einen ungenauen Wecker verwenden. Rufen Sie insbesondere set() auf.
Vom Nutzer angegebene Aktion, die innerhalb eines bestimmten Zeitfensters ausgeführt werden kann
Einen ungenauen Wecker verwenden. Rufen Sie insbesondere 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 genauen Alarms

Ihre App kann mit einer der folgenden Methoden exakte Alarme einstellen. Diese Methoden sind so angeordnet, dass die Methoden, die am Ende der Liste stehen, zeitkritische Aufgaben ausführen, aber mehr Systemressourcen erfordern.

setExact()

Einen Alarm zu einem nahezu exakten Zeitpunkt in der Zukunft auslösen, sofern keine anderen akkusparenden Maßnahmen 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 exakten Zeitpunkt in der Zukunft auslösen, selbst wenn Maßnahmen zur Batterieschonung aktiviert sind.

setAlarmClock()

Einen Alarm zu einem bestimmten Zeitpunkt in der Zukunft auslösen. Da diese Alarme für die Nutzer gut sichtbar sind, passt das System die Lieferdauer nie an. Das System identifiziert diese Alarme als die kritischsten und lässt bei Bedarf Energiesparmodus Modi zu, um die Alarme zu liefern.

Verbrauch von Systemressourcen

Wenn das System exakte Alarme auslöst, die von Ihrer App festgelegt werden, verbraucht das Gerät viele Ressourcen, wie z. B. die Akkulaufzeit, insbesondere wenn es sich im 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, können Sie diese mit WorkManager oder JobScheduler aus dem BroadcastReceiver des Weckers planen. Wenn Sie Aktionen ausführen möchten, während sich das Gerät im Stromsparmodus befindet, können Sie mit setAndAllowWhileIdle() einen ungenauen Alarm erstellen und einen Job über den Alarm starten.

Deklariere die entsprechende genaue Alarmberechtigung

Wenn Ihre App auf Android 12 oder höher ausgerichtet ist, benötigen Sie den speziellen App-Zugriff für Wecker und Erinnerungen. Dazu müssen Sie die Berechtigung SCHEDULE_EXACT_ALARM in der Manifestdatei Ihrer App deklarieren, 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 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 gewährt und unterstützen unterschiedliche Anwendungsfälle. Ihre App sollte nur dann exakte Alarme verwenden und die Berechtigung SCHEDULE_EXACT_ALARM oder USE_EXACT_ALARM deklarieren, wenn eine für Nutzer sichtbare Funktion zeitgenaue Aktionen erfordert.

USE_EXACT_ALARM

SCHEDULE_EXACT_ALARM

  • Vom Nutzer gewährt
  • Breiter gefasste Anwendungsfälle
  • Apps sollten bestätigen, dass die Berechtigung nicht widerrufen wurde

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 Sie prüfen möchten, ob Ihre App die Berechtigung hat, rufen Sie canScheduleExactAlarms() auf, bevor Sie versuchen, einen genauen Alarm einzustellen. Wenn die Berechtigung SCHEDULE_EXACT_ALARM für Ihre App widerrufen wird, wird diese beendet und alle zukünftigen exakten Alarme werden gelöscht. Das bedeutet auch, dass der von canScheduleExactAlarms() zurückgegebene Wert für den gesamten Lebenszyklus der Anwendung gültig bleibt.

Wenn Ihrer Anwendung die Berechtigung SCHEDULE_EXACT_ALARMS gewährt wird, sendet das System die Übertragung ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED. Ihre App sollte einen Broadcast-Empfänger implementieren, der Folgendes erfüllt:

  1. Bestätigt, dass deine 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 unmittelbar danach widerruft.
  2. Plant alle exakten Alarme, die deine App benötigt, basierend auf ihrem aktuellen Status neu. Diese Logik sollte der der Anwendung ähneln, wenn sie die ACTION_BOOT_COMPLETED-Übertragung empfängt.

Nutzer bitten, die Berechtigung SCHEDULE_EXACT_ALARM zu gewähren

Die Option heißt „Festlegen von Weckern und Erinnerungen zulassen“.
Abbildung 1: Auf der speziellen App-Zugriffsseite „Wecker und Erinnerungen“ in den Systemeinstellungen können Nutzer deiner App erlauben, exakte Alarme einzustellen.

Bei Bedarf können Sie Nutzer in den Systemeinstellungen zum Bildschirm Wecker und Erinnerungen weiterleiten (siehe Abbildung 1). Führen Sie dazu die folgenden Schritte aus:

  1. Erläutere in der Benutzeroberfläche deiner App, warum die App exakte Alarme planen muss.
  2. Rufen Sie einen Intent auf, der die Intent-Aktion ACTION_REQUEST_SCHEDULE_EXACT_ALARM enthält.

Sich wiederholenden Wecker stellen

Durch wiederkehrende Alarme kann das System deine App nach einem wiederkehrenden Zeitplan benachrichtigen.

Ein schlecht konzipierter Alarm kann zu einer schnellen Akkuentladung führen und die Server erheblich belasten. Aus diesem Grund sind unter Android 4.4 (API-Level 19) und höher alle sich wiederholenden Alarme nicht exakte Alarme.

Ein sich wiederholender Alarm hat folgende Eigenschaften:

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

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

  • Der Alarmintervall. Zum Beispiel einmal pro Tag, stündlich oder alle 5 Minuten.

  • Ausstehender Intent, der ausgelöst wird, wenn der Alarm ausgelöst wird. Wenn Sie einen zweiten Wecker mit demselben ausstehenden Intent festlegen, wird der ursprüngliche Wecker dadurch ersetzt.

Wenn Sie einen PendingIntent() abbrechen möchten, übergeben Sie FLAG_NO_CREATE an PendingIntent.getService(), um eine Instanz des Intents abzurufen (falls vorhanden). Anschließend übergeben Sie diesen Intent 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

Einer der ersten Überlegungen bei der Verwendung eines sich wiederholenden Alarms ist der Typ des Alarms.

Es gibt zwei allgemeine Uhrtypen für Alarme: „Verstrichene Echtzeit“ und „Echtzeituhr“ (RTC). Für die verstrichene Echtzeit wird die Zeit seit dem Systemstart als Referenz verwendet und die Echtzeituhr verwendet die UTC-Zeit (Wanduhr). Das bedeutet, dass die verstrichene Echtzeit zum Einstellen eines Alarms basierend auf dem Ablauf der Zeit geeignet ist (z. B. ein Alarm, der alle 30 Sekunden ausgelöst wird), da er nicht von der Zeitzone oder dem Gebietsschema beeinflusst wird. Der Echtzeituhrtyp eignet sich besser für Alarme, die vom aktuellen Gebietsschema abhängen.

Beide Typen haben eine „Wakeup“-Version, die angibt, die CPU des Geräts zu aktivieren, wenn der Bildschirm ausgeschaltet ist. Dadurch wird der Wecker zur geplanten Zeit ausgelöst. Dies ist nützlich, wenn Ihre App eine Zeitabhängigkeit hat. Das ist beispielsweise der Fall, wenn das Zeitfenster zur Durchführung eines bestimmten Vorgangs begrenzt ist. Wenn du nicht die Aufwachversion deines Alarmtyps verwendest, werden alle sich wiederholenden Alarme ausgelöst, wenn dein Gerät das nächste Mal wach ist.

Wenn der Alarm lediglich in einem bestimmten Intervall ausgelöst werden soll, z. B. jede halbe Stunde, verwenden Sie einen der verstrichenen Echtzeittypen. Im Allgemeinen ist das die bessere Wahl.

Wenn Ihr Alarm zu einer bestimmten Tageszeit ausgelöst werden soll, wählen Sie einen der uhrbasierten Echtzeituhrtypen aus. Beachten Sie jedoch, dass dieser Ansatz einige Nachteile haben kann. 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 funktioniert auch nicht gut, wie oben beschrieben. Wir empfehlen, nach Möglichkeit einen „Verstrichenen Echtzeit-Alarm“ zu verwenden.

Folgende Typen stehen zur Verfügung:

  • ELAPSED_REALTIME: Löst den ausstehenden Intent basierend auf der Zeit seit dem Starten des Geräts aus, aktiviert aber nicht. Die verstrichene Zeit umfasst alle Zeiten, in denen das Gerät im Ruhemodus war.

  • ELAPSED_REALTIME_WAKEUP: Aktiviert das Gerät und löst den ausstehenden Intent nach Ablauf der angegebenen Zeit seit dem Starten des Geräts aus.

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

  • RTC_WAKEUP: Weckt das Gerät, um den ausstehenden Intent zur angegebenen Zeit auszulösen.

Beispiele für abgelaufene Echtzeitalarme

Hier einige Beispiele für die Verwendung von ELAPSED_REALTIME_WAKEUP

Ruhemodus des Geräts nach 30 Minuten beenden und dann alle 30 Minuten:

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

Den Ruhemodus des Geräts in einer Minute beenden und einen einmaligen (nicht sich wiederholenden) Wecker auslö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 Echtzeit-Wecker

Hier sind einige Beispiele für die Verwendung von RTC_WAKEUP.

Wecke das Gerät gegen 14:00 Uhr auf, um den Alarm auszulösen, und wiederhole den Vorgang einmal täglich:

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

Aktivieren Sie das Gerät genau um 8:30 Uhr, damit der Alarm ausgelöst wird. Anschließend gehen Sie alle 20 Minuten so vor:

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

Lege fest, wie genau dein Alarm sein soll

Wie bereits beschrieben, ist die Auswahl des Alarmtyps oft der erste Schritt bei der Erstellung eines Alarms. Ein weiterer Unterschied ist die Präzision des Alarms. Für die meisten Anwendungen ist setInexactRepeating() die richtige Wahl. Wenn Sie diese Methode verwenden, synchronisiert Android mehrere ungenaue wiederkehrende Alarme und löst sie gleichzeitig aus. Dies reduziert die Entladung des Akkus.

Vermeiden Sie nach Möglichkeit genaue Alarme. Für die seltene App, die feste Zeitanforderungen hat, können Sie jedoch einen genauen Alarm festlegen, indem Sie setRepeating() aufrufen.

Mit setInexactRepeating() können Sie ein benutzerdefiniertes Intervall nicht wie mit setRepeating() angeben. Sie müssen eine der Intervallkonstanten wie INTERVAL_FIFTEEN_MINUTES, INTERVAL_DAY usw. verwenden. Die vollständige Liste finden Sie unter AlarmManager.

Einen Wecker ausschalten

Je nach App möchten Sie möglicherweise die Möglichkeit zum Abbrechen des Weckers bieten. Um einen Alarm auszuschalten, rufen Sie im Alarm Manager cancel() auf und übergeben Sie den PendingIntent, der nicht mehr ausgelöst werden soll. Beispiele:

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 beim Neustart des Geräts auslösen

Standardmäßig werden alle Wecker beim Herunterfahren eines Geräts abgebrochen. Um dies zu verhindern, kannst du deine App so konfigurieren, dass ein sich wiederholender Wecker automatisch neu gestartet wird, wenn der Nutzer das Gerät neu startet. Dadurch wird sichergestellt, dass das AlarmManager seine Aufgabe fortsetzt, ohne dass der Nutzer den Alarm manuell neu starten muss.

Gehe dazu so vor:

  1. Legen Sie im Manifest Ihrer App die Berechtigung RECEIVE_BOOT_COMPLETED fest. Dadurch kann deine App das ACTION_BOOT_COMPLETED empfangen, das nach dem Start des Systems übertragen 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 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>

    Der Bootempfänger ist im Manifest auf android:enabled="false" gesetzt. Das bedeutet, dass der Empfänger nur aufgerufen wird, wenn dies von der Anwendung explizit aktiviert wurde. Dadurch wird verhindert, dass der Boot-Empfänger unnötigerweise aufgerufen wird. So aktivieren Sie einen Empfänger, 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 die programmatische Aktivierung des Empfängers wird die Manifesteinstellung auch bei Neustarts überschrieben. Der Empfänger bleibt aktiviert, bis Ihre App ihn deaktiviert. So kannst du einen Empfänger deaktivieren, z. B. wenn der Nutzer einen Alarm 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, wenn sich das Gerät im Stromsparmodus befindet

Geräte mit Android 6.0 (API-Level 23) unterstützen den Stromsparmodus, der die Akkulaufzeit der Geräte verlängert. Alarme werden nicht ausgelöst, wenn sich das Gerät im Stromsparmodus befindet. Geplante Alarme werden so lange ausgesetzt, bis das Gerät den Stromsparmodus beendet. Wenn Sie Aufgaben auch dann ausführen müssen, wenn das Gerät inaktiv ist, haben Sie mehrere Möglichkeiten:

  • Stellen Sie einen genauen Wecker.

  • WorkManager API verwenden, die für 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 Ihres sich wiederholenden Weckers treffen, kann Auswirkungen darauf haben, wie Ihre App Systemressourcen nutzt oder missbraucht. Stellen Sie sich z. B. eine beliebte App vor, die sich mit einem Server synchronisiert. Wenn die Synchronisierung auf der Uhrzeit basiert und jede Instanz der Anwendung um 23:00 Uhr synchronisiert wird, kann die Serverlast zu einer hohen Latenz oder sogar zu einer Dienstverweigerung führen. Befolge diese Best Practices bei der Verwendung von Alarmen:

  • Fügen Sie allen Netzwerkanfragen, die infolge eines wiederholten Alarms ausgelöst werden, Zufälligkeit (Jitter) hinzu:

    • Arbeiten Sie vor Ort, wenn der Alarm ausgelöst wird. „Lokale Arbeit“ bezieht sich auf alles, was keinen Server erreicht oder Daten vom Server benötigt.

    • Gleichzeitig soll der Alarm mit den Netzwerkanfragen so eingestellt werden, dass er zu einem zufälligen Zeitpunkt ausgelöst wird.

  • Behalte die Alarmhäufigkeit auf ein Minimum.

  • Aktivieren Sie das Gerät nicht unnötig. Dieses Verhalten hängt vom Alarmtyp ab, wie unter Alarmtyp auswählen beschrieben.

  • Stellen Sie die Auslösungszeit Ihres Weckers nicht präziser ein, 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. Dies reduziert die Gesamtzahl der Aktivierungen des Systems, sodass der Akku weniger entladen wird. Ab Android 4.4 (API-Level 19) sind alle wiederkehrenden Alarme nicht exakte Alarme. setInexactRepeating() ist zwar eine Verbesserung gegenüber setRepeating(), kann aber dennoch einen Server überlasten, wenn jede Instanz einer Anwendung den Server etwa zur gleichen Zeit erreicht. Fügen Sie daher für Netzwerkanfragen Ihren Alarmen eine gewisse Zufälligkeit hinzu, wie bereits erläutert.

  • Wenn möglich, sollte der Wecker nicht auf der Uhrzeit basieren.

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