当我的应用程序启动时,我想让它检查一个特定的警报(通过AlarmManager注册)是否已经设置并运行。谷歌的结果似乎表明没有办法做到这一点。这仍然正确吗?我需要做这个检查,以便在采取任何行动创建一个新的警报之前建议用户。


当前回答

虽然这里几乎每个人都给出了正确答案,但没有人解释警报的工作依据是什么

你可以在这里了解更多关于AlarmManager及其工作的信息。但这里有一个简单的答案

你可以看到AlarmManager基本上在未来的某个时间安排一个PendingIntent。所以为了取消预定的Alarm,你需要取消PendingIntent。

在创建PendingIntent时,总是要注意两件事

PendingIntent.getBroadcast(context,REQUEST_CODE,intent, PendingIntent.FLAG_UPDATE_CURRENT);

请求代码——作为唯一标识符 Flag -定义PendingIntent的行为

现在要检查警报是否已经被安排或取消警报,你只需要访问相同的PendingIntent。如果您使用相同的请求代码并使用如下所示的FLAG_NO_CREATE,就可以做到这一点

PendingIntent pendingIntent=PendingIntent.getBroadcast(this,REQUEST_CODE,intent,PendingIntent.FLAG_NO_CREATE);

if (pendingIntent!=null)
   alarmManager.cancel(pendingIntent);

使用FLAG_NO_CREATE,如果PendingIntent不存在,它将返回null。如果它已经存在,则返回对现有的PendingIntent的引用

其他回答

对于其他可能需要这个的人,这里有一个答案。

使用adb shell dumpsys警报

你可以知道闹铃已经设置好了,什么时候闹铃和间隔时间。还有这个警报被触发的次数。

    Intent intent = new Intent("com.my.package.MY_UNIQUE_ACTION");
            PendingIntent pendingIntent = PendingIntent.getBroadcast(
                    sqlitewraper.context, 0, intent,
                    PendingIntent.FLAG_NO_CREATE);

FLAG_NO_CREATE不是创建挂起意图,因此它给出布尔值false。

            boolean alarmUp = (PendingIntent.getBroadcast(sqlitewraper.context, 0,
                    new Intent("com.my.package.MY_UNIQUE_ACTION"),
                    PendingIntent.FLAG_NO_CREATE) != null);

            if (alarmUp) {
                System.out.print("k");

            }

            AlarmManager alarmManager = (AlarmManager) sqlitewraper.context
                    .getSystemService(Context.ALARM_SERVICE);
            alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
                    System.currentTimeMillis(), 1000 * 60, pendingIntent);

在AlarmManager检查Pending Intent的值后,它给出true,因为AlarmManager更新了Pending Intent的标志。

            boolean alarmUp1 = (PendingIntent.getBroadcast(sqlitewraper.context, 0,
                    new Intent("com.my.package.MY_UNIQUE_ACTION"),
                    PendingIntent.FLAG_UPDATE_CURRENT) != null);
            if (alarmUp1) {
                System.out.print("k");

            }

我的印象是没有办法做到这一点,尽管这将是很好的。

你可以通过在某个地方记录Alarm_last_set_time来实现类似的结果,并有一个On_boot_starter BroadcastReciever:BOOT_COMPLETED之类的东西。

根据ron发表的评论,下面是详细的解决方案。让我们假设你已经注册了一个重复的警报,它的意图是这样的:

Intent intent = new Intent("com.my.package.MY_UNIQUE_ACTION");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, 
                                      intent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.MINUTE, 1);

AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60, pendingIntent);

检查它是否处于活动状态的方法是:

boolean alarmUp = (PendingIntent.getBroadcast(context, 0, 
        new Intent("com.my.package.MY_UNIQUE_ACTION"), 
        PendingIntent.FLAG_NO_CREATE) != null);

if (alarmUp)
{
    Log.d("myTag", "Alarm is already active");
}

关键是在javadoc中描述的FLAG_NO_CREATE:如果所描述的PendingIntent **不**已经存在,那么简单地返回null(而不是创建一个新的)

接收器的工作示例(上面的答案只是与动作有关)。

//starting
AlarmManager alarmManager = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getActivity(), MyReceiver.class);
intent.setAction(MyReceiver.ACTION_ALARM_RECEIVER);//my custom string action name
PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(), 1001, intent, PendingIntent.FLAG_CANCEL_CURRENT);//used unique ID as 1001
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), aroundInterval, pendingIntent);//first start will start asap

//and stopping
Intent intent = new Intent(getActivity(), MyReceiver.class);//the same as up
intent.setAction(MyReceiver.ACTION_ALARM_RECEIVER);//the same as up
PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(), 1001, intent, PendingIntent.FLAG_CANCEL_CURRENT);//the same as up
alarmManager.cancel(pendingIntent);//important
pendingIntent.cancel();//important

//checking if alarm is working with pendingIntent
Intent intent = new Intent(getActivity(), MyReceiver.class);//the same as up
intent.setAction(MyReceiver.ACTION_ALARM_RECEIVER);//the same as up
boolean isWorking = (PendingIntent.getBroadcast(getActivity(), 1001, intent, PendingIntent.FLAG_NO_CREATE) != null);//just changed the flag
Log.d(TAG, "alarm is " + (isWorking ? "" : "not") + " working...");

值得一提的是:

如果稍后创建应用程序(进程)重新检索相同类型的 PendingIntent(相同的操作,相同的Intent的动作,数据,类别, 组件,标志),它将收到一个PendingIntent 表示相同的令牌,如果该令牌仍然有效,则可以调用 取消()来删除它。

简而言之,你的PendingIntent应该有相同的特性(操作和意图的结构)来控制它。