使用cancel()从AlarmManager中删除闹钟 - Android

42

我正在尝试创建和删除两个不同方法中的闹钟,这两个方法在应用程序逻辑的不同时刻被调用。

但是,当我调用AlarmManager的cancel()方法时,闹钟并没有被删除。

这是我的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中待处理的Intent列表:

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而不是创建一个新的。

我使用Intent的filterEquals()方法比较了添加和删除方法中的两个意图(而不是PendingIntents),它返回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
}

只是出于好奇,你是如何获取设备的AlarmManager PendingIntents列表的? - iTurki
7
adb shell dumpsys alarm > dump.txt - Mike Bryant
这段代码无法正常工作,因为意图获取了新值,在取消时必须使用意图,以便在再次用于参数挂起意图的设置方法中使用闹钟管理器。 - Mir Hussain
4个回答

49

试一试这个标记:

PendingIntent.FLAG_UPDATE_CURRENT

改为:

PendingIntent.FLAG_CANCEL_CURRENT 

因此,PendingIntent 将如下所示:

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

请确保使用相同的 alert 对象和 mContext

另外注意:如果您想要一个全局的 AlarmManager,请将其放入静态变量中(仅在它为null时初始化)。


1
非常感谢,我已经卡在这里好几个小时了。 我将我的标志更改为PendingIntent.FLAG_UPDATE_CURRENT),现在它像魔法一样工作。 - Mike Bryant
1
我曾经遇到过类似的情况。对于未来可能会遇到这篇文章的人,建议尝试在待定意图上调用Cancel()方法。否则,getBroadcast将始终返回该意图(即使它的闹钟不会触发)。 - Ben Bishop
1
+1。应该也可以使用“0”作为标志 - 只要不取消现有的待处理意图,就无需更新现有的待处理意图。 - orip
你能详细解释一下为什么使用FLAG_CANCEL_CURRENT无法取消吗?在我看来,如果上下文、pendingIntent和requestCode都相同,那么闹钟是可以被取消的。 - Will
1
获取 AlarmManager 需要一个 Context,所以我想知道将其存储在静态变量中是否绝对安全 - 也就是说,不会有任何内存泄漏? - ban-geoengineering
@BenBishop:我也是用PendingIntent.FLAG_CANCEL_CURRENT做了同样的事情,而且它对我起作用了。但是,这不会引起任何内存问题吗? - oneManArmin

3
取消闹钟有点困惑。您需要传递相同的ID和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);
    }

0

取消在任何你设定的特定时间的闹钟管理器中的闹钟:

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

-2
如果您想取消闹钟管理器,只需在待定意图中放入正确的ID,并在该待定意图中调用cancel()函数即可。

cancel() 的 javadoc 表示 删除与匹配 Intent 相关的任何警报。任何类型的警报,只要其 Intent 与此相匹配(由 filterEquals(Intent) 定义),都将被取消。 requestCode 没有任何影响。 - boltup_im_coding

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接