Как использовать Android AlarmManager с небольшими интервалами, например, в 1 минуту?

#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) Для того, чтобы это работало в течение длительных периодов времени, широковещательный приемник должен быть зарегистрирован в манифесте, а не динамически