Удалить будильник из AlarmManager с помощью отмены () - Android

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

Однако, когда я вызываю метод cancel() AlarmManager, будильник не удаляется.

Вот мой addAlarm() метод:

AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);

Intent intent = new Intent(PROX_ALERT_INTENT);
intent.putExtra("ALERT_TIME", alert.date);
intent.putExtra("ID_ALERT", alert.idAlert);
intent.putExtra("TITLE", alert.title);
intent.putExtra("GEO_LOC", alert.isGeoLoc);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext,
        alert.idAlert, intent, PendingIntent.FLAG_CANCEL_CURRENT);

Calendar calendar = Calendar.getInstance();
calendar.setTime(alert.date);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
Log.e("ADD ALERT - WithoutGeoLoc - ",alert.toString());

Вот мой метод deleteAlarm():

AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);

Intent intent = new Intent(PROX_ALERT_INTENT);
intent.putExtra("ALERT_TIME", alert.date);
intent.putExtra("ID_ALERT", alert.idAlert);
intent.putExtra("TITLE", alert.title);
intent.putExtra("GEO_LOC", alert.isGeoLoc);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext,
        alert.idAlert, intent, PendingIntent.FLAG_CANCEL_CURRENT);

alarmManager.cancel(pendingIntent);
Log.e(TAG,"REMOVE ALERT - without GeoLoc"+alert.toString());

Вот мой Logcat:

01-23 17:44:07.411: E/ADD ALERT - WithoutGeoLoc -(18789): Alert [latitude=0.0, longitude=0.0, title=bfwu, comments=null, address=null, currency=hrk, idAlert=1, date=Sat Feb 23 17:44:04 CET 2013, isGeoLoc=null]
01-23 17:44:13.032: E/REMOVE ALERT without GeoLoc - (18789): Alert [latitude=0.0, longitude=0.0, title=bfwu, comments=null, address=null, currency=hrk, idAlert=1, date=Sat Feb 23 17:44:04 CET 2013, isGeoLoc=null]

Вот список ожидающих намерений в AlarmManager

Current Alarm Manager state:
Realtime wakeup (now=2013-01-23 17:44:37):
RTC_WAKEUP #48: Alarm{2c1d0588 type 0 com.my.app}
type=0 when=+364d23h59m33s288ms repeatInterval=0 count=0
operation=PendingIntent{2c0a6cb0: PendingIntentRecord{2c1d04e8 com.my.app  broadcastIntent}}
RTC_WAKEUP #47: Alarm{2c2298a0 type 0 com.my.app}
type=0 when=+30d23h59m27s360ms repeatInterval=0 count=0
operation=PendingIntent{2c292af8: PendingIntentRecord{2c22a628 com.my.app broadcastIntent}}

Пара замечаний:

  • RTC_WAKEUP #47 это мой оригинальный будильник
  • RTC_WAKEUP #48 — это новый сигнал тревоги, который должен был перезаписать #47, а не создавать новый.

Я сравнил два намерения (не pendingIntents) из моих методов добавления и удаления, используя метод Intent filterEquals(), который возвращает true... Тем не менее, сигнал тревоги не удаляется. Что я делаю неправильно?


ОБНОВЛЕНИЕ

Вот мой метод saveAlert(), который вызывает addAlarm() и deleteAlarm()

private void saveAlert() {
    // *** If Modifying Alert => REMOVE OLD ALERT (then add new one)
    Intent intent1 = null, intent2 = null;

    if (alert.idAlert != null) {
        if (alert.isGeoLoc == null || alert.isGeoLoc == false) {
            intent2 = ProximityService.removeProximityAlertWithoutGeoLoc(getApplicationContext(), devisesApp.alertsGlobal.getAlertById(alert));
        } else {
            ProximityService.removeProximityAlert(getApplicationContext(), alert);
        }
    }
    // *** Add Alert
    if (alert.isGeoLoc == null || alert.isGeoLoc == false) {
        intent1 = ProximityService.addProximityAlertWithoutGeoLoc(getApplicationContext(), alert, devisesApp.alertsGlobal);
    } else {
        ProximityService.addProximityAlert(getApplicationContext(), alert, devisesApp.alertsGlobal);
    }

    Log.i(TAG, "[saveAlert] Alert ID : " + alert.idAlert);
    devisesApp.alertsGlobal.addById(alert);
    Log.i("INTENT EQUALS", intent1.filterEquals(intent2) + ""); // This returns true
}

person Mike Bryant    schedule 23.01.2013    source источник
comment
Просто из любопытства, как вы получили список ожидаемых намерений AlarmManager устройства?   -  person iTurki    schedule 22.08.2015
comment
adb shell dumpsys alarm › dump.txt   -  person Mike Bryant    schedule 25.08.2015
comment
это примечание к коду работает, потому что намерение получает новое значение, а при отмене необходимо использовать намерение, когда оно снова используется для параметра, ожидающего намерения, в диспетчере тревог метода установки   -  person Mir Hussain    schedule 21.05.2017


Ответы (4)


Попробуйте этот флаг:

PendingIntent.FLAG_UPDATE_CURRENT

Вместо:

PendingIntent.FLAG_CANCEL_CURRENT 

Итак, PendingIntent будет выглядеть так:

PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 
        alert.idAlert, intent, PendingIntent.FLAG_UPDATE_CURRENT)  

(Убедитесь, что вы используете один и тот же объект alert и mContext!)

Дополнительное примечание: если вам нужен один глобальный AlarmManager, поместите AlarmManager в статическую переменную (и инициализируйте его, только если он равен null).

person Govil    schedule 24.01.2013
comment
большое спасибо, я застрял на этом часами, я изменил свой флаг на PendingIntent.FLAG_UPDATE_CURRENT), и теперь он работает как шарм - person Mike Bryant; 24.01.2013
comment
У меня была аналогичная ситуация. Что-то для будущих людей, которые наткнутся на этот пост, может попробовать вызвать Cancel() для ожидающего намерения. В противном случае getBroadcast всегда будет возвращать это намерение. (событие, хотя будильник не сработает) - person Ben Bishop; 11.09.2013
comment
+1. Также должно работать с «0» в качестве флагов — нет необходимости обновлять существующее ожидающее намерение, если вы не отменяете существующее. - person orip; 04.03.2014
comment
Можете ли вы подробнее объяснить, почему его нельзя отменить при использовании FLAG_CANCEL_CURRENT? Насколько я понимаю, если контекст, pendingIntent и requestCode совпадают, тревогу можно отменить. - person Will; 20.01.2016
comment
Для получения AlarmManager требуется Context, поэтому мне интересно, действительно ли безопасно хранить его в статической переменной, т. Е. Не будет ли утечек памяти? - person ban-geoengineering; 06.12.2016
comment
@BenBishop: я сделал то же самое, используя PendingIntent.FLAG_CANCEL_CURRENT , и у меня это сработало. Но это не вызывает проблем с памятью? - person rTECH; 21.08.2017

Отмена будильника немного сбивает с толку. Вы должны передать тот же идентификатор и IntentPending. Вот пример:

private void resetIntentWithAlarm(int time){


        Intent intentAlarm = new Intent(getApplicationContext(), DownloadService.class);
        intentAlarm.putExtra(Your Key, Your stuff to pass here);

        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

        PendingIntent pendingIntent = PendingIntent.getService(
                getApplicationContext(),
                YOUR_ID,
                intentAlarm,
                PendingIntent.FLAG_UPDATE_CURRENT
        );

    if (time != 0) {

        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (60L * 1000L * time), (60L * 1000L * time), pendingIntent);
        Log.i(TAG, "Alarm setted on for " + time + " mins.");
    }
    // if TIME == Zero, cancel alaram
    else {

        alarmManager.cancel(pendingIntent);
        Log.i(TAG, "Alarm CANCELED. Time = " + time);
    }
person oskarko    schedule 16.02.2017

Отмените будильник из менеджера будильника в любое время, которое вы установили:

Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) context.getSystemService(ALARM_SERVICE);
am.cancel(pendingIntent);
person Anurag Mishra    schedule 04.04.2019

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

person Никола Јовановић    schedule 23.10.2013
comment
cancel() javadoc говорит, что Remove any alarms with a matching Intent. Any alarm, of any type, whose Intent matches this one (as defined by filterEquals(Intent)), will be canceled. requestCode не имеет никакого влияния. - person boltup_im_coding; 20.10.2016