【问题标题】:AlarmManager Triggers before second interval completes在第二个间隔完成之前触发 AlarmManager
【发布时间】:2015-09-04 18:17:47
【问题描述】:

我编写了一个每天早上 5:22 运行的警报代码。该代码在第一个时间间隔内运行良好,但在 24 小时前触发第二个时间间隔。

我在 MainActivity 的 onCreate() 方法中添加了警报代码,该代码在第一个间隔内运行完美,但在第一个间隔之后,如果我打开 MainActivity,警报会再次触发,并在我打开 MainActivity 时继续触发。例如,如果我打开 MainActivity 两次,警报会触发两次。

我在这里也提到了一些解决方案,但它们不像marmor's answer那样工作。

我也尝试检查是否使用 FLAG_NO_CREATE 标志设置了警报,但它仍然不起作用。

下面是我的代码。

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(this, ServiceReceiver.class);

    PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 11111, intent, 0);

    Calendar calNow = Calendar.getInstance();
    Calendar calSet = (Calendar) calNow.clone();

    calSet.set(Calendar.HOUR_OF_DAY, 5);
    calSet.set(Calendar.MINUTE, 11);
    calSet.set(Calendar.SECOND, 0);
    calSet.set(Calendar.MILLISECOND, 0);

    if(calSet.compareTo(calNow) <= 0){
        //Today Set time passed, count to tomorrow
        calSet.add(Calendar.DATE, 1);
    }

    alarmMgr.cancel(alarmIntent);
    alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calSet.getTimeInMillis(),
            AlarmManager.INTERVAL_DAY, alarmIntent); //1000 * 60 * 1440

}

我正在记录服务运行到文本文件的时间。

编辑:

目标sdk版本为22

根据 kolombo 的建议,我检查了日期并检查了我的 if 语句是否已执行。 if 语句被执行,我得到了明天相同时间的日期。

我正在使用 Moto E 开发应用程序。

我已将项目文件here 上传到谷歌驱动器上。

【问题讨论】:

  • 我想你的 if 语句不起作用。你调试过这个日期吗?你需要更多的日期控制,LogCat 中的更多调试信息,你会看到它有什么问题。将日期转换为正常格式并进行比较。
  • 项目的目标 SDK 是什么(在 Manifest 中)?
  • 并且不要使用克隆,它不是必需的。 'if(calSet.getTimeInMillis()
  • 目标sdk版本为22
  • @kolombo if 条件正在执行,只是通过在 if 条件中添加 Log.i 来检查 log cat,但仍然会提前触发警报。

标签: java android alarmmanager


【解决方案1】:

您需要从服务上的 onStartCommand 函数返回 START_NOT_STICKY。或者您必须在作业完成后停止它。或者您可以使用 IntentService 代替 Service。闹钟工作正常。

public int onStartCommand(Intent intent, int flags, int startId){
    try{
        commitToFile("Start");
    }catch (Exception e){}
    try{
        commitToFile("End");
    }catch (Exception e){}
    return START_NOT_STICKY;
}

您返回 0,即 START_STICKY_COMPATIBILITY。当您的服务第一次启动和运行时触发警报。当您重新启动应用程序时,您的服务也会重新启动,因为您没有停止它。如果您返回 START_NOT_STICKY - 服务将不会重新启动。或者,如果您使用 IntentService,此服务会自动完成工作并自行完成。

【讨论】:

  • 感谢您的宝贵帮助。这对我很有帮助。作为感谢,我将悬赏 200 给你。
  • @Searock 不客气 :-) 这对我来说并不难。并感谢您的赏金:-)
  • 你可以用赏金奖励现有的答案吗? @Searock 你能确认一下元数据的赏金帮助吗?您需要手动点击答案旁边的赏金
  • 我过去做过,我奖励别人的答案,所以如果我奖励给我自己的问题有什么问题。有一个选项说奖励现有答案。答案确实在很大程度上帮助了我,用户也在很大程度上帮助了我。 :)
【解决方案2】:

每当您的 MainActivity 启动时 onCreate() 就会被调用,因此您最终会得到多个警报通知实例。

AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(this, ServiceReceiver.class);

PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 11111, intent, 0);

Calendar calNow = Calendar.getInstance();
Calendar calSet = (Calendar) calNow.clone();

calSet.set(Calendar.HOUR_OF_DAY, 5);
calSet.set(Calendar.MINUTE, 11);
calSet.set(Calendar.SECOND, 0);
calSet.set(Calendar.MILLISECOND, 0);

if(calSet.compareTo(calNow) <= 0){
    //Today Set time passed, count to tomorrow
    calSet.add(Calendar.DATE, 1);
}

alarmMgr.cancel(alarmIntent);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calSet.getTimeInMillis(),
        AlarmManager.INTERVAL_DAY, alarmIntent); //1000 * 60 * 1440

将上述代码放在if 条件中,并在再次调用 onCreate 时将结果保存在 SharedPreferences(例如:calSet)中,只需从 getSharedPreferences 中获取值并与 calNow 进行比较。

【讨论】:

    猜你喜欢
    • 2016-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多