我正在尝试创建一个简单的警报应用程序,警报应在几天后发生。
我创建了一项服务,根据首选项中保存的数据注册警报管理器。一切都运行正常,只是当应用程序没有运行时它不会触发警报。
AlarmService.java
@Override
protected void onHandleIntent(Intent intent) {
Toast.makeText(this,"Service started",Toast.LENGTH_LONG);
//set separate pending intent values for all days
setIntents();
// register the alarm manager here
alarmManager = (AlarmManager)(getSystemService(Context.ALARM_SERVICE));
execute();
}
private void execute() {
prefs=getSharedPreferences("user_data_pref",Context.MODE_PRIVATE);
prefEditor=prefs.edit();
int hour=prefs.getInt("ALARM_HOUR",0);
int minute=prefs.getInt("ALARM_MINUTE",0);
if(prefs.getString("ALARM_STATUS","NOT_SET").equals("SET"))
isAlarmOn=true;
if(prefs.getString("NOTIFICATION_STATUS","NOT_SET").equals("SET"))
isNotificationOn=true;
if (prefs.getBoolean("MON_SET",false)) {
setAlarmFor(Calendar.MONDAY,hour,minute,mondayIntent,isAlarmOn,isNotificationOn);
}
if (prefs.getBoolean("TUE_SET",false)) {
setAlarmFor(Calendar.TUESDAY,hour,minute,tuesdayIntent,isAlarmOn,isNotificationOn);
}
if (prefs.getBoolean("WED_SET",false)) {
setAlarmFor(Calendar.WEDNESDAY,hour,minute,wednesdayIntent,isAlarmOn,isNotificationOn);
}
if (prefs.getBoolean("THU_SET",false)) {
setAlarmFor(Calendar.THURSDAY,hour,minute,thursdayIntent,isAlarmOn,isNotificationOn);
}
if (prefs.getBoolean("FRI_SET",false)) {
setAlarmFor(Calendar.FRIDAY,hour,minute,fridayIntent,isAlarmOn,isNotificationOn);
}
if (prefs.getBoolean("SAT_SET",false)) {
setAlarmFor(Calendar.SATURDAY,hour,minute,saturdayIntent,isAlarmOn,isNotificationOn);
}
if (prefs.getBoolean("SUN_SET",false)) {
setAlarmFor(Calendar.SUNDAY,hour,minute,sundayIntent,isAlarmOn,isNotificationOn);
}
}
private void setAlarmFor(int weekday, int hour, int minute, PendingIntent pendingIntent, boolean isAlarmOn, boolean isNotificationOn){
if(isAlarmOn){
prefEditor.putString("ALARM_STATUS","SET");
prefEditor.commit();
}
if(isNotificationOn){
prefEditor.putString("NOTIFICATION_STATUS","SET");
prefEditor.commit();
}
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_WEEK,weekday);
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND,0);
/* Repeating on every week interval */
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
7*24*60*60*1000, pendingIntent);
}
private void setIntents(){
Intent intent = new Intent(this,AlarmReceiver.class);
mondayIntent=PendingIntent.getBroadcast(this, Calendar.MONDAY, intent, 0);
tuesdayIntent=PendingIntent.getBroadcast(this, Calendar.TUESDAY, intent, 0);
wednesdayIntent=PendingIntent.getBroadcast(this, Calendar.WEDNESDAY, intent, 0);
thursdayIntent=PendingIntent.getBroadcast(this, Calendar.THURSDAY, intent, 0);
fridayIntent=PendingIntent.getBroadcast(this, Calendar.FRIDAY, intent, 0);
saturdayIntent=PendingIntent.getBroadcast(this, Calendar.SATURDAY, intent, 0);
sundayIntent=PendingIntent.getBroadcast(this, Calendar.SUNDAY, intent, 0);
}
它应该触发显示警报的AlarmReceiver类。
AlarmReceiver.java
@Override
public void onReceive(Context context, Intent intent) {
prefs=context.getSharedPreferences("user_data_pref",Context.MODE_PRIVATE);
//Get Status of currently set alarm and notification
alarmStatus=prefs.getString("ALARM_STATUS","NOT_SET");
notificationStatus=prefs.getString("NOTIFICATION_STATUS","NOT_SET");
//Send notification if the notification is set
if(notificationStatus.equals("SET")){
Toast.makeText(context, "NOTIFICATION START SUCCESSFUL", Toast.LENGTH_SHORT).show();
playNotificationSound(context,getNotificationSound());
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setContentTitle("") // title for notification
.setContentText("") // message for notification
.setAutoCancel(true); // clear notification after click
Intent intent_1 = new Intent(context, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(context, 11, intent_1, Intent.FLAG_ACTIVITY_NEW_TASK);
mBuilder.setContentIntent(pi);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
displayNotification(context);
}
//Fire Alarm if the Alarm is set
if(alarmStatus.equals("SET")){
Toast.makeText(context, "ALARM START SUCCESSFUL", Toast.LENGTH_SHORT).show();
/** Creating Alarm */
Intent i = new Intent(context,FitterfoxAlarmActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
的AndroidManifest.xml
<receiver android:name=".OnBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".AlarmReceiver"></receiver>
<service android:name=".AlarmService"></service>
答案 0 :(得分:0)
尝试这套代码,您的服务永远不会阻止它为我工作。 &#34; alarmManager.setRepeating&#34;许多棒棒糖和棉花糖设备一旦启动就无法工作,然后失去对服务的控制,这将有助于你。
if (android.os.Build.VERSION.SDK_INT >= 23) {
piLR = PendingIntent.getBroadcast(context, 0, intentLR,
PendingIntent.FLAG_UPDATE_CURRENT);
amLR.setAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
interval, piLR);
} else if (android.os.Build.VERSION.SDK_INT >= 19
&& android.os.Build.VERSION.SDK_INT < 23) {
piLR = PendingIntent.getBroadcast(context, 0, intentLR,
PendingIntent.FLAG_UPDATE_CURRENT);
amLR.setInexactRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), interval, piLR);
} else {
amLR.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), interval, piLR);
}
答案 1 :(得分:0)
从KitKat开始,对AlarmManager
进行了更改,以提高设备的电池寿命。警报触发的时间不太准确。如果您希望闹钟在预定时间的几分钟内触发,则需要更改使用AlarmManager
的方式。
对于KitKat(API 19)及更高版本的构建,setRepeating()
中指定的时间不准确,如documentation中所述。文档还注意到:
如果您的应用程序需要精确的交付时间,则必须使用 一次性精确报警,每次重新安排。
您指示在应用未运行时警报不会触发。由于警报的周期为一周,因此计划时间与警报触发的实际时间之间可能存在较大差异。 documentation表示:
您的闹钟的第一次触发不会在请求的时间之前,但是 在此之后几乎整整一段时间内可能不会发生。
我怀疑使用您当前的代码,您最终会看到警报响起,但可能需要在预期时间后等待很长时间。
您修改后的代码可能需要使用setWindow()。
Marshmallow介绍了Doze模式,它进一步改变了警报调度。正如@Andy在他的回答中指出的那样,为了在Marshmallow和更高版本的设备上得到你想要的优点,你需要使用setExactAndAllowWhileIdle()。
另外两件需要修复的事情。您的PendingIntents可能应该使用标记PendingIntent.FLAG_UPDATE_CURRENT。在您的收件人中,标记Intent.FLAG_ACTIVITY_NEW_TASK
属于intent_1
,而非pi
。