当我的应用程序启动时,我想让它检查一个特定的警报(通过AlarmManager注册)是否已经设置并运行。谷歌的结果似乎表明没有办法做到这一点。这仍然正确吗?我需要做这个检查,以便在采取任何行动创建一个新的警报之前建议用户。
当前回答
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");
}
其他回答
根据我的经验,在最新版本的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>
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 Manager的set方法的文档引用:
如果已经为此意图计划了一个警报(使用 由Intent.filterEquals定义的两个意图的相等性),然后它 将被移除,并被这个替换。
如果你知道你想要闹钟设置,那么你不需要费心检查它是否已经存在。每次你的应用启动时创建它。您将用相同的意图替换任何过去的警报。
如果您试图计算以前创建的警报还剩多少时间,或者您确实需要知道这样的警报是否存在,则需要使用不同的方法。要回答这些问题,请考虑在创建警报时保存共享pref数据。您可以存储闹钟设置时刻的时钟时间戳,您希望闹钟响起的时间,以及重复周期(如果您设置了重复闹钟)。
刚找到另一个解决办法,似乎对我有用
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);
}
虽然这里几乎每个人都给出了正确答案,但没有人解释警报的工作依据是什么
你可以在这里了解更多关于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的引用
推荐文章
- 视图绑定-我如何获得包含布局的绑定?
- 在Android Studio中改变矢量资产的填充颜色
- 在构建中编写注释的语法是什么?gradle文件?
- 如何以编程方式添加按钮色调
- 用Android Studio进行调试永远停留在“等待调试器”状态
- Openssl不被视为内部或外部命令
- 无法执行dex:在Eclipse中超过GC开销限制
- 如何以编程方式将视图添加到视图
- 单击url会打开默认浏览器
- 使用Retrofit刷新OAuth令牌,而不修改所有调用
- 多个dex文件定义了landoid /support/v4/accessibilityservice/AccessibilityServiceInfoCompat
- 如何获得动作栏的高度?
- 从活动外部调用startActivity() ?
- createScaledBitmap的过滤器参数做什么?
- 为什么我在使用adb时访问数据文件夹被拒绝?