Как проверить, если AlarmManager уже имеет установленный будильник? - PullRequest
212 голосов
/ 29 декабря 2010

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

Ответы [ 10 ]

304 голосов
/ 06 марта 2012

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

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 (вместо создания нового)

108 голосов
/ 31 июля 2014

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

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

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

48 голосов
/ 21 января 2015

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

//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 alarm 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...");

Стоит упомянуть:

Если создаваемое приложение позже (процесс) повторно-принимает тот же тип PendingIntent (та же операция , то же Intent's - действие, данные, категории, компоненты, флаги ), он получит PendingIntent, представляющий тот же токен, если он все ещедопустимый, и, следовательно, может вызвать метод cancel () для его удаления.

Короче говоря, ваш PendingIntent должен иметь те же функции (структура операции и намерения), чтобы контролировать его.

39 голосов
/ 22 апреля 2015

Примечание эта цитата из документов для установленного метода Диспетчера аварийных сигналов:

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

Если вы знаете, что хотите установить аварийный сигнал, вам не нужно беспокоиться о том, существует ли он ужеили нет.Просто создайте его каждый раз, когда загружается ваше приложение.Любые прошлые тревоги будут заменены на те же Intent.

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

10 голосов
/ 24 февраля 2013

У меня 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);
7 голосов
/ 26 июля 2016

Только что нашел другое решение, мне кажется, что оно работает

3 голосов
/ 06 мая 2018

Несмотря на то, что почти все здесь дали правильный ответ, никто не объяснил, на чем основано срабатывание сигнализации

Вы можете узнать больше о AlarmManager и его работе здесь . Но вот быстрый ответ

Вы видите, AlarmManager в основном планирует PendingIntent в будущем. Поэтому для отмены запланированного будильника необходимо отменить PendingIntent.

Всегда помните о двух вещах при создании PendingIntent

PendingIntent.getBroadcast(context,REQUEST_CODE,intent, PendingIntent.FLAG_UPDATE_CURRENT);
  • Код запроса - действует как уникальный идентификатор
  • Флаг - определяет поведение PendingIntent

Теперь, чтобы проверить, запланирован ли будильник или отменить будильник, вам просто нужно получить доступ к тому же PendingIntent. Это можно сделать, если вы используете тот же код запроса и используете FLAG_NO_CREATE, как показано ниже

PendingIntent pendingIntent=PendingIntent.getBroadcast(this,REQUEST_CODE,intent,PendingIntent.FLAG_NO_CREATE);

if (pendingIntent!=null)
   alarmManager.cancel(pendingIntent);

При FLAG_NO_CREATE он вернет null, если PendingIntent еще не существует. Если он уже существует, он возвращает ссылку на существующий PendingIntent

3 голосов
/ 22 июня 2015

Я сделал простой (глупый или нет) сценарий bash, который извлекает long из оболочки 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;)

попробуй;)

1 голос
/ 19 августа 2015
    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 не создает ожидающее намерение, поэтому оно дает логическое значение false.

            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 Intent, оно выдаст значение true, поскольку AlarmManager обновляет флаг ожидающих намерений.

            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");

            }
0 голосов
/ 31 января 2011

У меня сложилось впечатление, что нет никакого способа сделать это, но было бы неплохо.

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

...