Android setAlarmClock()在打盹模式下触发太晚

Android setAlarmClock()在打盹模式下触发太晚,android,alarmmanager,sleep,doze,setalarmclock,Android,Alarmmanager,Sleep,Doze,Setalarmclock,我很难让我的收音机闹钟正常工作,我在这里读了很多关于这个话题的文章,但不幸的是没有人帮我 AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); Intent intent = new Intent(this, AlarmReceiver.class); PendingIntent penInt = PendingIntent.getBroadcast(this, intentId, intent, 0)

我很难让我的收音机闹钟正常工作,我在这里读了很多关于这个话题的文章,但不幸的是没有人帮我

AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);        
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent penInt = PendingIntent.getBroadcast(this, intentId, intent, 0);
这是我在stackoverflow上找到的API级别之间的区别方法,并将其放入我的
calcNextAlarm()
函数中(加上一些用于调试的日志消息),以正确设置警报,无论设备上使用的是什么API:

// problems in doze mode api 23+
if (Build.VERSION.SDK_INT >= 23) {
    if (testMode) Log.d("Ben", "setAlarmClock() - API 23+");
    am.setAlarmClock(new AlarmManager.AlarmClockInfo(alarmTimeInMillis, penInt), penInt);
}

else if (Build.VERSION.SDK_INT >= 19) {
// Wakes up the device in Idle Mode
    if (testMode) Log.d("Ben", "setExact() - API >= 19 && API < 23");
    am.setExact(AlarmManager.RTC_WAKEUP, alarmTimeInMillis, penInt);
}
// Old APIs
else {
    if (testMode) Log.d("Ben", "set() - API < 19");
    am.set(AlarmManager.RTC_WAKEUP, alarmTimeInMillis, penInt);
}
//打瞌睡模式api 23中的问题+
如果(Build.VERSION.SDK_INT>=23){
if(testMode)Log.d(“Ben”,“setAlarmClock()-API23+”);
am.setAlarmClock(新的AlarmManager.AlarmClockInfo(alarmTimeInMillis,penInt),penInt);
}
else if(Build.VERSION.SDK_INT>=19){
//在空闲模式下唤醒设备
if(testMode)Log.d(“Ben”,“setExact()-API>=19&&API<23”);
am.setExact(AlarmManager.RTC_唤醒,alarmTimeInMillis,penInt);
}
//旧API
否则{
if(testMode)Log.d(“Ben”,“set()-API<19”);
am.set(AlarmManager.RTC_唤醒,alarmTimeInMillis,penInt);
}
根据Log.d消息,我可以看到,在我的Android 7.1设备上,正在执行第一个方法
setAlarmClock()
,以设置接收器中的警报

在经历了3周的测试和编码失败后,我真的很绝望——我今天的闹钟又晚了4分钟——根据“打瞌睡模式”培训页面,这种情况永远不会发生:

使用setAlarmClock()设置的警报将继续正常触发-系统在警报触发前不久会退出休眠状态

在我的7.1手机上,当我将闹钟设置为“现在+5或6”分钟时,闹钟甚至会延迟20秒到1:40分钟。有谁能告诉我怎样才能真正及时地将闹钟完全关闭吗?

尝试使用:

setExactAndAllowWhileIdle()
这将确保警报及时发出。我已经在我自己的应用程序中进行了测试,它是可靠的

如果目标API小于23,请将其保存在检查设备中安装的当前API的If子句中。仅在API级别23以上使用此选项,其余部分继续使用setExact

好的,请回答您的评论:

1) 我已经准确地测试了它在打瞌睡模式下没有电池被插入

2) 是的,不幸的是,对于空闲类型的警报,每9分钟有一个警报限制。这里有两种选择:

首先使用SetExactAndAllowHileId触发第一个警报

a) 对于休眠,您必须使用setAlarmClock方法

b) 对于snooze,可以安排JobScheduler作业,并将最小延迟时间设置为snooze时间。这将确保作业至少安排在休眠间隔的间隙。但这将导致作业在间隔之后随机调度,因此您还需要将覆盖截止日期设置为0,以便作业在最小延迟之后立即调度。同时保持网络需求为无,空闲模式为默认或错误。根据我的经验,这种方法与精确报警方法一样可靠,我个人使用这种方法。

声明:

  • 如果您需要设置打盹时发出的警报,请使用 setAndAllowHileId()或setExactAndAllowHileId()

  • 使用setAlarmClock()设置的报警继续正常触发-系统 在警报响起前,出口处打瞌睡

在“让你的应用适应打瞌睡”一节中,它还说:

注意:既不是setAndAllowHileId()也不是setExactAndAllowHileId() 每个应用程序每9分钟可以触发一次以上的警报

该文件说明:

与其他警报不同,系统可以自由重新安排此类警报 警报与任何其他警报(即使来自 同样的应用程序。当设备空闲时(因为 当应用程序发出任何其他警报时,此警报可以在空闲时熄灭 将保持到稍后),但即使在不空闲时也可能发生。 请注意,操作系统将为自己提供更大的调度灵活性 这些警报比常规的精确警报更有效,因为应用程序 选择了这种行为。当设备处于空闲状态时,可能需要更长的时间 更自由地安排时间,以优化电池寿命


因此,SetExactAndAllowHileId不能保证精确执行,而setAlarmClock更精确(根据文档)。

这也不会像setAlarmClock方法那样向用户显示潜在的通知。现在它不是绝对精确到t,但根据我的经验,它相对精确到大约5-10秒。最后一个不顾一切的选择是在您想要的时间让高优先级FCM消息命中设备,但这取决于网络连接。我确信我以前尝试过,但我太不顾一切了,我会试一试:)1:您确定它在batteray上准确无误,而且不收费吗?(因为所有的方法在使用电源线而不是在打瞌睡模式时似乎都非常准确)2:根据打瞌睡培训页面:
注意:无论是setAndAllowHileId()还是setExactAndAllowHileId()都不能在每个应用程序中每9分钟触发一次以上的警报。
如果我想“打盹”5分钟-我是否应该使用正常的setAlarmClock()而不是setExactAndAllowHileIDLE()进行打盹?3:目标API为27,min SDK为16。目前似乎运行良好。(我认为还有一个问题是我的摩托罗拉E4 Plus,它在7.1.1的股票上有很多问题,有时时钟会“挂起”-我相信这也会累积到迟到的闹钟问题中…问候)有人能确认setAlarmClock不如SetExactAndAllowHileidle()精确吗?只有在打瞌睡模式下,在任何其他地方,我猜两者都同样准确