Android AlarmManager在第二天空闲时不会触发报警

Android AlarmManager在第二天空闲时不会触发报警,android,alarmmanager,alarm,android-broadcastreceiver,Android,Alarmmanager,Alarm,Android Broadcastreceiver,我知道关于这个话题有很多类似的话题,但我就是找不到一个真正解决问题或找出根本原因的 首先,我的目标是SDK 22(Android 5.1),这意味着我可以使用AlarmManager+WakefulBroadcastReceiver+IntentService,即使这不是最新的方式。 我对JobScheduler etc解决方案不感兴趣,我只是想了解发生了什么以及原因 我正在测试的手机有安卓8.0,但这并不重要,因为我的目标是安卓5.1 所以我处理的代码设置了第二天06:00的警报 privat

我知道关于这个话题有很多类似的话题,但我就是找不到一个真正解决问题或找出根本原因的

首先,我的目标是SDK 22(Android 5.1),这意味着我可以使用AlarmManager+WakefulBroadcastReceiver+IntentService,即使这不是最新的方式。 我对JobScheduler etc解决方案不感兴趣,我只是想了解发生了什么以及原因

我正在测试的手机有安卓8.0,但这并不重要,因为我的目标是安卓5.1

所以我处理的代码设置了第二天06:00的警报

private fun setupAlarm() {
    val calendar = Calendar.getInstance()
    calendar.timeInMillis = System.currentTimeMillis()
    calendar.add(Calendar.DAY_OF_YEAR, 1)
    calendar.set(Calendar.HOUR_OF_DAY, 6)
    calendar.set(Calendar.MINUTE, 0)

    val alarmIntent = Intent(this, AlarmReceiver::class.java)
    val alarmPendingIntent = PendingIntent.getBroadcast(this, 1221, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT)

    val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.timeInMillis, AlarmManager.INTERVAL_DAY, alarmPendingIntent)
}
AlarmReceiver仅启动服务:

class AlarmReceiver : WakefulBroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        startWakefulService(context, Intent(context, DownloadingIntentService::class.java));
    }
}
然后,该服务尝试下载一个文件,完成后调用completeWakefulIntent(intent)方法,让系统知道它的工作已经完成

我不知道它什么时候起作用,什么时候不起作用。一天早上它做了它应该做的,另一天却没有

我设置了一个远程LogCat功能,以查看IntentService是否启动,但到目前为止,我看不到来自它的任何日志,因此这意味着没有触发警报

如果我为下一分钟设置闹钟,甚至重复一次它应该做的任何事情。但是当我把时间推迟到明天早上的时候,这是非常不可靠的


谢谢你的帮助

我每天都用这段代码触发备份。它对我有用,试试看

AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context, MyReceiver.class);
    intent.setAction("CUSTOM_INTENT");
    alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.set(Calendar.HOUR_OF_DAY, 06);
    calendar.set(Calendar.MINUTE, 00);

    // setRepeating() lets you specify a precise custom interval--in this case,
    // 1 day
    alarmMgr.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis()/1000,
            AlarmManager.INTERVAL_DAY, alarmIntent);

我每天都用这个代码来触发备份。它对我有用,试试看

AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context, MyReceiver.class);
    intent.setAction("CUSTOM_INTENT");
    alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.set(Calendar.HOUR_OF_DAY, 06);
    calendar.set(Calendar.MINUTE, 00);

    // setRepeating() lets you specify a precise custom interval--in this case,
    // 1 day
    alarmMgr.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis()/1000,
            AlarmManager.INTERVAL_DAY, alarmIntent);
试试这个:

    Calendar now = Calendar.getInstance();
        Calendar alarm = Calendar.getInstance();
        alarm.set(Calendar.HOUR_OF_DAY, hourOfDay);
        alarm.set(Calendar.MINUTE, minute);
        long alarmMillis = alarm.getTimeInMillis();
        if (alarm.before(now)) alarmMillis+= 86400000L;  //It will add 1 day if your time selected before now
        //set alarm method of yours\\
设置AlarmManager(请求代码,alarmMillis)

我的接受者类别:

public class AlarmReceiver extends BroadcastReceiver {


    @Override
    public void onReceive(Context context, Intent intent) {
        //do your stuff here\\
    }
}
舱单:

<receiver android:name=".utils.AlarmReceiver" />

我已经试过上面的代码设置警报,并做我的自定义任务。也许这会对你有所帮助。

试试这个:

    Calendar now = Calendar.getInstance();
        Calendar alarm = Calendar.getInstance();
        alarm.set(Calendar.HOUR_OF_DAY, hourOfDay);
        alarm.set(Calendar.MINUTE, minute);
        long alarmMillis = alarm.getTimeInMillis();
        if (alarm.before(now)) alarmMillis+= 86400000L;  //It will add 1 day if your time selected before now
        //set alarm method of yours\\
设置AlarmManager(请求代码,alarmMillis)

我的接受者类别:

public class AlarmReceiver extends BroadcastReceiver {


    @Override
    public void onReceive(Context context, Intent intent) {
        //do your stuff here\\
    }
}
舱单:

<receiver android:name=".utils.AlarmReceiver" />


我已经试过上面的代码设置警报,并做我的自定义任务。也许这会对你有所帮助。

我自己也面临过这个问题。看看会发生什么,setRepeating方法让android系统调整触发警报的时间。它很可能会尝试批处理不同的报警,以优化电池使用。但在正常情况下,如果电话没有打瞌睡。。。它通常在正确的时间触发警报

但是,如果手机闲置一段时间,手机会进入睡眠模式,因此闹钟会延迟。我个人观察到延迟时间长达11:30小时

如果你想让它准确地发射,你必须使用setExactAndAllowHileId方法或setAlarmClock方法。在这种情况下,您将不得不自己处理下一次警报的调度。这些方法在打瞌睡模式下运行良好,并能在准确的时间触发警报


这些方法也有缺点。SetExactAndAllowHileIDLE方法只能用于计划报警,最多每九分钟一次。setAlarmClock方法将向用户显示一个类似常规警报的通知,并指示警报的详细信息(此行为因不同的操作系统版本而异)

我自己也遇到过这个问题。看看会发生什么,setRepeating方法让android系统调整触发警报的时间。它很可能会尝试批处理不同的报警,以优化电池使用。但在正常情况下,如果电话没有打瞌睡。。。它通常在正确的时间触发警报

但是,如果手机闲置一段时间,手机会进入睡眠模式,因此闹钟会延迟。我个人观察到延迟时间长达11:30小时

如果你想让它准确地发射,你必须使用setExactAndAllowHileId方法或setAlarmClock方法。在这种情况下,您将不得不自己处理下一次警报的调度。这些方法在打瞌睡模式下运行良好,并能在准确的时间触发警报

这些方法也有缺点。SetExactAndAllowHileIDLE方法只能用于计划报警,最多每九分钟一次。setAlarmClock方法将主要向用户显示一个类似常规警报的通知,并指示警报的详细信息(此行为因不同的操作系统版本而异)

一些事情:

  • 进一步的
    报警
    时间安排
  • 虽然您的目标是API级别22,但在更高的Android版本中,不推荐的元素可能无法完全工作,这是WakefulBroadcastReceiver的情况
  • 您正在尝试在Android 8.0中运行一个。值得探索的是:

    • 它可以从后台启动
    • 正确地通知用户您确实在做一些事情,而手机应该处于空闲状态
    • 不要害怕运行可能需要几秒钟才能完成的任务
  • 您可能已经终止了应用程序。当用户手动关闭应用程序时,在大多数设备中,所有的
    报警
    挂起内容
    也会被关闭


许多开发人员使用的一种调度策略不是设置一个重复的
报警
,而是有两个单独的报警不断地重新安排彼此的时间(Kushan在他的回答中提到了类似的事情)

简言之:

在一天中尽快启动
计划程序
(即使当用户打开你的应用程序时,它也可能被触发多次)。检查所需的
pendingents
是否已经存在(您的后台作业)。如果没有,就安排一下。另外,在11点55分左右安排另一个
警报

这个午夜计划程序所要做的就是在5分钟内重新安排主
AlarmManager
,然后再安排接下来几天的作业和午夜警报

此方法允许您:

  • 计划精确的报警,自r