当我的应用程序启动时,我想让它检查一个特定的警报(通过AlarmManager注册)是否已经设置并运行。谷歌的结果似乎表明没有办法做到这一点。这仍然正确吗?我需要做这个检查,以便在采取任何行动创建一个新的警报之前建议用户。
当前回答
根据我的经验,在最新版本的Android中,我认为它只允许广播消息唤醒警报,而不是直接启动服务。看看这个链接:https://developer.android.com/training/scheduling/alarms,上面写着:
报警器具有以下特点:
它们允许你在设定的时间和/或间隔内发射intent。 您可以将它们与广播接收器结合使用以启动服务和执行其他操作。
第二句话的关键词是“连词”。它明确指出,警报是为Broadcast设计的(这意味着不是为直接启动服务而设计的)。我尝试了几个小时使用一个PendingIntent与getService(),但不能让它工作,即使我确认挂起的意图是正确地使用:
pendingIntent.send(0);
对于“targetSdkVersion 29”,这没有工作..[不会触发onStartCommand()]:
Intent launchIntent = new Intent(context, MyService.class);
launchIntent.putExtra(Type.KEY, SERVER_QUERY);
PendingIntent pendingIntent =
PendingIntent.getService(context, 0, launchIntent, 0);
我可以验证警报正在运行使用:
adb shell dumpsys alarm | grep com.myapp
然而,这确实奏效了:
public static class AlarmReceiverWakeup extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "onReceive Alarm wakeup");
startService(context);
}
}
public static void scheduleAlarmWakeup(Context context) {
Intent broadcastIntent = new Intent(context, AlarmReceiverWakeup.class);
broadcastIntent.putExtra(Type.KEY, SERVER_QUERY);
PendingIntent pendingIntent =
PendingIntent.getBroadcast(context, 0, broadcastIntent, 0);
AlarmManager alarmManager =
(AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// NOTE: using System.currentTimeMillis() fails w/ELAPSED_REALTIME_WAKEUP
// use SystemClock.elapsedRealtime() instead
alarmManager.setRepeating(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime()+5000,
AlarmManager.INTERVAL_FIFTEEN_MINUTES/4,
getAlarmPendingIntent(context)
);
}
顺便说一下,这是Broadcast Receiver的AndroidManifest.xml条目:
<receiver android:name=".ServerQueryService$AlarmReceiverWakeup"
android:enabled="true">
<intent-filter>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
其他回答
我的印象是没有办法做到这一点,尽管这将是很好的。
你可以通过在某个地方记录Alarm_last_set_time来实现类似的结果,并有一个On_boot_starter BroadcastReciever:BOOT_COMPLETED之类的东西。
刚找到另一个解决办法,似乎对我有用
Intent myIntent = new Intent(MainActivity.this, MyReceiver.class);
boolean isWorking = (PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, PendingIntent.FLAG_NO_CREATE) != null);
if (isWorking) {Log.d("alarm", "is working");} else {Log.d("alarm", "is not working");}
if(!isWorking) {
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
int timeNotif = 5 * 60 * 1000;//time in ms, 7*24*60*60*1000 for 1 week
Log.d("Notif", "Notification every (ms): " + timeNotif);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), timeNotif, pendingIntent);
}
对于其他可能需要这个的人,这里有一个答案。
使用adb shell dumpsys警报
你可以知道闹铃已经设置好了,什么时候闹铃和间隔时间。还有这个警报被触发的次数。
根据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应该有相同的特性(操作和意图的结构)来控制它。
推荐文章
- 横向列表视图在Android?
- 标准的Android菜单图标,例如刷新
- 改变开关的“开”色
- 以编程方式将EditText的输入类型从PASSWORD更改为NORMAL,反之亦然
- 如何在隐藏和查看密码之间切换
- 在Android上调整一个大的位图文件到缩放输出文件
- 如何更改Android版本和代码版本号?
- Android Studio突然无法解析符号
- 应用程序重新启动而不是恢复
- 如何设置整个应用程序在纵向模式?
- Android中文本的阴影效果?
- 以编程方式设置TextView的布局权重
- Android -如何覆盖“后退”按钮,所以它不完成()我的活动?
- 如何从通知点击发送参数到一个活动?
- 导航目标xxx对于这个NavController是未知的