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:
- Pierwszy alarm włącza się w określonym oknie czasowym, licząc od podanego czasu uruchomienia.
- 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()
ipostDelayed()
. 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 iflexInterval
(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
- Przyznano automatycznie
- Nie może zostać unieważniona przez użytkownika
- Obowiązują wprowadzające wkrótce zasady Google Play
- Ograniczone przypadki użycia
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:
- 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. - 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_COMPLETED
transmisji.
Poproś użytkowników o przyznanie uprawnień SCHEDULE_EXACT_ALARM
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ć:
- W interfejsie aplikacji wyjaśnij użytkownikowi, dlaczego aplikacja musi planować dokładne alarmy.
- 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ć:
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"/>
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. } } }
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:
Ustaw dokładny alarm.
Użyj interfejsu WorkManager API, który został stworzony do wykonywania zadań w tle. Możesz wskazać, że system powinien przyspieszyć Twoją pracę, aby została ukończona jak najszybciej. Więcej informacji: Planowanie zadań za pomocą usługi WorkManager
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()
zamiastsetRepeating()
Gdy używaszsetInexactRepeating()
, 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.