在另一个 pendingIntent 中取消 AlarmManager 的 pendingIntent

26

我想取消定义了一个service的AlarmManager,在这个service中可能会启动新的AlarmManager或取消先前定义的alarm。我知道在alarmManager.cancel(PendingIntent)中,参数pendingintent必须与filterEquals(Intent other)相同,但是它仍然无法正常工作,取消失败。这是我的代码:

public class GetRoundStroe {
    private Store[] stores;
    private Context mContext;

    public GetRoundStroe(Context mContext) {
        this.mContext = mContext;
    }

    public Store[] getStores() {
        if (ComCommand.haveInternet(mContext)) {
            start_am_normal();
        } else {
            start_am_silence();
        }
        return stores;
    }

    public Store[] start_am_silence() {


        long firstTime = SystemClock.elapsedRealtime();

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

        if (AlarmHolder.mAlarmNormal != null) {
            am.cancel(AlarmHolder.mAlarmNormal);

        }

        am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                firstTime, TestSwitch.getInstance().getSilence_time(), AlarmHolder.mAlarmSilence);


        return null;


    }

    public Store[] start_am_normal() {


        long firstTime = SystemClock.elapsedRealtime();

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

        if (AlarmHolder.mAlarmSilence != null) {
            MyLog.e(GetRoundStroe.class,"AlarmHolder.mAlarmSilence"+AlarmHolder.mAlarmSilence+"");
            am.cancel(AlarmHolder.mAlarmSilence);
        }
        am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                firstTime, TestSwitch.getInstance().getNormal_time(), AlarmHolder.mAlarmNormal);

        return null;
    }

    private static final class AlarmHolder {
        static final PendingIntent mAlarmSilence = PendingIntent.getService(ApplicationContext.getInstance(),
                0,
                new Intent(ApplicationContext.getInstance(), GetRoundSilenceService.class),
                0);

        static final PendingIntent mAlarmNormal = PendingIntent.getService(ApplicationContext.getInstance(),
                0, new
                Intent(ApplicationContext.getInstance(), GetRoundNormalService.class),
                0);

    }
}

GetRoundSilenceService和GetRoundNormalService调用start_am_normal()或start_am_silence函数,有人可以帮忙吗?谢谢。

2个回答

73
   myIntent = new Intent(SetActivity.this, AlarmActivity.class);
   pendingIntent = PendingIntent.getActivity(CellManageAddShowActivity.this,
       id, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
   pendingIntent.cancel();
   alarmManager.cancel(pendingIntent);

以下代码可以帮助您移除/取消挂起的意图和闹钟:

您需要做的主要事情是:

  1. 创建具有相同ID和适当意图标志的待定意图。
  2. 取消该待定意图。
  3. 使用闹钟管理器取消闹钟。

4
完美的答案,需要调用pendingIntent.cancel()和alarmanager.cancel(pendingIntent)两个方法来“完全”取消pendingIntent。 - Soham
@MKJParekh 为什么不用这个?PendingIntent.FLAG_CANCEL_CURRENT - likejudo
1
@likejiujitsu 实际上我们正在创建PendingIntent,以便我们可以取消它,我们不是为任何其他用途而创建。所以这是我们唯一的需求。现在你建议的标志:PendingIntent.FLAG_CANCEL_CURRENT 这个标志表明,如果有任何其他具有相同id的挂起意图对象可用,则当前正在创建的PendingIntent对象将不会被创建。 在我们的情况下,将始终有一个对象可用,因此不会创建新对象,并且将先前的对象分配给此对象。所以是的,我们也可以使用那个标志,我相信它会很好地工作。 - MKJParekh
您无需取消待处理意图。当使用FLAG_CANCEL_CURRENT时,AlarmManager.cancel不起作用,闹钟仍会显示在“dumpsys alarm”的输出中。我不知道为什么。 - Shaw
1
@Shaw,FLAG_CANCEL_CURRENT文档明确指出它将取消现有的PendingIntent并用您传递给AlarmManager的新PendingIntent替换它。尽管技术上并不准确,但我认为名称很令人困惑。https://developer.android.com/reference/android/app/PendingIntent.html#FLAG_CANCEL_CURRENT - Ethan Hohensee
@MKJParekh,我有一个类似的用例,我想在Activity B中取消Activity A中的一个pendingIntent。这里是链接:https://stackoverflow.com/questions/61161676/android-cancel-alarm-and-pendingintent-in-different-activity 你有任何解决方法吗? - AJW

1

@MKJParekh的回答是正确的,但我想添加更多信息,以便我们都知道什么有效,什么无效。

假设在activityA上,您创建并设置AlarmManager在30秒内打开activityC,然后在任何其他活动(可以是任何)上,我们想要取消该AlarmManager。因此,我们将执行以下操作;

在activityA中,我们创建并设置AlarmManager;

//activityA
Intent myIntentA = new Intent(actvityA.this, activityB.class)
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent myPendingIntent = PendingIntent.getActivity(activityA.this, 0, myIntentA, PendingIntent.FLAG_ONE_SHOT);

//Calendar with the time we want to fire the Alarm
Calendar calendar = Calendar.getInstance();   // Get Current Time
calendar.add(Calendar.SECOND,30);      //Fire Alarm in 30 seconds from Now.                  

((AlarmManager)getSystemService(ALARM_SERVICE)).setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), myPendingIntent);

在另一个活动中,一段时间后我们希望取消在activityA中创建的AlarmManager,而我们无法访问该活动。让我们称这个当前的活动为activityZ;
//activityZ
Intent myIntentZ = new Intent(activityZ.this, activityB.class);
PendingIntent pendingIntentZ = PendingIntent.getActivity(activityZ.this, 0, myIntentZ, PendingIntent.FLAG_ONE_SHOT);

((AlarmManager)getSystemService(ALARM_SERVICE)).cancel(pendingIntentZ);

一些重要的要点,

我们在new Intent(context)getActivity(context)中提供的上下文是相同的,但它们不必匹配我们取消AlarmManager的活动,例如在这种情况下,activityZ有另一个上下文。

我们想要用AlarmManager打开的类在两个活动中必须是相同的,例如new Intent (context, activityB.class),requestCode必须是相同的,我在这个例子中使用了0。最后,在两个活动中,标志必须是相同的,例如PendingIntent.FLAG_ONE_SHOT

myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);被使用是因为PendingIntent.getActivity如果我们在没有现有活动的上下文中启动活动,则需要它。


建议修改:鉴于您在第一行将Intent定义为“myIntentA”,那么您的第二行“myIntent.setFlags(...);”应该改为:“myIntentA.setFlags(...);”。 - AJW
我正在尝试向BroadcastReceiver发送消息,但是对于pendingIntent,没有等效的"Intent.FLAG_ACTIVITY_NEW_TASK"。有什么想法可以在另一个Activity中取消Alarm和pendingIntent以获取getBroadcast?请参见https://stackoverflow.com/questions/61161676/android-cancel-alarm-and-pendingintent-in-different-activity。 - AJW

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