我试图制作一个应用程序,要求计划时间准确无误。我需要在特定时间重置app内生成的日志(驱动程序职责信息)。
我尝试使用setAlarm
,但它在6.0及以上版本上无法正常使用。因为它应该在没有互联网的情况下工作,我无法使用Push Notification.
我也尝试使用setAlarmClock
,但它也不能正常工作。
我需要alarm
准确1小时24小时
更新
日志警报
public static void startLogAlarm(Context ctx,long milliseconds) {
final int SDK_INT = Build.VERSION.SDK_INT;
// 1 Day = 86400 seconds = 86400000 milliseconds
long timeInMillis = System.currentTimeMillis() + milliseconds;
AlarmManager alarmManager = (AlarmManager) ctx
.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(ctx, eLogReceiver.class);
intent.setAction(Utility.eLOG_ACTION);
PendingIntent pi = PendingIntent.getBroadcast(ctx, 3, intent, PendingIntent.FLAG_UPDATE_CURRENT);
if (SDK_INT < Build.VERSION_CODES.KITKAT) {
alarmManager.set(AlarmManager.RTC_WAKEUP, timeInMillis, pi);
} else if (Build.VERSION_CODES.KITKAT <= SDK_INT && SDK_INT < Build.VERSION_CODES.M) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, timeInMillis, pi);
} else if (SDK_INT >= Build.VERSION_CODES.M) {
// AlarmManager.AlarmClockInfo alarmClockInfo = new AlarmManager.AlarmClockInfo(timeInMillis, pi);
// alarmManager.setAlarmClock(alarmClockInfo, pi);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timeInMillis, pi);
}
}
// Start Alarm
Utility.startLogAlarm(this, Constants.DAY_MILLISECONDS);
public class Constants {
public static final long HOUR_MILLISECONDS = 3600000;
public static final long DAY_MILLISECONDS = 86400000;
}
传感器警报
public static void startSensorAlarm(Context ctx, long timeInMillis) {
final int SDK_INT = Build.VERSION.SDK_INT;
AlarmManager alarmManager = (AlarmManager) ctx
.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(ctx, AlarmReceiver.class);
intent.setAction(Utility.SENSOR_ACTION);
PendingIntent pi = PendingIntent.getBroadcast(ctx, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
if (SDK_INT < Build.VERSION_CODES.KITKAT) {
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeInMillis, pi);
} else if (Build.VERSION_CODES.KITKAT <= SDK_INT && SDK_INT < Build.VERSION_CODES.M) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeInMillis, pi);
} else if (SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeInMillis, pi);
//AlarmManager.AlarmClockInfo alarmClockInfo = new AlarmManager.AlarmClockInfo(System.currentTimeMillis()+timeInMillis, pi);
alarmManager.setAlarmClock(alarmClockInfo, pi);
}
showLog("Sensor Alarm Time", timeInMillis + "");
}
群组闹钟
public static void startGroupAlarm(Context ctx) {
final int SDK_INT = Build.VERSION.SDK_INT;
AlarmManager alarmManager = (AlarmManager) ctx
.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(ctx, AlarmReceiver.class);
intent.setAction(Utility.GROUP_UPDATE_ACTION);
PendingIntent pi = PendingIntent.getBroadcast(ctx, 2, intent, PendingIntent.FLAG_UPDATE_CURRENT);
if (SDK_INT < Build.VERSION_CODES.KITKAT) {
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + INTERVAL_EVERY_8_HOURS, pi);
} else if (Build.VERSION_CODES.KITKAT <= SDK_INT && SDK_INT < Build.VERSION_CODES.M) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + INTERVAL_EVERY_8_HOURS, pi);
} else if (SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + INTERVAL_EVERY_8_HOURS, pi);
}
Utility.showLog("Group Alarm", "Started");
}
LogNoticeAlarm
public static void startLogNoticeAlarm(Context ctx, long milliseconds) {
final int SDK_INT = Build.VERSION.SDK_INT;
// 1 Hour = 3600 seconds = 3600000 milliseconds
long HourMilliseconds = System.currentTimeMillis() + milliseconds;
AlarmManager alarmManager = (AlarmManager) ctx
.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(ctx, eLogNoticeReceiver.class);
intent.setAction(Utility.eLOG_NOTICE_ACTION);
PendingIntent pi = PendingIntent.getBroadcast(ctx, 4, intent, PendingIntent.FLAG_UPDATE_CURRENT);
if (SDK_INT < Build.VERSION_CODES.KITKAT) {
alarmManager.set(AlarmManager.RTC_WAKEUP, HourMilliseconds, pi);
} else if (Build.VERSION_CODES.KITKAT <= SDK_INT && SDK_INT < Build.VERSION_CODES.M) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, HourMilliseconds, pi);
} else if (SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + milliseconds, pi);
// AlarmManager.AlarmClockInfo alarmClockInfo = new AlarmManager.AlarmClockInfo(HourMilliseconds, pi); // alarmManager.setAlarmClock(alarmClockInfo, pi);
}
}
我一直在使用总共4个警报1个需要每5分钟安排一次,休息时间为1小时8小时24小时。那传感器警报(每5分钟一次)是否导致其他警报出现问题?
请建议最佳解决方案
注意:关于SO的所有其他问题都无效。
答案 0 :(得分:0)
显然这个因为每隔5分钟发出警报就会引起问题。所以其他警报会因为两次警报同时发生而导致失败。
所以我的建议是将你的其他闹钟时间设置为1或2分钟之后/之前(即8小时2分钟而不是8小时)。
注意: 1或2分钟应完全取决于您的铃声持续时间。
答案 1 :(得分:0)
有几种方法可以解决这个问题。
首先要注意Android Alarm Documentation:
中的这个(释义)引用警报管理器旨在在特定时间运行您的代码,即使您的应用当前未运行。对于正常的计时操作(刻度等),使用处理程序更容易,也更有效。
您可以详细了解权衡here。话虽如此,我会在保持所有警报的基础上回答。同一文献中的另一个引用提到:
从API 19(KITKAT)开始,警报传递不准确:操作系统将移动警报以最小化唤醒... targetSdkVersion早于API 19的应用程序将继续看到先前的行为。
这实际上是指Doze Mode,其中指出:
中窃取Google的图片AlarmManager警报(包括setExact())被推迟到下一个维护窗口。
这对您来说意味着,如果您有相互靠近的警报,设备将在下一个维护周期中批量处理它们,但如果您设置了
targetSdkVersion
更低,您可以轻松修复以排除批处理行为(,但代价是其他已编译的改进)。
假设您实际上坚持使用Doze行为,切换到扩展常规BroadCastReceiver
的{{3}}内容有助于确保您有时间回复RTC_WAKEUP
警报。
您还可以使用多个BroadcastReceiver,以便Android单独处理它们(而不是将它们分配到每分钟一次/维护)。这只意味着在不同的接收器上处理不同的待处理意图:
Intent intent = new Intent(ctx, AlarmReceiver.class);
...
Intent intent = new Intent(ctx, AlarmReceiver2.class); //a different receiver class
...
我的代码中不清楚eLogNotice接收器是否是其他警报使用的同一接收器的实例。