AlarmManager 在请求时未触发
AlarmManager not firing when requested
所以我制作了一个应用程序,它应该在每周三早上 8:15 发送通知。我正在使用 AlarmManager 从日历日期发送不准确的重复警报,以打开发送通知的未决意图。
目前的情况是,只有在您首次下载该应用程序时才会发送通知。今天早上它并没有像我或我的任何用户应该发生的那样发生。我想知道 AlarmManager 是否被安排在第一次通知触发后一周(即首次下载应用程序后一周)?
这是我在 MainActivity 中的 manageNotifications 方法:
public void manageNotifications() {
alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
alarmIntent = new Intent(this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
calendar = java.util.Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(java.util.Calendar.DAY_OF_WEEK, java.util.Calendar.WEDNESDAY);
calendar.set(java.util.Calendar.HOUR_OF_DAY, 8);
calendar.set(java.util.Calendar.MINUTE, 15);
/*
sets alarm manager to go off at 8:15 in the morning every 7 days on Wednesday
*/
alarmManager.setInexactRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), 1000 * 60 * 60 * 24 * 7, pendingIntent);
}//end manageNotifications
这是待定意图调用的我的 AlarmReceiver:
public class AlarmReceiver 扩展 BroadcastReceiver {
NotificationCompat.Builder notificationBuilder;
Intent notificationResultIntent;
ArrayList<Show> shows;
SharedPreferences spSpreadsheets, spNotifications;
final String showSpreadsheetURL = "https://docs.google.com/spreadsheets/d/1Ax2-gUY33i_pRHZIwR8AULy6-nbnAbM8Qm5-CGISevc/gviz/tq";
public void onReceive(Context context, Intent intent) {
System.out.println("AlarmReceiver created");
spNotifications = context.getSharedPreferences("notificationToggle", Context.MODE_PRIVATE);
spSpreadsheets = context.getSharedPreferences("spreadsheets", Context.MODE_PRIVATE);
if (spNotifications.getBoolean("notifications", false)) {
int nextRegularShowIndex = 0, i = 0;
shows = new ArrayList<>();
try {
if (spSpreadsheets.getString("showsSpreadsheet", "").equals(""))
getShows(context);
shows = processShowsJson(new JSONObject(spSpreadsheets.getString("showsSpreadsheet", "")));
while (shows.get(i).getShowTime() != 0) {
/*
checks for first instance of a regular showtime
*/
i++;
nextRegularShowIndex = i;
}
checkForPastShows();
notificationBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.applogo)
.setContentTitle("Comedy Club of Jacksonville")
.setContentText(shows.get(nextRegularShowIndex).getComedian() + " headlines this weekend at the Comedy " +
"Club of Jacksonville. Click to read more.")
.setDefaults(Notification.DEFAULT_ALL);
notificationResultIntent = new Intent(context, ThisWeekendFromNotification.class).putParcelableArrayListExtra("shows", shows);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(ThisWeekend.class);
stackBuilder.addNextIntent(notificationResultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder.setContentIntent(resultPendingIntent);
notificationBuilder.setAutoCancel(true);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, notificationBuilder.build());
System.out.println("Notification built");
} catch (Exception e) {
e.printStackTrace();
}//end onReceive
}
}
这是我的 BootReceiver class 用于在 phone 重新启动时重置警报:
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
java.util.Calendar calendar = java.util.Calendar.getInstance();
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent alarmIntent = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(java.util.Calendar.DAY_OF_WEEK, java.util.Calendar.WEDNESDAY);
calendar.set(java.util.Calendar.HOUR_OF_DAY, 8);
calendar.set(java.util.Calendar.MINUTE, 15);
/*
sets alarm manager to go off at 8:15 in the morning every 7 days on Wednesday
*/
alarmManager.setInexactRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), 1000 * 60 * 60 * 24 * 7, pendingIntent);
}
}
}
首先,您正在使用 setInexactRepeating()
。除非您的 minSdkVersion
为 19 或更高,否则您不能使用任意周期的 setInexactRepeating()
。
其次,setInexactRepeating()
不准确。您的闹钟不会在星期三 8:15am 响起。它会在某个时候熄灭。引用 the JavaDocs:
Your alarm's first trigger will not be before the requested time, but it might not occur for almost a full interval after that time.
第三,正如 Squonk 在评论中指出的那样,您正在使用 RTC
作为警报类型。您的闹钟将进一步延迟,直到设备因其他原因被唤醒。
如果您的 targetSdkVersion
低于 19,您可以使用 setRepeating()
进行精确重复闹钟。否则,请使用set()
(pre-API Level 19)和setExact()
(API Level 19+)安排您的闹钟,并将下一个闹钟安排为工作的一部分警报响起时完成。此外,如果您想将设备从睡眠模式唤醒以完成您的工作,请使用 RTC_WAKEUP
。
所以我制作了一个应用程序,它应该在每周三早上 8:15 发送通知。我正在使用 AlarmManager 从日历日期发送不准确的重复警报,以打开发送通知的未决意图。
目前的情况是,只有在您首次下载该应用程序时才会发送通知。今天早上它并没有像我或我的任何用户应该发生的那样发生。我想知道 AlarmManager 是否被安排在第一次通知触发后一周(即首次下载应用程序后一周)?
这是我在 MainActivity 中的 manageNotifications 方法:
public void manageNotifications() {
alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
alarmIntent = new Intent(this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
calendar = java.util.Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(java.util.Calendar.DAY_OF_WEEK, java.util.Calendar.WEDNESDAY);
calendar.set(java.util.Calendar.HOUR_OF_DAY, 8);
calendar.set(java.util.Calendar.MINUTE, 15);
/*
sets alarm manager to go off at 8:15 in the morning every 7 days on Wednesday
*/
alarmManager.setInexactRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), 1000 * 60 * 60 * 24 * 7, pendingIntent);
}//end manageNotifications
这是待定意图调用的我的 AlarmReceiver:
public class AlarmReceiver 扩展 BroadcastReceiver {
NotificationCompat.Builder notificationBuilder;
Intent notificationResultIntent;
ArrayList<Show> shows;
SharedPreferences spSpreadsheets, spNotifications;
final String showSpreadsheetURL = "https://docs.google.com/spreadsheets/d/1Ax2-gUY33i_pRHZIwR8AULy6-nbnAbM8Qm5-CGISevc/gviz/tq";
public void onReceive(Context context, Intent intent) {
System.out.println("AlarmReceiver created");
spNotifications = context.getSharedPreferences("notificationToggle", Context.MODE_PRIVATE);
spSpreadsheets = context.getSharedPreferences("spreadsheets", Context.MODE_PRIVATE);
if (spNotifications.getBoolean("notifications", false)) {
int nextRegularShowIndex = 0, i = 0;
shows = new ArrayList<>();
try {
if (spSpreadsheets.getString("showsSpreadsheet", "").equals(""))
getShows(context);
shows = processShowsJson(new JSONObject(spSpreadsheets.getString("showsSpreadsheet", "")));
while (shows.get(i).getShowTime() != 0) {
/*
checks for first instance of a regular showtime
*/
i++;
nextRegularShowIndex = i;
}
checkForPastShows();
notificationBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.applogo)
.setContentTitle("Comedy Club of Jacksonville")
.setContentText(shows.get(nextRegularShowIndex).getComedian() + " headlines this weekend at the Comedy " +
"Club of Jacksonville. Click to read more.")
.setDefaults(Notification.DEFAULT_ALL);
notificationResultIntent = new Intent(context, ThisWeekendFromNotification.class).putParcelableArrayListExtra("shows", shows);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(ThisWeekend.class);
stackBuilder.addNextIntent(notificationResultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder.setContentIntent(resultPendingIntent);
notificationBuilder.setAutoCancel(true);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, notificationBuilder.build());
System.out.println("Notification built");
} catch (Exception e) {
e.printStackTrace();
}//end onReceive
}
}
这是我的 BootReceiver class 用于在 phone 重新启动时重置警报:
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
java.util.Calendar calendar = java.util.Calendar.getInstance();
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent alarmIntent = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(java.util.Calendar.DAY_OF_WEEK, java.util.Calendar.WEDNESDAY);
calendar.set(java.util.Calendar.HOUR_OF_DAY, 8);
calendar.set(java.util.Calendar.MINUTE, 15);
/*
sets alarm manager to go off at 8:15 in the morning every 7 days on Wednesday
*/
alarmManager.setInexactRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), 1000 * 60 * 60 * 24 * 7, pendingIntent);
}
}
}
首先,您正在使用 setInexactRepeating()
。除非您的 minSdkVersion
为 19 或更高,否则您不能使用任意周期的 setInexactRepeating()
。
其次,setInexactRepeating()
不准确。您的闹钟不会在星期三 8:15am 响起。它会在某个时候熄灭。引用 the JavaDocs:
Your alarm's first trigger will not be before the requested time, but it might not occur for almost a full interval after that time.
第三,正如 Squonk 在评论中指出的那样,您正在使用 RTC
作为警报类型。您的闹钟将进一步延迟,直到设备因其他原因被唤醒。
如果您的 targetSdkVersion
低于 19,您可以使用 setRepeating()
进行精确重复闹钟。否则,请使用set()
(pre-API Level 19)和setExact()
(API Level 19+)安排您的闹钟,并将下一个闹钟安排为工作的一部分警报响起时完成。此外,如果您想将设备从睡眠模式唤醒以完成您的工作,请使用 RTC_WAKEUP
。