Takeaway:
Recently, AlarmManager alarm clock was used to develop a reminder service. There was no problem in the simulator test, and there was no problem in the phones with lower versions (android6.0 and below), but there was a “delay after screen off” problem on the phones with android11 version, which was about 2-5 minutes. The specific reasons are: In order to alleviate the notorious power consumption problem of Android phones, Google introduced a new power saving mechanism Doze mode in version 6.0. After Android 6.0, if AlarmManager can still be responded immediately when the phone is in the so-called Doze mode, You need to use AlarmManager new provides two methods of setAndAllowWhileIdle () or setExactAndAllowWhileIdle ().
What is AlarmManager?
AlarmManager is a system-level alert service in Android that broadcasts a specific Intent for us at a specific time. With an Intent, we need it to perform an action, such as startActivity, startService, startBroadcast, to make the Intent useful. Typically, we use PendingIntent, which can be understood as an Intent wrapper that contains the specified action.
AlarmManager is suitable for developing scheduled tasks similar to alarm clocks. It is usually used as a global timer to start a certain piece of code.
There are three common methods used in the AlarmManager object:
1. Set (int type, long startTime, PendingIntent PI), used to set an alarm.
SetRepeating (int type, long startTime, long intervalTime, PendingIntent PI) is used to set the repeated alarm clock. PendingIntent is sent once every intervalTime millisecond.
3, setInexactRepeating (int type, long startTime, Long intervalTime, PendingIntent PI) This is more energy efficient than the setRepeating() method because the system combines similar alarms to avoid waking the device unnecessarily. The PendingIntent is sent with an interval of approximately intervalTime milliseconds. The main difference between setRepeating and setInexactRepeating is accuracy. The use of setInexactRepeating can reduce battery consumption. Therefore, this method is given priority.
- The int type: four wake-up types of AlarmManager, which can use the following four constants:
1, AlarmManager. ELAPSED_REALTIME: using relative time can be achieved by SystemClock. ElapsedRealtime () to obtain (from boot up to now, the number of milliseconds, including mobile phone of sleep), equipment when sleep will not wake up the equipment. 2. Alarmmanager. ELAPSED_REALTIME_WAKEUP: Has the same basic function as ELAPSED_REALTIME, but wakes up the device when it is asleep. 3. Alarmmanager. RTC: Use the absolute time, which can be obtained from System.currentTimemillis (). 4. Alarmmanager. RTC_WAKEUP: Provides the same basic functions as RTC, but wakes up the device when it is asleep. Relative time: equipment after the boot to the current time, SystemClock. ElapsedRealtime () to obtain the relative time. Absolute time: the time between January 1, 1970 and the current experience. System.currenttimemillis () and calendar.getTimeInmillis () get absolute time. If it is relative to time, then calculate triggerAtMillis will need to use the SystemClock. ElapsedRealtime (); If it is absolute time, then calculating triggerAtMillis requires either System.CurrentTimemillis () or calendar.getTimeInmillis ().
- Parameter Long startTime: the first execution time of the alarm, in milliseconds
- Parameter Long intervalTime: Indicates the interval between alarm execution, in milliseconds.
- Parameter PendingIntent PI: Specifies the execution action of the alarm, such as sending a broadcast, giving an alert, and so on.
Fully compatible AlarmManager example code, perfect to solve the problem of alarm delay after screen off above android6.0:
/* Get the alarm manager */
AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
/* Define an alarm action (taskService is a custom service) */
Intent intent = new Intent(context, taskService.class);
PendingIntent pi = PendingIntent.getService(context, 0, intent, 0);
// The version is later than Android 6.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pi);
}
// Version larger than Android 4.4
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// Single alarm clock:
//alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pi);
// Repeat alarm:
alarmManager.setWindow(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 5 * 1000,pi);
} else {
/* Repeat the alarm */
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 5 * 1000, pi);
}
Copy the code