Как проверить, установлен ли AlarmManager уже установленный будильник?


182

Когда мое приложение запускается, я хочу, чтобы он проверял, установлен ли какой-либо конкретный сигнал тревоги (зарегистрированный через AlarmManager). Результаты google, похоже, указывают на то, что нет никакого способа сделать это. Это все еще правильно? Мне нужно сделать эту проверку, чтобы сообщить пользователю, прежде чем предпринимать какие-либо действия для создания нового аварийного сигнала.

  0

Пожалуйста, подтвердите ответ, что решить проблему или разместить собственное решение. 16 янв. 172017-01-16 22:13:53

-3

Вы говорите о будильнике - какой источник вы можете скачать здесь - https://android.googlesource.com/platform/packages/apps/AlarmClock

Или вы разговариваете установки времени, когда данная задача должна быть выполнена - http://developer.android.com/reference/android/app/AlarmManager.html

  0

они переименовали его в DeskClock: http://android.git.kernel.org/?p=platform/packages/apps/DeskClock.git;a=summary 29 дек. 102010-12-29 18:41:20

  0

Я имею в виду будильник, установленный в моем коде с помощью AlarmManager. Я не могу найти какой-либо метод, чтобы проверить, установлен ли сигнал тревоги для определенного намерения. Поскольку программа позволяет пользователю установить будильник, а затем закрыть приложение, которое я хочу знать, когда приложение открыто, установлен ли будильник и работает «вне поля зрения». 29 дек. 102010-12-29 19:41:19

  0

Кажется, что класс AlarmManager не обеспечивает такую ​​функциональность. Здесь вы можете посмотреть источник AlarmManager - http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.1_r2/android/app/AlarmManager.java Если вы действительно в отчаянии, вы можете расширить его (или повторно реализовать IAlarmManager) и создать собственный диспетчер аварийных сигналов. Overkill. 29 дек. 102010-12-29 20:18:28

  0

Обновление: из другого потока я обнаружил, что следующее задание выполняет следующее: - 30 дек. 102010-12-30 13:27:22

+6

alarms = (AlarmManager) getSystemService (Context.ALARM_SERVICE); \t Строка ALARM_ACTION; ALARM_ACTION = AAAlarmReceiver.ACTION_LOAD_LISTVIEW; Intent intentToFire = новое намерение (ALARM_ACTION); boolean alarmUp = (PendingIntent.getBroadcast (cText, 0, intentToFire, PendingIntent.FLAG_NO_CREATE)! = Null); 30 дек. 102010-12-30 13:27:40

  0

Пожалуйста, ответьте только на конкретный ответ. Если вы хотите задать вопрос или что-то еще, сохраните его в комментарии. 01 дек. 172017-12-01 10:39:08

  0

@RahatZaman О чем ты говоришь? Одна из основных проблем переполнения стека: «Дайте человеку рыбу, и вы кормите его в течение дня. Научите человека ловить рыбу, и вы кормите его на всю жизнь ». Итак, указывая на источник lib, здесь довольно распространенная практика. 05 дек. 172017-12-05 10:06:25


1

Im под впечатлением, что Тереза нет способа сделать это, было бы неплохо.

Вы можете добиться аналогичного результата, записав где-то Alarm_last_set_time, и иметь вид вещания On_boot_starter BroadcastReciever: BOOT_COMPLETED.


277

Следуя за комментарием ron, вы найдете подробное решение. Допустим, вы зарегистрировали повторяющееся тревогу в ожидании намерения, как это:

Intent intent = new Intent("com.my.package.MY_UNIQUE_ACTION"); 
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, 
             intent, PendingIntent.FLAG_UPDATE_CURRENT); 
Calendar calendar = Calendar.getInstance(); 
calendar.setTimeInMillis(System.currentTimeMillis()); 
calendar.add(Calendar.MINUTE, 1); 

AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60, pendingIntent); 

, как вы бы проверить, если он активен должен:

boolean alarmUp = (PendingIntent.getBroadcast(context, 0, 
     new Intent("com.my.package.MY_UNIQUE_ACTION"), 
     PendingIntent.FLAG_NO_CREATE) != null); 

if (alarmUp) 
{ 
    Log.d("myTag", "Alarm is already active"); 
} 

Ключевым моментом здесь является FLAG_NO_CREATE, который как описано в javadoc: if the described PendingIntent **does not** already exists, then simply return null (вместо создания нового)

+8

Нужно ли использовать намерение только с помощью строки действий? Я попытался указать класс, новый Intent (контекст, MyClass.class), но он не работает. Он всегда возвращает значение null, даже когда будильник работает. 04 апр. 122012-04-04 08:39:49

+5

toc777, он не должен быть строкой, которая соответствует объявленному действию в вашем намеренном фильтре в манифесте.xml 11 апр. 122012-04-11 08:27:24

+4

Chris, Это была еще одна проблема, которая вызывала мою проблему. Намерение, о котором я упомянул выше, действительно работает :) 12 апр. 122012-04-12 12:25:50

  0

Проблема, с которой я столкнулся, не вызывала отмену на BATH alarmManager и pendingIntent. I.E ~ alarmMgr.cancel (alarmIntent); alarmIntent.cancel(); 29 май. 142014-05-29 12:01:21

  0

@ChrisKnight: Будет ли это работать, если я проверю приложение, скажем app1, если будильник установлен и запущен в приложении2? а также, как аварийные сигналы умирают во время обновления приложения, и поэтому нам нужно снова его перезагрузить (для случая с обновлением приложения)? 08 июл. 142014-07-08 03:25:46

+1

Всегда возвращает TRUE, что ожидающие намерения уже существуют. Даже после удаления и переустановки приложения. Сколько времени ожидает ожидание? 13 авг. 142014-08-13 20:33:24

+30

Обратите внимание, что вам нужно будет вызвать '' 'alarmManager.cancel (pendingIntent)' '' и '' 'pendingIntent.cancel()' '', чтобы это решение вернуло false. 29 сен. 142014-09-29 20:00:44

+1

для пользователей, использующих новый Intent (context, YourService.class), вы можете использовать .setAction («ACTIONNAME»), чтобы определить действие по намерению 28 ноя. 142014-11-28 20:11:13

+1

Lifesaver. Обратите внимание, что вам нужно будет создать намерение точно так же, как вы его создали раньше, за исключением флагов. 26 фев. 152015-02-26 10:07:31

+22

В этом случае это не очевидно, код в этом ответе не проверяет, что ожидающее намерение было зарегистрировано диспетчером аварийных сообщений. Код просто проверяет, что PendingIntent был создан через getBroadcast с эквивалентным целевым намерением. Вы можете это доказать, запустив код alarmUp после получения getBroadcast, но перед всеми функциями календаря и диспетчера аварийных сообщений. Это вернет true. Этот факт объясняет, почему вы должны PendingIntent.cancel, чтобы вернуть значение к false. Строго говоря, это не отвечает на вопрос. 21 апр. 152015-04-21 21:09:49

+1

Извините. Я хочу спросить, что такое MY_UNIQUE_ACTION? Откуда он? 23 июл. 152015-07-23 01:14:26

+1

@ LeonardFebrianto Я думаю, что это был ответ, давно назревший, но я уверен, что у вас есть причина. Это просто имя действия, это может быть любая постоянная действий, связанная с приемниками в вашем манифесте. 15 дек. 152015-12-15 05:49:51

  0

не работает, если тревога убита «принудительной остановкой» и т. Д. Она должна быть отменена перед использованием этого кода. 17 дек. 152015-12-17 13:55:17

+1

Я пробовал Intent intent = new Intent (ctx, MyReceiver.class); вместо того, чтобы передавать unique_action, и это сработало :) 22 дек. 152015-12-22 11:24:16

  0

ohh его работая спасибо! 23 дек. 152015-12-23 03:46:33

+1

подсказка для будущих читателей - убедитесь, что вы не ошибаетесь. PendingIntent.getBroadcast (...) с PendingIntent.getService (...) - сэкономить некоторые неприятности! :) 18 апр. 162016-04-18 04:33:00

+2

это первый раз, когда я вижу столь высокий рейтинг WRONG. См. Комментарий от bigh_29. 03 янв. 172017-01-03 20:29:37


7

У меня есть 2 будильника. Я использую намерение с массовкой вместо действия, чтобы идентифицировать событие:

Intent i = new Intent(context, AppReciever.class); 
i.putExtra("timer", "timer1"); 

вещи в том, что с дифф статистами намерение (и тревога) обыкновение быть уникальными. Таким образом, чтобы иметь возможность определить, какой сигнал активен или нет, я должен был определить Diff requestCode -s:

boolean alarmUp = (PendingIntent.getBroadcast(context, MyApp.TIMER_1, i, 
        PendingIntent.FLAG_NO_CREATE) != null); 

и вот как была создана сигнализация:

public static final int TIMER_1 = 1; 
public static final int TIMER_2 = 2; 

PendingIntent pending = PendingIntent.getBroadcast(context, TIMER_1, i, 
      PendingIntent.FLAG_CANCEL_CURRENT); 
setInexactRepeating(AlarmManager.RTC_WAKEUP, 
      cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pending); 
pending = PendingIntent.getBroadcast(context, TIMER_2, i, 
      PendingIntent.FLAG_CANCEL_CURRENT); 
setInexactRepeating(AlarmManager.RTC_WAKEUP, 
      cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pending); 
  0

С помощью утилит намерения и это решение сработало для меня. Только одно изменение заключается в том, что я использую сервис, поэтому я изменил его на «PendingIntent.getService» 27 авг. 162016-08-27 10:07:25


92

Для других, которые могут нуждаться в этом, вот ответ.

Использование adb shell dumpsys alarm

Вы можете знать, тревога была установлена, и когда они собираются встревожена и интервал. Также сколько раз этот сигнал был вызван.

+4

. Это должен быть правильный ответ. 04 окт. 142014-10-04 22:07:13

+1

Это точно 09 дек. 142014-12-09 12:43:14

+24

Не совсем программный ответ на ОП, а крутой отзыв. Очень хорошо знать. 06 май. 152015-05-06 17:38:12

+1

добавьте grep для фильтрации обычно длинного списка аварийных сигналов: 'adb shell dumpsys alarm | grep <например. имя пакета вашего приложения> 'Также работает в новых системах Windows (я использую Win10) 08 авг. 162016-08-08 10:51:30

+2

grep выполняется на мобильном устройстве, а не на вашем ПК. Поэтому, если grep работает, зависит от ОС Android. Старые телефоны не поставляются с grep. 07 мар. 172017-03-07 13:15:26


36

Рабочий пример с приемником (верхний ответ был только с действиями).

//starting 
AlarmManager alarmManager = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE); 
Intent intent = new Intent(getActivity(), MyReceiver.class); 
intent.setAction(MyReceiver.ACTION_ALARM_RECEIVER);//my custom string action name 
PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(), 1001, intent, PendingIntent.FLAG_CANCEL_CURRENT);//used unique ID as 1001 
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), aroundInterval, pendingIntent);//first start will start asap 

//and stopping 
Intent intent = new Intent(getActivity(), MyReceiver.class);//the same as up 
intent.setAction(MyReceiver.ACTION_ALARM_RECEIVER);//the same as up 
PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(), 1001, intent, PendingIntent.FLAG_CANCEL_CURRENT);//the same as up 
alarmManager.cancel(pendingIntent);//important 
pendingIntent.cancel();//important 

//checking if alram is working with pendingIntent 
Intent intent = new Intent(getActivity(), MyReceiver.class);//the same as up 
intent.setAction(MyReceiver.ACTION_ALARM_RECEIVER);//the same as up 
boolean isWorking = (PendingIntent.getBroadcast(getActivity(), 1001, intent, PendingIntent.FLAG_NO_CREATE) != null);//just changed the flag 
Log.d(TAG, "alarm is " + (isWorking ? "" : "not") + " working..."); 

Я описал также на моем blog

+1

Я не уверен, что этого достаточно. В случае, когда PendingIntent зарегистрирован в AlarmManager, а затем остановлен с помощью обоих методов отмены, «isWorking» выше будет по-прежнему истинным. Ожидается, что PendingIntent не будет удален из AlarmManager и продолжит возвращать экземпляр. Как мы тогда точно знаем, когда аварийные сигналы были включены/выключены? 10 июн. 162016-06-10 07:36:29

  0

Это действительно сработало отлично. Следует отметить: setAction() и requestCode() должны быть одинаковыми во всех getBroadcast(), и его стоит удалить приложение с вашего устройства. Это меня поймало. Спасибо 11 июн. 162016-06-11 10:12:42

  0

Отлично работает. Благодаря! 01 сен. 162016-09-01 12:59:48

  0

Хороший пример, но я бы не использовал 1001 как частный код запроса. Просто 0, чтобы сделать пример более очевидным. 09 июл. 172017-07-09 08:12:57


29

Примечание Эта цитата из документации для менеджера сигнализации:

Если уже есть сигнал для этого Намерения запланированного (с равенство двух намерений определяется Intent.filterEquals), то он будет удален и заменен этим.

Не беспокойтесь о том, существует ли будильник, если вы пытаетесь решить, создавать ли сигнал тревоги или нет. Просто создавайте его каждый раз, когда ваше приложение загружается. Вы замените все прошлые аварийные сигналы, которые вы настроили.

Вам нужен другой подход, если вы пытаетесь рассчитать, сколько времени осталось для ранее созданного аварийного сигнала, или если вам действительно нужно знать, существует ли такая сигнализация даже. Чтобы ответить на эти вопросы, подумайте об экономии общих данных pref во время создания тревоги. Вы можете сохранить временную метку часов в тот момент, когда была установлена ​​тревога, время, в течение которого вы ожидаете, что будильник погаснет, и период повторения (если вы настроите повторяющийся сигнал).

  0

По-моему, это должен быть принятый ответ. Если у ОП не возникла особая ситуация, которая оправдывает не повторение тревоги 19 май. 162016-05-19 16:11:12

  0

В моем случае я хочу знать, установлен ли будильник, и поэтому я не хочу создавать новый или перезапускать существующий аварийный сигнал. 21 июл. 172017-07-21 14:00:12


3

Я сделал простой (глупый или не) скрипт bash, который извлекает длинные строки из оболочки adb, преобразует их в метки времени и показывает их красным цветом.

echo "Please set a search filter" 
read search 

adb shell dumpsys alarm | grep $search | (while read i; do echo $i; _DT=$(echo $i | grep -Eo 'when\s+([0-9]{10})' | tr -d '[[:alpha:][:space:]]'); if [ $_DT ]; then echo -e "\e[31m$(date -d @$_DT)\e[0m"; fi; done;) 

попробовать;)


2
Intent intent = new Intent("com.my.package.MY_UNIQUE_ACTION"); 
      PendingIntent pendingIntent = PendingIntent.getBroadcast(
        sqlitewraper.context, 0, intent, 
        PendingIntent.FLAG_NO_CREATE); 

FLAG_NO_CREATE не создают ожидающий намерения, так что это дает логическое значение ложь.

  boolean alarmUp = (PendingIntent.getBroadcast(sqlitewraper.context, 0, 
        new Intent("com.my.package.MY_UNIQUE_ACTION"), 
        PendingIntent.FLAG_NO_CREATE) != null); 

      if (alarmUp) { 
       System.out.print("k"); 

      } 

      AlarmManager alarmManager = (AlarmManager) sqlitewraper.context 
        .getSystemService(Context.ALARM_SERVICE); 
      alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 
        System.currentTimeMillis(), 1000 * 60, pendingIntent); 

После AlarmManager проверить значение Pending Намерение это дает верно, потому что AlarmManager Update Флаг ожидании Намерения.

  boolean alarmUp1 = (PendingIntent.getBroadcast(sqlitewraper.context, 0, 
        new Intent("com.my.package.MY_UNIQUE_ACTION"), 
        PendingIntent.FLAG_UPDATE_CURRENT) != null); 
      if (alarmUp1) { 
       System.out.print("k"); 

      } 

5

Просто найти другое решение, кажется, работает для меня

Intent myIntent = new Intent(MainActivity.this, MyReceiver.class); 

boolean isWorking = (PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, PendingIntent.FLAG_NO_CREATE) != null); 
if (isWorking) {Log.d("alarm", "is working");} else {Log.d("alarm", "is not working");} 

if(!isWorking) { 
    pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT); 
    alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); 
    int timeNotif = 5 * 60 * 1000;//time in ms, 7*24*60*60*1000 for 1 week 
    Log.d("Notif", "Notification every (ms): " + timeNotif); 
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), timeNotif, pendingIntent); 
    } 
  0

Иногда, на Marshmallow, после того, как вы принудительно остановите приложение, getBroadcast() вернет ненулевое значение, но будильник не установлен. 15 фев. 182018-02-15 20:14:10