当我的应用程序启动时,我想让它检查一个特定的警报(通过AlarmManager注册)是否已经设置并运行。谷歌的结果似乎表明没有办法做到这一点。这仍然正确吗?我需要做这个检查,以便在采取任何行动创建一个新的警报之前建议用户。
当前回答
如果你的目标是Android 12(即目标SDK 31),那么,对于AlarmManager, PendingIntent不能在没有Mutable或Immutable标志的情况下创建。如果没有这个可变性标志,应用程序将抛出一个运行时错误。有关这方面的更多详细信息,请参阅本文档。下面的代码片段对我来说是有用的,它将帮助那些将应用程序定位于Android 12的人。
创建告警:
public static void setupReminderServiceAlarm ( Context context ) {
Log.d ( TAG, "Trying to setup reminder service alarm" );
if (!isReminderServiceAlarmSet ( context )) {
AlarmManager alarmManager = (AlarmManager) context.getApplicationContext ().getSystemService ( Context.ALARM_SERVICE );
Intent intent = new Intent ( context.getApplicationContext (), ReminderIntentReceiver.class );
intent.setAction ( REMINDER_INTENT_ACTION );
PendingIntent pendingIntent;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
pendingIntent = PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE );
} else {
pendingIntent = PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, 0 );
}
alarmManager.setRepeating ( AlarmManager.RTC_WAKEUP, getReminderTriggerTime (), REMINDER_INTERVAL, pendingIntent );
Log.d ( TAG, "Reminder service alarm setup completed" );
}
}
查询告警是否已设置:
private static boolean isReminderServiceAlarmSet ( Context context ) {
Intent intent = new Intent ( context.getApplicationContext (), ReminderIntentReceiver.class );
intent.setAction ( REMINDER_INTENT_ACTION );
boolean isBackupServiceAlarmSet;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_NO_CREATE );
isBackupServiceAlarmSet = (PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_NO_CREATE ) != null);
} else {
PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_NO_CREATE );
isBackupServiceAlarmSet = (PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_NO_CREATE ) != null);
}
Log.d ( TAG, "Reminder service alarm is " + (isBackupServiceAlarmSet ? "" : "not ") + "set already" );
return isBackupServiceAlarmSet;
}
取消之前设置的闹钟:
public static void cancelReminderServiceAlarm ( Context context ) {
Log.d ( TAG, "Reminder service alarm canceled" );
AlarmManager alarmManager = (AlarmManager) context.getApplicationContext ().getSystemService ( Context.ALARM_SERVICE );
Intent intent = new Intent ( context.getApplicationContext (), ReminderIntentReceiver.class );
intent.setAction ( REMINDER_INTENT_ACTION );
PendingIntent pendingIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
pendingIntent = PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE );
} else {
pendingIntent = PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, 0 );
}
alarmManager.cancel ( pendingIntent );
pendingIntent.cancel ();
}
希望这个答案能帮助那些瞄准Android 12 / SDK 31+应用程序的人。此外,请确保在清单中添加此权限,以调度针对上述告警的告警。
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
其他回答
刚找到另一个解决办法,似乎对我有用
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);
}
请注意Alarm Manager的set方法的文档引用:
如果已经为此意图计划了一个警报(使用 由Intent.filterEquals定义的两个意图的相等性),然后它 将被移除,并被这个替换。
如果你知道你想要闹钟设置,那么你不需要费心检查它是否已经存在。每次你的应用启动时创建它。您将用相同的意图替换任何过去的警报。
如果您试图计算以前创建的警报还剩多少时间,或者您确实需要知道这样的警报是否存在,则需要使用不同的方法。要回答这些问题,请考虑在创建警报时保存共享pref数据。您可以存储闹钟设置时刻的时钟时间戳,您希望闹钟响起的时间,以及重复周期(如果您设置了重复闹钟)。
接收器的工作示例(上面的答案只是与动作有关)。
//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 12(即目标SDK 31),那么,对于AlarmManager, PendingIntent不能在没有Mutable或Immutable标志的情况下创建。如果没有这个可变性标志,应用程序将抛出一个运行时错误。有关这方面的更多详细信息,请参阅本文档。下面的代码片段对我来说是有用的,它将帮助那些将应用程序定位于Android 12的人。
创建告警:
public static void setupReminderServiceAlarm ( Context context ) {
Log.d ( TAG, "Trying to setup reminder service alarm" );
if (!isReminderServiceAlarmSet ( context )) {
AlarmManager alarmManager = (AlarmManager) context.getApplicationContext ().getSystemService ( Context.ALARM_SERVICE );
Intent intent = new Intent ( context.getApplicationContext (), ReminderIntentReceiver.class );
intent.setAction ( REMINDER_INTENT_ACTION );
PendingIntent pendingIntent;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
pendingIntent = PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE );
} else {
pendingIntent = PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, 0 );
}
alarmManager.setRepeating ( AlarmManager.RTC_WAKEUP, getReminderTriggerTime (), REMINDER_INTERVAL, pendingIntent );
Log.d ( TAG, "Reminder service alarm setup completed" );
}
}
查询告警是否已设置:
private static boolean isReminderServiceAlarmSet ( Context context ) {
Intent intent = new Intent ( context.getApplicationContext (), ReminderIntentReceiver.class );
intent.setAction ( REMINDER_INTENT_ACTION );
boolean isBackupServiceAlarmSet;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_NO_CREATE );
isBackupServiceAlarmSet = (PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_NO_CREATE ) != null);
} else {
PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_NO_CREATE );
isBackupServiceAlarmSet = (PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_NO_CREATE ) != null);
}
Log.d ( TAG, "Reminder service alarm is " + (isBackupServiceAlarmSet ? "" : "not ") + "set already" );
return isBackupServiceAlarmSet;
}
取消之前设置的闹钟:
public static void cancelReminderServiceAlarm ( Context context ) {
Log.d ( TAG, "Reminder service alarm canceled" );
AlarmManager alarmManager = (AlarmManager) context.getApplicationContext ().getSystemService ( Context.ALARM_SERVICE );
Intent intent = new Intent ( context.getApplicationContext (), ReminderIntentReceiver.class );
intent.setAction ( REMINDER_INTENT_ACTION );
PendingIntent pendingIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
pendingIntent = PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE );
} else {
pendingIntent = PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, 0 );
}
alarmManager.cancel ( pendingIntent );
pendingIntent.cancel ();
}
希望这个答案能帮助那些瞄准Android 12 / SDK 31+应用程序的人。此外,请确保在清单中添加此权限,以调度针对上述告警的告警。
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
我的印象是没有办法做到这一点,尽管这将是很好的。
你可以通过在某个地方记录Alarm_last_set_time来实现类似的结果,并有一个On_boot_starter BroadcastReciever:BOOT_COMPLETED之类的东西。
推荐文章
- 在Android中,对话框被取消或被取消有什么区别?
- 在ScrollView触摸处理中的HorizontalScrollView
- 何时在Android中使用RxJava,何时使用Android架构组件中的LiveData ?
- 如何在Android项目中使用ThreeTenABP
- 指定的子节点已经有一个父节点。你必须先在子对象的父对象上调用removeView() (Android)
- 我的Android设备没有出现在adb设备列表中
- 在没有安装apk的情况下获取Android .apk文件的VersionName或VersionCode
- Fragment onResume() & onPause()不会在backstack上被调用
- 如何设置基线对齐为假提高性能在线性布局?
- 如何获得当前屏幕方向?
- 如何在Android中渲染PDF文件
- 我如何解决错误“minCompileSdk(31)指定在一个依赖的AAR元数据”在本机Java或Kotlin?
- 如何改变TextInputLayout的浮动标签颜色
- Android工作室如何运行gradle同步手动?
- 如何以编程方式在我的EditText上设置焦点(并显示键盘)