Поведение AlarmManager.set() не соответствует документации. Я делаю что-то неправильно?

Я устанавливаю будильники, используя этот код

//in onCreate()
mAlarmManager = (AlarmManager) getApplicationContext()
            .getSystemService(ALARM_SERVICE);

//called for each timer I schedule
Intent intent = new Intent (Intents.MY_INTENT_ACTION);
PendingIntent pendIntent = PendingIntent.getBroadcast(
    getApplicationContext(), alert.getID(), 
    intent, PendingIntent.FLAG_ONE_SHOT);
long delay = 1000 * alert.getDuration();
Calendar cal = Calendar.getInstance();
mAlarmManager.set(AlarmManager.RTC_WAKEUP,
    cal.getTimeInMillis() + delay, pendIntent);

Но поведение, которое я вижу, не соответствует тому, что я должен увидеть в документации1,

public void set (тип int, long triggerAtTime, операция PendingIntent)

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

что предполагает, что вызов set(int type, long triggetAtTime, PendingIntent operation) для уже тревожного намерения должен заменить старое тревожное событие для этого намерения. Я не вижу, чтобы будильники сбрасывались. Вместо этого каждый сигнал тревоги, который я устанавливаю, срабатывает, несмотря на то, что все намерения, которые активируются ожидающими намерениями, должны совпадать (согласно filterEquals(intent)), поскольку все, что я установил для каждого намерения, является идентичным действием.

Я делаю что-то не так, или API ведет себя не так, как описано в документации?

Примечание: изменение экземпляра PendingIntent на

PendingIntent pendIntent = PendingIntent.getBroadcast(
getApplicationContext(), CONSTANT_ID,
intent, PendingIntent.FLAG_ONE_SHOT);

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


person Chris Bye    schedule 31.10.2011    source источник
comment
Попробуйте избавиться от alarm.getID() и использовать 0.   -  person CommonsWare    schedule 31.10.2011
comment
см. мой комментарий к ответу Джонга ниже.   -  person Chris Bye    schedule 31.10.2011


Ответы (3)


Возможно, это потому, что вы даете каждому сигналу тревоги свой идентификатор (дает ли alert.getID() разные идентификаторы или нет?). Согласно документации, это не должно иметь значения, но вы все равно должны попробовать.

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

person Jong    schedule 31.10.2011
comment
Это, наверное, все. Это имеет значение. Другой идентификатор означает, что это технически другое намерение. - person kabuko; 31.10.2011
comment
На самом деле это та функциональность, которую я ищу, но она не соответствует тому, что я ожидаю от документации, поэтому это заставляет меня подозревать, что мое понимание где-то ошибочно. Я добавил еще одно предложение в цитату из документации, указывающее, что понятие повторного использования идентичных IntentSenders (PendingIntents) рассматривается отдельно и, на самом деле, работает нормально. Мой вопрос заключается в том, смотрит ли AlarmManager на намерения, сгенерированные PendingIntent, или просто на уникальность PendingIntent - person Chris Bye; 31.10.2011
comment
В документации говорится, что он определяет намерения с помощью filterEquals. filterEquals не имеет ничего общего с PendingIntent, поэтому я не уверен, что это имеет значение. Но он должен проверить это. - person Jong; 31.10.2011
comment
Постарайтесь сохранить ссылку на ваш последний установленный будильник, чтобы вы могли отменить его при необходимости. - person Jong; 31.10.2011
comment
Опять же, текущее поведение, когда несколько аварийных сигналов используют разные PendingIntent для генерации одинакового Intent для широковещательной рассылки, является желаемой функциональностью для моего приложения. Однако это не соответствует поведению, описанному в документации, и это меня беспокоит. Мне любопытно, ошибаюсь ли я или документация неверна. Прямо сейчас кажется, что Android сравнивает, по крайней мере, идентификатор, связанный с PendingIntent, и отбрасывает предупреждения для PendingIntent с совпадающими идентификаторами, но не сравнивает, равны ли связанные намерения в соответствии с filterEquals (намерение) - person Chris Bye; 31.10.2011
comment
Я предполагаю, что проблема в документации. Я обнаружил, что документация AudioManager неверна, но мне удалось это исправить, сохранив статическую ссылку на мой AudioManager. Попробуйте сохранить статическую ссылку на ваш AlarmManager. Я держу статическую ссылку на AlarmManager в одном из своих приложений, и он без проблем отменяет сопоставление намерений. - person Jong; 31.10.2011
comment
Это просто странно. Я могу поэкспериментировать со статической ссылкой, но поскольку наблюдаемое неправильное поведение на самом деле является моей желаемой функциональностью (мне нужно было что-то взломать, чтобы мои намерения НЕ совпадали), я в основном оставлю это в покое. Есть мысли о том, стоит ли кому-то сообщить об этом (и к кому с этим идти), или просто отпустить? Есть несколько приемлемых обходных путей для получения желаемого поведения для любого нормального случая, который я могу придумать, поэтому я не думаю, что это большая проблема. - person Chris Bye; 31.10.2011
comment
Ну, это серьезная ошибка ИМО. В AudioManager, если вы потеряете ссылку, вы больше никогда не сможете включить звук приглушенного звукового потока. Это серьезная проблема, и если она возникает в других объектах *Manager, нужно что-то делать. - person Jong; 31.10.2011
comment
Что ж, я посмотрю, смогу ли я немного пошуметь на некоторых досках или покричать об этом в Google. Надеюсь, мы просто тупые и неправильно читаем документацию, но я не питаю к этому оптимизма. Это имеет некоторые последствия для отмены тревог (или других управляемых PendingIntent), поскольку вы не можете отменить Intent, только PendingIntent. Если бы существовали приложения, которые более активно взаимодействовали с помощью pendingIntents, то повсюду могло бы происходить какое-то очень странное поведение. - person Chris Bye; 01.11.2011

Вы пробовали с флагом PendingIntent: PendingIntent.FLAG_UPDATE_CURRENT вместо PendingIntent.FLAG_ONE_SHOT?

person Kocus    schedule 31.10.2011
comment
Я думаю, мы никогда не узнаем - person Denny; 07.03.2018

Похоже, консенсус заключается в том, что документация для AlarmManager.set(), а также других методов AlarmManager, утверждающих, что намерения (а не только обертка PendingIntents) сравниваются, чтобы проверить, установлен ли конкретный сигнал тревоги.

Не полагайтесь на сопоставление намерений AlarmManager, вместо этого полагайтесь на сопоставление PendingIntents, которое, похоже, работает так, как рекламируется.

person Chris Bye    schedule 01.11.2011