Wecker stellen

Alarme (basierend auf der Klasse AlarmManager) geben Ihnen die Möglichkeit, zeitbasierte Vorgänge außerhalb der Lebensdauer Ihrer Anwendung auszuführen. Sie können beispielsweise einen Alarm verwenden, um einen lang andauernden Vorgang zu starten, z. B. einmal am Tag einen Dienst zu starten, um eine Wettervorhersage herunterzuladen.

Alarme haben folgende Eigenschaften:

  • Sie ermöglichen es, Intents zu festgelegten Zeiten und/oder Intervallen auszulösen.

  • Sie können sie in Verbindung mit Broadcast-Empfängern verwenden, um Jobs oder WorkRequests für die Ausführung anderer Vorgänge zu planen.

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

  • Sie helfen Ihnen, den Ressourcenbedarf Ihrer Anwendung zu minimieren. Sie können Vorgänge planen, ohne Timer oder kontinuierlich ausgeführte Dienste zu benötigen.

Ungenauen Alarm einstellen

Wenn eine App einen ungenauen Alarm ausgibt, gibt das System den Alarm zu einem späteren Zeitpunkt aus. Ungenaue Alarme bieten einige Garantien für den Zeitpunkt der Alarmauslöser, wobei gleichzeitig Einschränkungen für den Energiesparmodus wie den Stromsparmodus berücksichtigt werden.

Entwickler können die folgenden API-Garantien nutzen, um den Zeitpunkt der Zustellung ungenauer Alarme anzupassen.

Nach einer bestimmten Zeit einen Wecker stellen

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

Unter Android 12 (API-Level 31) und höher löst das System den Alarm innerhalb einer Stunde nach der angegebenen Auslösungszeit aus, es sei denn, es gibt Einschränkungen zum Energiesparmodus wie Energiesparmodus oder Stromsparmodus.

Alarm während eines bestimmten Zeitfensters auslösen

Wenn deine App setWindow() aufruft, wird der Alarm nie vor der angegebenen Auslösezeit ausgelöst. Sofern keine Einschränkungen zur Energieeinsparung gelten, wird der Alarm innerhalb des angegebenen Zeitfensters ausgelöst, beginnend ab der festgelegten Auslösungszeit.

Wenn Ihre App auf Android 12 oder höher ausgerichtet ist, kann das System den Aufruf eines nicht exakten Alarms mit Zeitfenster um mindestens 10 Minuten verzögern. Aus diesem Grund werden windowLengthMillis-Parameterwerte unter 600000 auf 600000 begrenzt.

In regelmäßigen Abständen einen sich wiederholenden Alarm auslösen

Wenn deine App setInexactRepeating() aufruft, löst das System mehrere Alarme aus:

  1. Der erste Alarm wird innerhalb des angegebenen Zeitfensters ausgelöst, beginnend ab der festgelegten Auslösungszeit.
  2. Nachfolgende Alarme werden normalerweise nach Ablauf des angegebenen Zeitfensters ausgelöst. Die Zeit zwischen zwei aufeinanderfolgenden Alarmen 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 Alarmen planen, um mehrere häufige Anwendungsfälle zu erfüllen. Wenn die Hauptfunktion Ihrer App von einem genau abgestimmten Wecker abhängt, z. B. bei einer Wecker- oder Kalender-App, können Sie stattdessen einen exakten Wecker verwenden.

Anwendungsfälle, die möglicherweise keine genauen Alarme erfordern

Die folgende Liste zeigt gängige Arbeitsabläufe, für die möglicherweise kein exakter Alarm erforderlich ist:

Timing von Vorgängen während der Lebensdauer deiner App planen
Die Klasse Handler enthält mehrere gute Methoden zur Verarbeitung von Zeitvorgängen, z. B. alle n Sekunden, während die Anwendung aktiv ist: postAtTime() und postDelayed(). Beachten Sie, dass diese APIs auf der Systemverfügbarkeit und nicht auf Echtzeit basieren.
Geplante Hintergrundarbeiten wie das Aktualisieren der App und das Hochladen von Protokollen
Mit
WorkManager können Sie zeitabhängige regelmäßige Arbeiten 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 bei Inaktivität)
Einen ungenauen Alarm verwenden. Rufen Sie insbesondere setAndAllowWhileIdle() auf.
Vom Nutzer angegebene Aktion, die nach einer bestimmten Zeit ausgeführt werden soll
Einen ungenauen Alarm verwenden. Rufen Sie insbesondere set() auf.
Eine vom Nutzer angegebene Aktion, die innerhalb eines bestimmten Zeitfensters ausgeführt werden kann
Einen ungenauen Alarm verwenden. Rufen Sie insbesondere setWindow() auf. Wenn Ihre App auf Android 12 oder höher ausgerichtet ist, beträgt die kleinstmögliche Fensterlänge 10 Minuten.

Möglichkeiten zum Stellen eines exakten Alarms

Mit einer der folgenden Methoden kann Ihre App exakte Alarme einstellen. Diese Methoden sind so angeordnet, dass diejenigen, die sich weiter am Ende der Liste befinden, zeitkritische Aufgaben erfüllen, aber mehr Systemressourcen benötigen.

setExact()

Ein Alarm kann zu einem fast genauen Zeitpunkt in der Zukunft ausgelöst werden, solange keine anderen energiesparenden Maßnahmen aktiv sind.

Verwende diese Methode, um exakte Alarme festzulegen, es sei denn, die Arbeit deiner App ist für den Nutzer zeitkritisch.

setExactAndAllowWhileIdle()

Ein Alarm kann zu einem nahezu genauen Zeitpunkt in der Zukunft ausgelöst werden, selbst wenn Energiesparmodusn bereits aktiv 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 verlässt bei Bedarf den Energiesparmodus, um die Alarme zu liefern.

Verbrauch von Systemressourcen

Wenn das System exakte Alarme auslöst, die von deiner App ausgelöst werden, verbraucht das Gerät sehr viele Ressourcen, z. B. die Akkulaufzeit, insbesondere im Energiesparmodus. Außerdem kann das System diese Anfragen nicht einfach in Stapeln zusammenfassen, um die Ressourcen effizienter zu nutzen.

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

Deklariere die entsprechende Berechtigung für den exakten Alarm

Wenn deine App auf Android 12 oder höher ausgerichtet ist, benötigst du den speziellen App-Zugriff „Wecker und Erinnerungen“. Deklariere dazu die Berechtigung SCHEDULE_EXACT_ALARM in der Manifestdatei deiner 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 die Berechtigung USE_EXACT_ALARM erklären.

<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. Deine App sollte nur dann exakte Alarme verwenden und entweder die Berechtigung SCHEDULE_EXACT_ALARM oder USE_EXACT_ALARM deklarieren, wenn eine für Nutzer sichtbare Funktion in deiner App zeitgenaue Aktionen erfordert.

USE_EXACT_ALARM

SCHEDULE_EXACT_ALARM

  • Vom Nutzer gewährt
  • Breitere Auswahl an Anwendungsfällen
  • Apps müssen bestätigen, dass die Berechtigung nicht widerrufen wurde

Die Berechtigung SCHEDULE_EXACT_ALARM wird für 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 an 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 beim Upgrade des Geräts auf Android 14 vorab gewährt.

Hinweis: Wenn der exakte Alarm mit einem OnAlarmListener-Objekt wie z. B. mit der setExact API eingestellt wird, 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 erteilt 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 einzustellen. Wenn die Berechtigung SCHEDULE_EXACT_ALARM für deine App widerrufen wird, wird die App beendet und alle zukünftigen genauen Wecker werden abgebrochen. Dies 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 die Übertragung ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED an sie. In Ihrer App sollte ein Übertragungsempfänger implementiert werden, der folgende Aufgaben erfüllt:

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

Nutzer um die Berechtigung SCHEDULE_EXACT_ALARM bitten

Die Option heißt „Einrichten von Weckern und Erinnerungen zulassen“
Abbildung 1. In den Systemeinstellungen finden Nutzer die spezielle App-Zugriffsseite für „Wecker und Erinnerungen“. Dort können sie Ihrer App erlauben, exakte Alarme festzulegen.

Bei Bedarf kannst du Nutzer zum Bildschirm Alarme & Erinnerungen in den Systemeinstellungen weiterleiten, wie in Abbildung 1 dargestellt. Führen Sie dazu die folgenden Schritte aus:

  1. Erklären Sie dem Nutzer auf der Benutzeroberfläche Ihrer Anwendung, warum die Anwendung 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 den Akku stark beanspruchen und die Server erheblich belasten. Aus diesem Grund sind alle sich wiederholenden Alarme unter Android 4.4 (API-Level 19) und höher unpräzise Alarme.

Ein sich wiederholender Alarm hat die folgenden Eigenschaften:

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

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

  • Das Intervall des Alarms. Zum Beispiel einmal täglich, stündlich oder alle 5 Minuten.

  • Ein ausstehender Intent, der ausgelöst wird, wenn der Alarm ausgelöst wird. Wenn Sie einen zweiten Alarm festlegen, der denselben ausstehenden Intent verwendet, ersetzt er den ursprünglichen Alarm.

Wenn Sie ein PendingIntent() abbrechen möchten, übergeben Sie FLAG_NO_CREATE an PendingIntent.getService(), um eine Instanz des Intents abzurufen (sofern vorhanden). Ü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

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

Es gibt zwei allgemeine Uhrtypen für Wecker: „Verstrichene Echtzeit“ und „Echtzeituhr“. Die verstrichene Echtzeit verwendet die „Zeit seit Systemstart“ als Referenz und die Echtzeituhr verwendet die UTC-Zeit (Zeitzeit). Das bedeutet, dass die verstrichene Echtzeit sich dafür eignet, einen Alarm basierend auf dem Zeitverlauf einzustellen (z. B. ein Alarm, der alle 30 Sekunden ausgelöst wird), da er nicht von Zeitzone oder Sprache beeinflusst wird. Die Echtzeituhr eignet sich besser für Wecker, die von der aktuellen Sprache abhängen.

Beide Typen haben eine Wakeup-Version, die angibt, dass die CPU des Geräts aktiviert werden soll, wenn der Bildschirm ausgeschaltet ist. Dadurch wird sichergestellt, dass der Alarm zum geplanten Zeitpunkt ausgelöst wird. Dies ist nützlich, wenn Ihre App zeitabhängig ist. z. B. wenn das Zeitfenster begrenzt ist, um einen bestimmten Vorgang auszuführen. Wenn du nicht die Wakeup-Version deines Weckertyps verwendest, werden alle sich wiederholenden Wecker ausgelöst, wenn dein Gerät das nächste Mal wach ist.

Wenn der Alarm nur in einem bestimmten Intervall ausgelöst werden soll, zum Beispiel jede halbe Stunde, verwende einen der verstrichenen Echtzeittypen. Im Allgemeinen ist das die bessere Wahl.

Wenn der Alarm zu einer bestimmten Tageszeit ausgelöst werden soll, wähle einen der uhrbasierten Echtzeituhrtypen aus. Beachten Sie jedoch, dass dieser Ansatz einige Nachteile mit sich bringen 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 lässt sich ebenfalls nicht gut skalieren, wie oben erläutert. Wir empfehlen, wenn möglich einen Wecker in der verstrichenen Zeit zu verwenden.

Hier 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. Das Gerät wird jedoch nicht aktiviert. Die verstrichene Zeit umfasst die Zeit, in der sich das Gerät im Ruhemodus befand.

  • ELAPSED_REALTIME_WAKEUP: Das Gerät wird aktiviert und der ausstehende Intent wird nach Ablauf der angegebenen Zeitspanne seit dem Starten des Geräts ausgelöst.

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

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

Beispiele für verstrichene Echtzeit-Alarme

Hier einige Beispiele für die Verwendung von ELAPSED_REALTIME_WAKEUP

Wecke das Gerät in 30 Minuten, um den Alarm auszulösen, und danach 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);

Aktivieren Sie das Gerät, um in einer Minute einen einmaligen (sich nicht wiederholenden) Wecker 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 Echtzeit-Wecker

Hier einige Beispiele für die Verwendung von RTC_WAKEUP.

Wecke das Gerät auf, um den Alarm gegen 14:00 Uhr auszulösen. Wiederhole den Vorgang einmal am Tag 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, damit der Alarm genau um 8:30 Uhr und danach alle 20 Minuten ausgelöst wird:

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

Präzision des Weckers festlegen

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 Anwendungen ist setInexactRepeating() die richtige Wahl. Bei dieser Methode synchronisiert Android mehrere sich wiederholende Alarme und löst sie gleichzeitig aus. Dadurch wird der Akku geschont.

Verwende möglichst keine exakten Alarme. Für die seltene Anwendung mit starren Zeitanforderungen können Sie jedoch einen genauen 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. Die vollständige Liste finden Sie unter AlarmManager.

Einen Wecker ausschalten

Je nach App können Sie den Wecker auch abstellen. Rufe zum Abbrechen eines Alarms cancel() im Alarm Manager auf und übergib 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);
}

Einen Wecker stellen, wenn das Gerät neu gestartet wird

Standardmäßig werden alle Alarme abgebrochen, wenn ein Gerät ausgeschaltet wird. Um dies zu verhindern, kannst du deine App so gestalten, dass ein wiederkehrender Wecker automatisch neu startet, wenn der Nutzer das Gerät neu startet. Dadurch wird sichergestellt, dass AlarmManager weiterhin seine Aufgabe 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 App fest. So kann Ihre App die ACTION_BOOT_COMPLETED empfangen, die übertragen wird, nachdem das System gestartet wurde. 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 der Manifestdatei Ihrer App den Empfänger 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 Bootempfänger im Manifest auf android:enabled="false" gesetzt ist. Dies bedeutet, dass der Empfänger nur dann aufgerufen wird, wenn die Anwendung dies explizit aktiviert. Dadurch wird verhindert, dass der Bootempfänger unnötig aufgerufen wird. So kannst du einen Empfänger aktivieren (z. B. wenn der Nutzer einen Alarm 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 auch dann aktiviert, wenn der Nutzer das Gerät neu startet. Mit anderen Worten: Wenn Sie den Empfänger programmatisch aktivieren, wird die Manifesteinstellung auch bei Neustarts überschrieben. Der Empfänger bleibt aktiviert, bis ihn deine App 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);
    

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

Geräte mit Android 6.0 (API-Level 23) unterstützen den Stromsparmodus, mit dem sich die Akkulaufzeit verlängern lässt. Im Energiesparmodus des Geräts werden keine Wecker ausgelöst. Geplante Alarme werden erst dann ausgelöst, wenn der Stromsparmodus des Geräts beendet wird. Falls Sie Arbeiten auch bei inaktivem Gerät ausführen müssen, gibt es mehrere Möglichkeiten:

  • Stellen Sie einen exakten Alarm ein.

  • Verwenden Sie die WorkManager API, 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 werden kann. Weitere Informationen finden Sie unter Aufgaben mit WorkManager planen.

Best Practices

Jede Entscheidung, die du bei der Gestaltung eines wiederkehrenden Alarms triffst, kann Auswirkungen darauf haben, wie deine App Systemressourcen verwendet (oder missbraucht). Stellen Sie sich zum Beispiel eine beliebte App vor, die mit einem Server synchronisiert wird. Wenn die Synchronisierung auf der Uhrzeit basiert und jede Instanz der Anwendung um 23:00 Uhr synchronisiert wird, kann die Auslastung des Servers zu einer hohen Latenz oder sogar zu einer Dienstverweigerung führen. Beachte diese Best Practices bei der Verwendung von Alarmen:

  • Weisen Sie allen Netzwerkanfragen, die als Folge eines sich wiederholenden Weckers ausgelöst werden, eine Zufälligkeit (Jitter) hinzu:

    • Erledige vor Ort Arbeit, wenn der Alarm ausgelöst wird. „Lokale Arbeit“ bedeutet alles, was nicht auf einen Server trifft oder die Daten vom Server erfordert.

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

  • Beschränke die Alarmhäufigkeit auf ein Minimum.

  • Aktivieren Sie das Gerät nicht unnötig. Dieses Verhalten wird durch den Alarmtyp bestimmt, wie unter Alarmtyp auswählen beschrieben.

  • Die Auslösungszeit deines Alarms darf nicht genauer sein, als es sein muss.

    Verwenden Sie setInexactRepeating() anstelle von setRepeating(). Wenn du setInexactRepeating() verwendest, synchronisiert Android wiederkehrende Wecker aus mehreren Apps und löst sie gleichzeitig aus. Dadurch verringert sich die Häufigkeit, mit der das System den Ruhemodus des Geräts beenden muss, um den Akku zu schonen. Ab Android 4.4 (API-Ebene 19) sind alle wiederkehrenden Alarme ungenaue Alarme. setInexactRepeating() ist zwar eine Verbesserung gegenüber setRepeating(), kann aber einen Server dennoch überfordern, wenn jede Instanz einer Anwendung den Server etwa zur selben Zeit erreicht. Fügen Sie daher bei Netzwerkanfragen, wie oben erläutert, einen gewissen Zufallsfaktor für Ihre Alarme ein.

  • Richte deinen Wecker nach Möglichkeit nicht auf die Uhrzeit zurück.

    Wiederholte Alarme, die auf einer genauen 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.