【问题标题】:Stop alarmManager from other activity从其他活动中停止 alarmManager
【发布时间】:2015-08-01 20:38:17
【问题描述】:

我正在尝试通过 Map 活动中的 onBackPressed() 方法停止 MainActivity 中的 alarmManager。我已经尝试了下面的代码,但是 alarmManager 没有被停止并且仍在触发。我该如何解决?

MainActivity 中的代码:

Intent intent = new Intent(MainActivity.this, GetLLRD.class);
intent.putExtra("json_data", json);
PendingIntent pendingIntent = PendingIntent.getService(
        getApplicationContext(), 123, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar cal = Calendar.getInstance();
alarm.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), 20 * 1000, pendingIntent);
startService(intent);

地图活动中的代码:

@Override
public void onBackPressed() {       
    Intent intent = new Intent(Map.this, MainActivity.class);
    PendingIntent pendingIntent = PendingIntent.getService(
            getApplicationContext(), 123, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    alarm.cancel(pendingIntent);
}

【问题讨论】:

  • 您尝试取消的 PendingIntent 与您最初设置的闹钟不同。
  • @ci_:我怎样才能使它们相同?我的错误在哪里?
  • 嗯,Intents 是针对初学者的不同类的。您正在 GetLLRD.class 上设置警报,然后尝试在 MainActivity.class 上取消它。
  • 我用这个意图尝试过 `Intent intent = new Intent(Map.this,GetLLRD.class);` 现在它可以工作了。谢谢。

标签: android


【解决方案1】:

你的问题是你使用两个不同的类来创建和停止警报:

Intent intent = new Intent(context,
                    GetLLRD.class);

Intent intent = new Intent(context,
                    MainActivity.class);

/** as in source code  - new intent constructor */
public Intent(Context packageContext, Class<?> cls) {
    mComponent = new ComponentName(packageContext, cls);
}

如果你想检查你是否有与之前相同的待处理意图,你可以尝试使用:

 Intent.filterEquals(oherIntent);

要取消警报,您有两个选项使用标志或使用相同的警报意图:

PendingIntent.FLAG_CANCEL_CURRENT

& 我建议将未决意图作为最终意图 - 示例:

 /**
 * create pending intent
 */
final PendingIntent pIntent(Intent alarmIntent) {
    // Create a PendingIntent to be triggered when the alarm goes off
    return PendingIntent.getBroadcast(getApplicationContext(), AlarmReceiver.REQUEST_CODE,
            alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}


 /**
 * cancel alarm
 */
public void cancelAlarm(Intent alarmIntent, Context context) {
    try {

        AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        /** use flag cancel here */
        PendingIntent pIntent = PendingIntent.getService(context, AlarmReceiver.REQUEST_CODE, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
        /** cancel alarm */
        alarm.cancel(pIntent);

    } catch (Exception e) {
        // handle exception here 
    }
}

为什么要使待定意图成为最终的?

因为你需要取消闹钟:

  • 使用相同的 id 和适当的 Intent FLAG 创建待处理 Intent。

    (获取对当前待处理意图的引用)

PendingIntent.getBroadcast(context, REQUEST_CODE, intent, 
                       PendingIntent.FLAG_UPDATE_CURRENT);
  • 取消该未决意图。
PendingIntent.cancel();
  • 使用警报管理器取消警报。
AlarmManager.cancel(PendingIntent);

PendingIntent 本身只是对系统维护的令牌的引用,该令牌描述用于检索它的原始数据。这意味着,即使它拥有的应用程序的进程被杀死,PendingIntent 本身仍可用于其他已被赋予它的进程。如果创建应用程序稍后重新检索相同类型的 PendingIntent(相同的操作、相同的 Intent 操作、数据、类别和组件以及相同的标志),它将接收表示相同令牌的 PendingIntent,如果它仍然有效,并且可以因此调用 cancel() 将其删除。

【讨论】:

  • 我不明白你的观点我怎样才能使它最终?我要把这条线放在哪里PendingIntent.FLAG_CANCEL_CURRENT?
  • 您为什么在pIntent 中使用getBroadcast,在cancelAlarm 中使用getSystemService?我没有使用 Broadcastreceiver。
  • @MrPencil 我告诉你如何创建挂起的意图 - 作为最终在取消时重用它 - 你的挂起意图可以是活动/或广播等
  • PendingIntent 不必是完全相同的对象,这是不正确的。
  • @ci_ - 我给了两个选择
【解决方案2】:

如果你正在使用活动,请使用

PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),
                            12345, intent,0);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-25
    • 1970-01-01
    相关资源
    最近更新 更多