#android #timer #alarmmanager #background-service
#Android #таймер #alarmmanager #фоновая служба
Вопрос:
Я хочу создать какой-нибудь внешний сервисный монитор и получать уведомления о проблемах как можно быстрее.
Я попытался настроить AlarmManager
интервал в 1-2 минуты, но, похоже, он срабатывает случайным образом каждые несколько минут.
Конечно, я хочу быть в безопасности от уничтожения моей фоновой задачи Android, которая остановит мониторинг, если я просто использую Service
.
Можно ли использовать AlarmManager
с небольшими точными интервалами?
Какие подходы используются в таких приложениях, как Facebook, Gmail, для уведомления о новых сообщениях?
Было бы лучше сделать Service
с startForeground
и частичным WakeLock
?
Ответ №1:
Я попытался настроить AlarmManager с интервалом в 1-2 минуты, но, похоже, он срабатывает случайным образом каждые несколько минут.
Поскольку вы решили не показывать, как вы «настраиваете AlarmManager с интервалом в 1-2 минуты», кому-либо будет сложно вам помочь. Пожалуйста, прочитайте документацию AlarmManager
и обратите внимание на неточное поведение по умолчанию, новое для Android 4.4.
Я хочу быть в безопасности от уничтожения моей фоновой задачи Android, которая остановит мониторинг, если я просто использую сервис.
AlarmManager
не решает всех проблем в этом отношении. Например, если пользователь выбирает принудительную остановку вашего приложения (например, через настройки), ваши сигналы тревоги удаляются.
Можно ли использовать AlarmManager с небольшими точными интервалами?
Используйте setRepeating()
на Android 1.0-4.3 и setExact()
на Android 4.4 . В setExact()
рамках обработки одного аварийного события вам нужно будет запланировать следующее аварийное событие.
Было бы лучше создать службу с startForeground и частичной блокировкой пробуждения?
Только если ваше устройство всегда подключено к источнику питания (например, монитор промышленного процесса).
Комментарии:
1. Вам не нужно беспокоиться о 4.4 и plus отдельно, если вы установили целевую версию ниже 4.4.
2. @Eu.Dr.: Правильно. Тем не менее, есть много факторов, влияющих на выбор
targetSdkVersion
. Опытные программисты учитывают, что когда-нибудь им нужно будет поднять ихtargetSdkVersion
и забыть о его влиянии на сигналы тревоги. Поэтому такие программисты будут использоватьsetExact()
его в момент разработки новогоAlarmManager
кода, когда требуются точные сигналы тревоги.targetSdkVersion
в основном для облегчения перехода к уже существующему коду, а не в качестве лицензии на игнорирование изменений при написании нового кода.3. Примет это, но я вообще не могу достичь интервала в 1 минуту, даже на adroid 3 target SDK. Это может быть связано с тем, что я использую MIUI Android, похоже, что существует некоторый внутренний предел, равный 5 минутам в качестве наименьшего интервала тревоги
4. @killer_PL: я использовал
AlarmManager
для демонстраций всего пять секунд, так что он, безусловно, способен на это. НоAlarmManager
это область, в которой производители устройств вносят изменения, пытаясь продлить срок службы батареи, поэтому меня не удивит, если ваше устройство является источником вашей проблемы. Вы можете сравнить с эмулятором x86, или другим устройством, или чем-то еще.5.
setRepeating()
на некоторых устройствах не работает надежно на Android 5 и выше, даже если вы установилиtargetSdk
значение 8 (Android 2.2). Большинство новых устройств, похоже, игнорируютtargetSdk
настройки для этого и используют свои собственные алгоритмы управления питанием. К сожалению.
Ответ №2:
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 30);
Intent intent = new Intent(MainActivity.this, YourClass.class);
PendingIntent pintent = PendingIntent.getService(MainActivity.this,
0, intent, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
60* 1000, pintent);
Комментарии:
1. В моем случае это происходит ровно каждые 5 минут.
Ответ №3:
Публикуем фрагмент кода, который мы использовали.Пожалуйста, измените в соответствии с вашими требованиями. Мы используем его каждые 15 секунд, и это работает.
public class AlarmManagerBroadcastReceiver extends BroadcastReceiver
{
private static final int _REFRESH_INTERVAL = 60 * 1; // 1 minutes
// Alarm id
private static final int ALARM_ID = 102; // This can be any random integer.
PendingIntent pi = null;
AlarmManager am= null;
@Override
public void onReceive(Context context, Intent intent)
{
/* All actions to be handled here.. */
}
// This is to initialize the alarmmanager and the pending intent. It is done in separate method because, the same alarmmanager and
// pending intent instance should be used for setting and cancelling the alarm.
public void SetContext(Context context)
{
this.context = context;
am=(AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
pi = PendingIntent.getBroadcast(context, ALARM_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
// Setting the alarm to call onRecieve every _REFRESH_INTERVAL seconds
public void SetAlarm()
{
// am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * _REFRESH_INTERVAL , pi);
try
{
am.cancel(pi);
}catch (Exception ignored){}
am.setRepeating(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime(), 1000 * _REFRESH_INTERVAL , pi);
}
// Cancel the alarm.
public void CancelAlarm()
{
am.cancel(pi);
}
}
Комментарии:
1. Это решение такое же, как у меня, и оно запускается ровно каждые 5 минут.
2. Обратите внимание на две вещи: 1) Начиная с API 19, все сигналы тревоги являются неточными; 2) Для того, чтобы это работало в течение длительных периодов времени, широковещательный приемник должен быть зарегистрирован в манифесте, а не динамически