AlarmManager setRepeating не работает с ежедневным интервалом

#android #notifications #alarmmanager

#Android #уведомления #alarmmanager оповещатель

Вопрос:

Я столкнулся с проблемой при попытке настроить ежедневное уведомление.

Раньше я AlarmManager каждый день устанавливал будильник в 6:00 вечера

 Intent myIntent = new Intent(this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, myIntent,
    PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
if (calendar.get(Calendar.HOUR_OF_DAY) >= 18) {
    calendar.add(Calendar.DATE, 1);
}

calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.HOUR_OF_DAY, 18);
alarmManager.cancel(pendingIntent);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
    calendar.getTimeInMillis(), 24*60*60*1000,
    pendingIntent);
 

Но я не знаю, почему первый сигнал тревоги срабатывает ровно в 18:00, но следующий сигнал тревоги срабатывает в случайное время. Иногда в 19:30, иногда в 20:06. Я просто не понимаю, в чем я здесь не прав.

Я пробовал и INTERVAL_DAY то 24*60*60*1000 , и другое — ничего не получалось. Но он отлично работал с интервалом в 1 минуту, 5 минут, 10 минут, 1 час и т.д.

AlarmReceiver:

 public class AlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Intent service1 = new Intent(context, MyAlarmService.class);
        context.startService(service1);
        System.out.println("alarm");
    }
}
 

Личный кабинет Армсервис:

 public class MyAlarmService extends Service {
     private NotificationManager mManager;

     @Override
     public IBinder onBind(Intent arg0) {
       // TODO Auto-generated method stub
        return null;
     }

    @Override
    public void onCreate() {
       // TODO Auto-generated method stub  
       super.onCreate();
    }

    @SuppressWarnings("static-access")
    @Override
    public void onStart(Intent intent, int startId) {
       super.onStart(intent, startId);

       mManager = (NotificationManager) this.getApplicationContext().getSystemService(this.getApplicationContext().NOTIFICATION_SERVICE);
       Intent intent1 = new Intent(this.getApplicationContext(),MainActivity.class);

       Notification notification = new Notification(R.drawable.ic_launcher,"Test notification", System.currentTimeMillis());

       intent1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP| Intent.FLAG_ACTIVITY_CLEAR_TOP);

       PendingIntent pendingNotificationIntent = PendingIntent.getActivity( this.getApplicationContext(),0, intent1,PendingIntent.FLAG_UPDATE_CURRENT);
       notification.flags |= Notification.FLAG_AUTO_CANCEL;
       notification.setLatestEventInfo(this.getApplicationContext(), "Test", "Test a notification", pendingNotificationIntent);

       mManager.notify(0, notification);
    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
    }
}
 

Комментарии:

1. На чем вы запускаете код? Это устройство или эмулятор Android 4.4? Или это что-то еще? Кроме PendingIntent того, что вы используете?

2. Я добавил свой код pendintIntent, это просто простой приемник для отображения уведомления при срабатывании будильника

Ответ №1:

У вас две проблемы:

  1. setRepeating() является неточным на Android 4.4 с android:targetSdkVersion индексом 19 или выше.
  2. Вы не пользуетесь WakefulBroadcastReceiver ни моим WakefulIntentService , ни своим собственным WakeLock устройством, и поэтому устройство может снова перейти в спящий режим между моментом срабатывания будильника и моментом завершения работы вашей службы.

В этом случае вы можете решить # 2 проще, просто переместив код из onStart() (который, кстати, устарел уже ~ 5 лет) onReceive() и полностью избавившись от службы. Здесь вам нужна услуга, только если вы выполняете дисковый ввод-вывод или сетевой ввод-вывод; повышение a Notification должно быть дешевым.

Комментарии:

1. спасибо, я постараюсь дать отзыв в ближайшее время, я новичок в Android, и это код из образца локального уведомления

2. Насколько неточен setRepeating()? Я имею в виду, если я хочу, чтобы он вызывался примерно раз в ~ 5 минут, могу ли я быть уверен, что он будет вызван через 5-8 минут или, возможно, даже через 20 минут?

3. @AlexBerdnikov: «Насколько неточно setRepeating()?» — к сожалению, это не задокументировано. 🙁