Planowanie alarmów

Alarmy (oparte na klasie AlarmManager) umożliwiają wykonywanie operacji zależnych od czasu poza czasem działania aplikacji. Na przykład możesz użyć alarmu do zainicjowania długo trwającej operacji, takiej jak uruchamiając usługę raz dziennie, aby pobrać prognozę pogody.

Alarmy mają te cechy:

  • Umożliwiają uruchamianie intencji w ustalonych odstępach czasu lub w określonych odstępach czasu.

  • Można ich używać w połączeniu z odbiornikami, aby zaplanować jobs lub WorkRequests do wykonania inne operacji.

  • Działa ona poza aplikacją, więc możesz jej używać do wywoływania zdarzeń lub działań nawet wtedy, gdy aplikacja nie jest uruchomiona, a urządzenie jest uśpione.

  • Pomagają zminimalizować wymagania dotyczące zasobów aplikacji. Możesz zaplanować operacje bez korzystania z zegarów ani usług działających w ciągu.

.

Ustawianie nieprecyzyjnego alarmu

Gdy aplikacja ustawi nieprecyzyjny alarm, system wyświetli go w przyszłości. Alarmy nieprecyzyjne dają pewne gwarancje czasu dostarczania alarmów przy jednoczesnym przestrzeganiu ograniczeń dotyczących oszczędzania baterii, takich jak: Uśpienie.

Deweloperzy mogą wykorzystać poniższe gwarancje interfejsu API, aby dostosować czas podanie nieprecyzyjnego alarmu.

Wysyłanie alarmu po określonej godzinie

Jeśli aplikacja wywołuje set(), setInexactRepeating(), lub setAndAllowWhileIdle(), alarm nigdy nie włączy się przed podanym czasem wyzwalania.

W Androidzie 12 (poziom API 31) i nowszych system wywołuje alarm w ciągu 1 godziny od podanego czasu uruchomienia, chyba że obowiązują ograniczenia dotyczące oszczędzania baterii, takie jak Oszczędzanie baterii czy Doze.

Dostarcz alarm w wybranym przedziale czasu

Jeśli aplikacja zadzwoni pod numer setWindow(), alarm nigdy nie włączy się przed dostarczonym w czasie wyzwalacza. Jeśli nie są włączone żadne ograniczenia dotyczące oszczędzania baterii, alarm jest włączony dostarczone w określonym przedziale czasu, począwszy od danego wyzwalacza obecnie się znajdujesz.

Jeśli Twoja aplikacja jest przeznaczona na Androida 12 lub nowszego, system może opóźnić wywołanie alarmu nieprecyzyjnego o co najmniej 10 minut. Z tego powodu wartości parametrów windowLengthMillis poniżej 600000 są przycinane do 600000.

Uruchamiaj powtarzający się alarm w mniej więcej regularnych odstępach czasu

Jeśli aplikacja wywołuje setInexactRepeating(), system wywołuje kilka alarmów:

  1. Pierwszy alarm włącza się w określonym oknie czasowym, licząc od podanego czasu uruchomienia.
  2. Kolejne alarmy zwykle włączają się po upływie określonego czasu. Czas między dwoma kolejnymi wywołaniami alarmu może się różnić.

Ustawianie precyzyjnego alarmu

System wywołuje dokładny alarm w konkretnym momencie w przyszłości.

Większość aplikacji może planować zadania i zdarzenia za pomocą nieprecyzyjnych alarmów, aby realizować popularne przypadki użycia. Jeśli główna funkcjonalność aplikacji zależy od alarmu o precyzyjnym czasie, np. w aplikacji budzika lub kalendarza, możesz użyć alarmu precyzyjnego.

Zastosowania, które mogą nie wymagać alarmów precyzyjnych

Poniżej znajdziesz listę typowych procesów, które mogą nie wymagać dokładnego alarmu:

Planowanie operacji czasowych w trakcie użytkowania aplikacji
Klasa Handler zawiera kilka przydatnych metod do obsługi operacji związanych z czasowaniem, takich jak wykonywanie pewnych działań co n sekund podczas działania aplikacji: postAtTime() i postDelayed(). Pamiętaj, że te interfejsy API zależą od czasu działania systemu a nie w czasie rzeczywistym.
zaplanowane działanie w tle, takie jak aktualizowanie aplikacji i przesyłanie dzienników;
WorkManager umożliwia zaplanowanie okresowych okresów zależnego od czasu pracy. Możesz podać interwał powtarzania i flexInterval (co najmniej 15 minut), aby określić szczegółowy czas działania.
Działanie określone przez użytkownika, które powinno zostać wykonane po określonym czasie (nawet jeśli system jest nieaktywny)
Użyj alarmu nieprecyzyjnego. A konkretnie chodzi o wywołanie setAndAllowWhileIdle()
działanie określone przez użytkownika, które powinno nastąpić po określonym czasie;
Użyj alarmu nieprecyzyjnego. A konkretnie chodzi o wywołanie set()
Działanie określone przez użytkownika, które może zostać wykonane w określonym przedziale czasu
Użyj alarmu nieprecyzyjnego. A konkretnie chodzi o wywołanie setWindow() Pamiętaj, że jeśli Twoja aplikacja jest przeznaczona na Androida 12 lub nowszego, minimalna dozwolona długość okna to 10 minut.

Sposoby ustawiania precyzyjnego alarmu

Aplikacja może ustawiać alarmy precyzyjne za pomocą jednej z tych metod. Metody te są uporządkowane w taki sposób, że te na samym dole listy wyświetlają się częściej do wykonywania kluczowych zadań, ale wymagają więcej zasobów systemowych.

setExact()

Włączanie alarmu w prawie dokładnym czasie w przyszłości, o ile nie są aktywne inne środki oszczędzania baterii.

Używaj tej metody, aby ustawiać alarmy precyzyjne, chyba że praca aplikacji jest krytyczna dla użytkownika.

setExactAndAllowWhileIdle()

Wywołuj alarm w przyszłości prawie dokładnym czasie, nawet przy oszczędzaniu baterii środków ochrony.

setAlarmClock()

Uruchom alarm o określonej godzinie w przyszłości. Ponieważ te alarmy są są bardzo widoczne dla użytkowników, system nigdy nie dostosowuje czasu dostawy. System uznaje je za najważniejsze i w razie potrzeby nie wyłącza trybów oszczędzania energii.

Wykorzystanie zasobów systemu

Gdy system uruchamia alarmy ustawione przez aplikację, urządzenie zużywa dużo zasobów, takich jak czas pracy na baterii, zwłaszcza jeśli jest w trybie oszczędzania energii. Ponadto system nie może łatwo grupować tych żądań, aby efektywniej wykorzystywać zasoby.

Zdecydowanie zalecamy utworzenie alarmu nieprecyzyjnego, gdy jak to tylko możliwe. Aby wykonać dłuższą pracę, zaplanuj ją za pomocą WorkManager lub JobScheduler od alarmu BroadcastReceiver Aby wykonywać pracę, podczas gdy urządzenie jest w trybie uśpienia, utwórz niedokładny alarm, używając: setAndAllowWhileIdle() i uruchomienie zadania z poziomu alarmu.

Zadeklaruj odpowiednie uprawnienia dostępu do precyzyjnych alarmów

Jeśli Twoja aplikacja jest kierowana na Androida 12 lub nowszego, musisz uzyskać "Alarmy i przypomnienia” aplikacji ze specjalnym dostępem. Aby to zrobić, zadeklaruj parametr SCHEDULE_EXACT_ALARM zgodnie z poniższym fragmentem kodu:

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

Jeśli Twoja aplikacja jest kierowana na Androida 13 (poziom interfejsu API 33) lub nowszego, możesz wybrać zadeklaruj SCHEDULE_EXACT_ALARM lub USE_EXACT_ALARM uprawnienia.

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

Chociaż uprawnienia SCHEDULE_EXACT_ALARM i USE_EXACT_ALARM które wskazują te same możliwości, są przyznawane w różny sposób i obsługują różne i zastosowania. Aplikacja powinna używać precyzyjnych alarmów i zadeklarować uprawnienie SCHEDULE_EXACT_ALARM lub USE_EXACT_ALARM tylko wtedy, gdy funkcja widoczna dla użytkowników wymaga wykonywania działań w precyzyjnie określonym czasie.

USE_EXACT_ALARM

SCHEDULE_EXACT_ALARM

  • Przyznane przez użytkownika
  • szerszy zakres zastosowań,
  • Aplikacje powinny potwierdzać, że uprawnienia nie zostały cofnięte

Uprawnienie SCHEDULE_EXACT_ALARM nie jest wstępnie przyznane nowym instalacjom aplikacji kierowane na Androida 13 (poziom interfejsu API 33) i nowsze wersje. Jeśli użytkownik przeniesie dane aplikacji na urządzenie z Androidem 14, korzystając z kopii zapasowej i przywracania, na nowym urządzeniu zostanie odrzucone uprawnienie SCHEDULE_EXACT_ALARM. Jeśli jednak istniejąca aplikacja ma już to uprawnienie, zostanie ono przyznane wstępnie, gdy aktualizacji urządzeń do Androida 14.

Uwaga: jeśli dokładny alarm jest ustawiany za pomocą obiektu OnAlarmListener, np. za pomocą interfejsu API setExact, uprawnienie SCHEDULE_EXACT_ALARM nie jest wymagane.

Używanie uprawnienia SCHEDULE_EXACT_ALARM

W przeciwieństwie do uprawnienia USE_EXACT_ALARM uprawnienie SCHEDULE_EXACT_ALARM musi zostać przyznane przez użytkownika. Zarówno użytkownik, jak i system mogą unieważnić Uprawnienie SCHEDULE_EXACT_ALARM.

Aby sprawdzić, czy aplikacja otrzymała odpowiednie uprawnienia, wywołaj canScheduleExactAlarms() zanim spróbujesz ustawić dokładny alarm. Gdy uprawnienie SCHEDULE_EXACT_ALARM zostanie cofnięty dla Twojej aplikacji, aplikacja przestanie działać i wszystkie przyszłe alarmy precyzyjne zostaną zostały anulowane. Oznacza to też, że wartość zwracana przez funkcję canScheduleExactAlarms() pozostaje prawidłowa przez cały cykl życia aplikacji.

Gdy aplikacja otrzyma uprawnienie SCHEDULE_EXACT_ALARMS, system wysyła do niej ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED. transmisję. Aplikacja powinna implementować odbiornik rozgłoszeniowy, który:

  1. potwierdza, że aplikacja nadal ma uprawnienia dostępu do określonych aplikacji. Aby to zrobić, zadzwoń pod numer canScheduleExactAlarms(). Ta kontrola chroni aplikację przed przypadkiem, gdy użytkownik przyzna jej uprawnienia, które zostanie cofnięte niemal natychmiast.
  2. Zmienia terminy alarmów precyzyjnych, których potrzebuje aplikacja, na podstawie jej bieżącego stanu. Ta logika powinna być podobna do tej, którą aplikacja wykonuje po otrzymaniu ACTION_BOOT_COMPLETEDtransmisji.

Poproś użytkowników o przyznanie uprawnień SCHEDULE_EXACT_ALARM

Opcja nosi nazwę „Zezwalaj na ustawianie alarmów i przypomnień”.
Rysunek 1. „Alarmy i przypomnienia” na stronie dostępu aplikacji w ustawieniach systemu, gdzie użytkownicy mogą zezwolić aplikacji na ustawianie alarmów.

W razie potrzeby można również przekierować użytkowników do sekcji Alarmy i ekran z przypomnieniami tak jak na rys. 1. Aby to zrobić:

  1. W interfejsie aplikacji wyjaśnij użytkownikowi, dlaczego aplikacja musi planować dokładne alarmy.
  2. Wywołaj intencję, która zawiera parametr ACTION_REQUEST_SCHEDULE_EXACT_ALARM działanie intencji.

Ustawianie alarmu powtarzającego się

Alarmy powtarzające się umożliwiają systemowi wysyłanie powiadomień do aplikacji zgodnie z określonym harmonogramem.

Źle zaprojektowany alarm może rozładowywać baterię i znacznie obciążać serwery. Dlatego w Androidzie 4.4 (poziom interfejsu API 19) i nowszych powtarzające się alarmy to alarmy nieprecyzyjne.

Alarm powtarzający ma te cechy:

  • Typ alarmu. Więcej informacji znajdziesz w artykule Wybieranie typu alarmu.

  • Czas wyzwalania. Jeśli podany czas wyzwolenia przypada w przeszłości, uruchamia się natychmiast.

  • Interwał alarmu. Na przykład raz dziennie, co godzinę lub co 5 minut.

  • Intencja oczekująca, która jest uruchamiana po aktywowaniu alarmu. Gdy ustawisz drugi alarm, który używa tego samego oczekującego zamiaru, zastąpi on pierwotny alarm.

Aby anulować PendingIntent(), prześlij FLAG_NO_CREATE do PendingIntent.getService(), aby uzyskać instancję inencji (jeśli istnieje), a następnie prześlij tę intencję do 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);
}

Wybieranie typu alarmu

Jedną z pierwszych kwestii, które należy wziąć pod uwagę, jest typ powtarzającego się alarmu. co powinno być takie samo.

Istnieją 2 ogólne typy zegarów dla alarmów: „Czas rzeczywisty” oraz "zegar w czasie rzeczywistym" (RTC). Czas upływający w czasie rzeczywistym używa jako odniesienia „czasu od uruchomienia systemu”, a zegar czasu rzeczywistego używa czasu UTC (zegar ścienny). Oznacza to, że upływający czas rzeczywisty jest odpowiedni do ustawiania alarmu na podstawie upływu czasu (na przykład alarmu, który działa co 30 sekund), ponieważ nie jest on zależny od strefy czasowej ani lokalizacji. Typ zegara w czasie rzeczywistym jest bardziej odpowiedni w przypadku alarmów zależnych od bieżących ustawień regionalnych.

Oba typy mają wersję „budzenia”, która powoduje wybudzenie procesora urządzenia, jeśli ekran jest wyłączony. Dzięki temu alarm zostanie uruchomiony o zaplanowanej godzinie. Jest to przydatne, gdy aplikacja ma zależność czasową. Na przykład, jeśli ma ograniczony czas na wykonanie określonej operacji. Jeśli nie używasz tagu wybudzenia typu, to potem zostaną uruchomione wszystkie powtarzające się alarmy. gdy urządzenie zostanie wybudzone.

Jeśli po prostu chcesz, aby alarm był uruchamiany w określonym odstępie czasu (np. co pół godziny), użyj jednego z typów czasu upływającego w czasie rzeczywistym. Zazwyczaj jest to lepszy wybór.

Jeśli chcesz, aby alarm uruchomił się o określonej porze dnia, wybierz jeden z podanych terminów. zegarów w czasie rzeczywistym. Pamiętaj jednak, że takie podejście może mieć pewne wady. Aplikacja może nie działać prawidłowo w innych lokalizacjach, a jeśli użytkownik zmieni ustawienia czasu na urządzeniu, może to spowodować nieoczekiwane działanie aplikacji. Jak już wspomnieliśmy, użycie typu alarmu zegarka w czasie rzeczywistym nie jest też zbyt elastyczne. Zalecamy korzystanie z raportów „Upłynęło w czasie rzeczywistym”, alarm jeśli to możliwe.

Oto lista typów:

  • ELAPSED_REALTIME: uruchamia oczekujący zamiar na podstawie czasu, jaki upłynął od uruchomienia urządzenia, ale nie wybudza urządzenia. Upływający czas obejmuje czas, w którym urządzenie było w stanie uśpienia.

  • ELAPSED_REALTIME_WAKEUP: budzi urządzenie i uruchamia oczekujący zamiar po upływie określonego czasu od momentu uruchomienia urządzenia.

  • RTC: uruchamia oczekujący zamiar we wskazanym czasie, ale nie wybudza urządzenia.

  • RTC_WAKEUP: wybudza urządzenie, aby w określonym czasie uruchomić oczekujący zamiar.

Przykłady alarmów w czasie rzeczywistym

Oto kilka przykładów użycia funkcji ELAPSED_REALTIME_WAKEUP

Wybudź urządzenie po 30 minutach i co 30 minut potem:

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

Aby uruchomić alarm jednorazowy (niepowtarzalny) w ciągu minuty, obudź urządzenie:

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

Przykłady alarmów zegara w czasie rzeczywistym

Oto kilka przykładów użycia funkcji RTC_WAKEUP

Obudź urządzenie, aby uruchomić alarm około 14:00. powtarzaj raz dziennie o tej samej porze:

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

Wybudź urządzenie, aby alarm uruchomił się dokładnie o 8:30 i co 20 minut potem:

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

Zdecyduj, jak dokładny ma być alarm

Jak już wspomnieliśmy, wybór typu alarmu jest często pierwszym krokiem tworzenia alarmu. Kolejną różnicą jest to, jak dokładny jest alarm. . W przypadku większości aplikacji setInexactRepeating() jest właściwym wyborem. Gdy używasz tej metody, Android synchronizuje wiele nieprecyzyjnych alarmów powtarzających i uruchamia je w tym samym czasie. Pozwala to zmniejszyć zużycie baterii.

W miarę możliwości unikaj alarmów precyzyjnych. W rzadkich aplikacjach, które działają sztywno czas, możesz ustawić dokładny alarm, dzwoniąc pod numer setRepeating().

Dzięki setInexactRepeating() nie możesz określić niestandardowego interwału w taki sam sposób, jak setRepeating() Musisz użyć jednej z interwałowych stałych, np. INTERVAL_FIFTEEN_MINUTES, INTERVAL_DAY itd. Zobacz AlarmManager znajdziesz pełną listę.

Anuluj alarm

W zależności od aplikacji możesz dodać możliwość anulowania alarmu. Aby anulować alarm, wywołaj funkcję cancel() w Menedżerze alarmów, przekazując parametr PendingIntent, którego już nie chcesz uruchamiać. Na przykład:

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

Uruchom alarm po ponownym uruchomieniu urządzenia

Domyślnie wszystkie alarmy są anulowane po wyłączeniu urządzenia. Aby temu zapobiec, możesz zaprojektować aplikację aby automatycznie powtarzać alarm, gdy użytkownik uruchomi urządzenie ponownie. Dzięki temu AlarmManager będzie nadal wykonywać swoje zadanie bez konieczności ręcznego uruchamiania alarmu przez użytkownika.

Aby to zrobić:

  1. Ustawianie RECEIVE_BOOT_COMPLETED w pliku manifestu aplikacji. Dzięki temu aplikacja będzie mogła otrzymywać ACTION_BOOT_COMPLETED który jest wysyłany po zakończeniu rozruchu systemu (działa to tylko wtedy, gdy została już co najmniej raz uruchomiona przez użytkownika):

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
  2. Aby odbierać transmisję, zainstaluj: BroadcastReceiver

    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. Dodaj odbiornik do pliku manifestu aplikacji za pomocą filtra intencji, który filtruje według działania ACTION_BOOT_COMPLETED:

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

    Zwróć uwagę, że w pliku manifestu odbiorca uruchamiania ma wartość android:enabled="false". Oznacza to, że odbiorca nie zostanie wywołany, chyba że aplikacja wyraźnie to umożliwi. Zapobiega to niepotrzebnemu wywoływaniu odbiornika uruchamiania. Możesz włączyć odbiornik (na przykład po ustawieniu przez użytkownika alarmu):

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

    Po włączeniu tego sposobu odbiornik pozostanie włączony, nawet jeśli użytkownik uruchamia ponownie urządzenie. Inaczej mówiąc, programowe włączenie odbiornika zastąpi ustawienie w pliku manifestu nawet po ponownym uruchomieniu. Odbiornik pozostanie włączony, dopóki aplikacja go nie wyłączy. Aby wyłączyć odbiornik (np. jeśli użytkownik anuluje alarm), wykonaj te czynności:

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

Wywołuj alarmy, gdy urządzenie jest w trybie uśpienia

Urządzenia z Androidem 6.0 (poziom interfejsu API 23) obsługują tryb Doze, który wydłuża czas pracy baterii. Alarmy nie są sygnalizowane, gdy urządzenie jest w Tryb uśpienia Wszystkie zaplanowane alarmy zostaną odłożone do momentu zamknięcia urządzenia. Jeśli chcesz wykonać zadanie, gdy urządzenie jest nieaktywne, masz do wyboru kilka opcji:

Sprawdzone metody

Każdy wybór dokonany przy projektowaniu powtarzającego się alarmu może mieć konsekwencje sposobu wykorzystywania (lub nadużywania) zasobów systemowych przez aplikację. Wyobraź sobie na przykład, że chcesz utworzyć jest to popularna aplikacja, która synchronizuje się z serwerem. Jeśli operacja synchronizacji jest oparta na czasie i każdy egzemplarz aplikacji synchronizuje się o 23:00, obciążenie serwera może spowodować duże opóźnienie lub nawet odmowę usługi. Stosuj te sprawdzone metody dotyczące alarmów:

  • Dodaj losowość (zakłócenia) do wszystkich żądań sieciowych, które uruchomienie w wyniku powtarzającego się alarmu:

    • wykonywać jakiekolwiek działania lokalne po uruchomieniu alarmu. „Praca lokalna” to wszystko, co nie wymaga korzystania z serwera ani przesyłania danych na serwer.

    • W tym samym czasie zaplanuj alarm, który zawiera żądania sieci, aby były wykonywane w losowym przedziale czasu.

  • Ogranicz częstotliwość alarmów do minimum.

  • Nie wybudzaj urządzenia niepotrzebnie (to działanie jest zależne od zgodnie z opisem w sekcji Wybieranie typu alarmu).

  • Nie ustawiaj dokładnej godziny włączenia alarmu.

    Użyj setInexactRepeating() zamiast setRepeating() Gdy używasz setInexactRepeating(), Android synchronizuje alarmy powtarzające się z kilku aplikacji i uruchamia je jednocześnie. Dzięki temu system musi uruchamiać urządzenie mniej razy, co zmniejsza zużycie baterii. Od Android 4.4 (poziom API 19), wszystkie powtarzające się alarmy są alarmami nieprecyzyjnymi. Pamiętaj, że chociaż setInexactRepeating() jest lepszym rozwiązaniem niż setRepeating(), to nadal może przeciążyć serwer, jeśli każda instancja aplikacji łączy się z serwerem w przybliżeniu w tym samym czasie. Dlatego w przypadku żądań sieciowych zwiększ losowość jak już wcześniej omówiliśmy alarmy.

  • W miarę możliwości unikaj używania budzika na podstawie godziny.

    Powtarzające się alarmy oparte na dokładnym czasie aktywacji nie są dobrze skalowane. Użyj ELAPSED_REALTIME, jeśli jak to możliwe. Inny alarm omówiono bardziej szczegółowo w następnej sekcji.