Android
AlarmManager
Szukaj…
Uruchom zamiar w późniejszym czasie
- Utwórz odbiornik. Ta klasa otrzyma zamiar i zajmie się nim tak, jak chcesz.
public class AlarmReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
// Handle intent
int reqCode = intent.getExtras().getInt("requestCode");
...
}
}
- Podaj zamiar AlarmManager. Ten przykład wyzwoli zamiar wysłania do AlarmReceiver po 1 minucie.
final int requestCode = 1337;
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
am.set( AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 60000 , pendingIntent );
Jak anulować alarm
Jeśli chcesz anulować alarm i nie masz odniesienia do oryginalnego PendingIntent użytego do ustawienia alarmu, musisz odtworzyć PendingIntent dokładnie tak, jak to było w momencie jego utworzenia.
Zamiarem jest uważany przez AlarmManager za równy :
jeśli ich działanie, dane, typ, klasa i kategorie są takie same. To nie porównuje żadnych dodatkowych danych zawartych w zamiarach.
Zwykle kod żądania dla każdego alarmu jest definiowany jako stała:
public static final int requestCode = 9999;
Tak więc, dla prostej konfiguracji alarmu takiej jak ta:
Intent intent = new Intent(this, AlarmReceiver.class);
intent.setAction("SomeAction");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, targetTimeInMillis, pendingIntent);
Oto, jak utworzyć nowe odwołanie PendingIntent, którego można użyć do anulowania alarmu za pomocą nowego odwołania AlarmManager:
Intent intent = new Intent(this, AlarmReceiver.class);
intent.setAction("SomeAction");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, requestCode, intent, PendingIntent.FLAG_NO_CREATE);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
if(pendingIntent != null) {
alarmManager.cancel(pendingIntent);
}
Tworzenie dokładnych alarmów we wszystkich wersjach Androida
Wraz z upływem czasu coraz więcej optymalizacji baterii w systemie Android, metody AlarmManager
również uległy znacznej zmianie (aby umożliwić bardziej łagodny czas). Jednak w przypadku niektórych aplikacji nadal musi być możliwie jak najdokładniejszy we wszystkich wersjach Androida. Następujący pomocnik używa najdokładniejszej metody dostępnej na wszystkich platformach do planowania PendingIntent
:
public static void setExactAndAllowWhileIdle(AlarmManager alarmManager, int type, long triggerAtMillis, PendingIntent operation) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M){
alarmManager.setExactAndAllowWhileIdle(type, triggerAtMillis, operation);
} else if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
alarmManager.setExact(type, triggerAtMillis, operation);
} else {
alarmManager.set(type, triggerAtMillis, operation);
}
}
Tryb API23 + Tryb drzemki zakłóca działanie AlarmManager
Android 6 (API23) wprowadził tryb Doze, który zakłóca działanie AlarmManager. Do obsługi alarmów używa pewnych okien serwisowych, więc nawet jeśli użyłeś setExactAndAllowWhileIdle()
, nie możesz upewnić się, że twój alarm uruchomi się w żądanym momencie.
Możesz wyłączyć to zachowanie dla swojej aplikacji za pomocą ustawień telefonu ( Settings/General/Battery & power saving/Battery usage/Ignore optimizations
lub podobne)
W aplikacji możesz sprawdzić to ustawienie ...
String packageName = getPackageName();
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (pm.isIgnoringBatteryOptimizations(packageName)) {
// your app is ignoring Doze battery optimization
}
... i ostatecznie pokaż odpowiednie okno dialogowe ustawień:
Intent intent = new Intent();
String packageName = getPackageName();
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent);