AlarmManager仅在重启设备时触发

时间:2015-03-19 18:43:33

标签: android alarmmanager

我有一个发送每周通知的应用。它应该在周四早上8:15开火;但是,我在重新启动手机后(本周上午8:15之后)本周才收到更新。警报在第一次运行时在MainActivity中设置,我实现了BootReceiver,以便在用户关闭手机时重置警报。有没有人知道我是否在某个错过的地方遇到了逻辑错误?

编辑:现在每次重启都会触发。我该如何解决这个问题?通知功能的方式使得每次重启时发送通知成为一个大问题(它会增加用于兑换奖励的点值)。

以下是MainActivity的代码部分:

public void manageNotifications() {
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.set(java.util.Calendar.DAY_OF_WEEK, java.util.Calendar.THURSDAY);
    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 Thursday
     */
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60 * 60 * 24 * 7, pendingIntent);
}//end manageNotifications

这是我的BootReceiver类:

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.THURSDAY);
        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 Thursday
     */
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60 * 60 * 24 * 7, pendingIntent);
    }
}

}

这是第一次运行时从BootReceiver和MainActivity调用的AlarmReceiver代码:

public class AlarmReceiver extends 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
    }
}

1 个答案:

答案 0 :(得分:0)

跟随我的reddit评论:看起来好像你正在设置闹钟过去。 Calendar apis有点奇怪。

    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.set(java.util.Calendar.DAY_OF_WEEK, java.util.Calendar.THURSDAY);
    calendar.set(java.util.Calendar.HOUR_OF_DAY, 8);
    calendar.set(java.util.Calendar.MINUTE, 15);

此代码会将日历设置为星期四上午8:15 当前周。因此,如果用户在星期五早上重新启动手机,则此时间将指向上一个星期四早上。这会导致AlarmManager根据setRepeating()的文档立即触发警报:https://developer.android.com/reference/android/app/AlarmManager.html

  

如果规定的触发时间是过去的,则会立即触发警报,警报计数取决于触发时间相对于重复间隔的过去程度。

编辑 - 跟进您对如何修复的评论:

快速而肮脏的方式就是这样的

long alarmTime = calendar.getTimeInMillis();
if (alarmTime < System.currentTimeMillis()) {
    alarmTime += DateUtils.WEEK_IN_MILLIS;
}

alarmManager.set( ... alarmTime ... );

我在讨论有关Java Calendar api的问题时常常讨厌听到这个问题,但是使用Joda-Time库(或者在你的情况下Joda-Time Android)将为您节省很多痛苦。 api更清晰,更容易使用。