Android
AlarmManager
Поиск…
Запустите намерение позднее
- Создайте приемник. Этот класс получит намерение и обработает его, как вы пожелаете.
public class AlarmReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
// Handle intent
int reqCode = intent.getExtras().getInt("requestCode");
...
}
}
- Дайте намерение AlarmManager. Этот пример вызовет намерение отправляться в AlarmReceiver через 1 минуту.
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 );
Как отменить будильник
Если вы хотите отменить будильник, и у вас нет ссылки на исходный PendingIntent, используемый для установки будильника, вам нужно воссоздать PendingIntent точно так, как это было, когда оно было изначально создано.
Настройщик считается равным с помощью AlarmManager :
если их действие, данные, тип, класс и категории одинаковы. Это не сравнивает никаких дополнительных данных, включенных в намерения.
Обычно код запроса для каждого аварийного сигнала определяется как константа:
public static final int requestCode = 9999;
Итак, для простой тревоги, настроенной так:
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);
Вот как вы создадите новую ссылку PendingIntent, которую вы можете использовать для отмены тревоги с помощью новой ссылки 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);
}
Создание точных сигналов тревоги на всех версиях Android
С течением времени в систему Android все больше и больше оптимизируются батареи, методы AlarmManager
также значительно изменились (чтобы обеспечить более мягкое время). Однако для некоторых приложений по-прежнему необходимо быть как можно более точным на всех версиях Android. Следующий помощник использует самый точный метод, доступный на всех платформах для планирования 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);
}
}
Режим API23 + Doze вмешивается в AlarmManager
Android 6 (API23) представил режим Doze, который мешает AlarmManager. Он использует определенные окна обслуживания для обработки аварийных сигналов, поэтому, даже если вы использовали setExactAndAllowWhileIdle()
вы не можете убедиться, что ваш будильник срабатывает в нужный момент времени.
Вы можете отключить это поведение для своего приложения, используя настройки вашего телефона ( Settings/General/Battery & power saving/Battery usage/Ignore optimizations
или подобное)
Внутри приложения вы можете проверить этот параметр ...
String packageName = getPackageName();
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (pm.isIgnoringBatteryOptimizations(packageName)) {
// your app is ignoring Doze battery optimization
}
... и в итоге отобразите соответствующий диалог настроек:
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);