최근 저희 회사의 제품은 고객으로부터 예정된 종료가 제 시간에 이루어지지 않고 가끔 작동하지 않는다는 불만을 제기했습니다. 특정 반복 작업은 비교적 오랜 시간이 지나면 자동으로 종료되며 이러한 확률 문제는 발생하기 쉽습니다.
이 예정된 종료 기능은 이전 동료에 의해 구현되었으므로 코드를 확인하고 추적 코드를 확인해야 하며 타이밍 메서드가 AlarmManager에서 set() 메서드를 사용했음을 발견했습니다.
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, setTime, pendingIntent);
나는 그것을 직접 디버깅하고 단기 타이밍이 기능을 정상적으로 실현할 수 있음을 발견 한 다음 10 시간 타이머를 조정하여 종료하고 실제로 오류가 있음을 발견했으며 종료가 3 분 동안 지연되었습니다.
문서 및 기타 정보 참조:
공식 문서에서는 전원을 절약하기 위해(시스템 깨우기 및 배터리 사용 감소) API19(android4.4)를 시작하도록 제안합니다. Alarm.set() 및 Alarm.setRepeating() 사용은 정확성을 보장하지 않습니다. API19 이상은 setWindow() 및 setExact()라는 두 가지 다른 정확한 Alarm 메서드를 사용해야 합니다.
하지만 Android 8.0에서 setExact() 메서드를 사용한 후에도 여전히 오랫동안 시간을 지키지 않는다는 것을 알았고 계속해서 정보를 확인했으며 API23(Android 6.0) 이후에 공식에서 새로운 애플리케이션 인터페이스를 추가한 것을 발견했습니다. :
그런 다음 끈기 있게 인터페이스 메서드를 setExactAndAllowWhileIdle()로 변경합니다.
그런데 이상하게도 안드로이드 8.0에서 이 인터페이스를 사용하고 10시간으로 장시간 타이머를 설정한 다음 화면을 꺼도 여전히 시간을 맞추지 못하는 문제가 있어 지연되는 현상이 발생했습니다. 전체 2 분.
이때 참을성이 없어 다른 구현 방법으로 과감히 변경하기로 했습니다. 타이밍에 AlarmManager를 사용하는 대신 안정성이 정말 걱정됩니다.
해결책
마지막으로 폴링은 설정된 종료 시간을 현재 시간과 비교하는 데 사용됩니다.
여기에서 ACTION_TIME_TICK 시스템 브로드캐스트를 수신하도록 등록 하고 시스템은 매분 ACTION_TIME_TICK 브로드캐스트를 전송합니다.
방송을 수신할 때마다 비교를 하여 설정된 종료 타임스탬프를 현재 시간과 비교하여 비교 시간의 절대값이 60 미만이면 해당 동작을 수행한다.
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(ACTION_TIME_TICK)) {
//setMillionSeconds为设定的定时时间戳
if (Math.abs(setMillionSeconds - System.currentTimeMillis()) <= 60000) {
//to do what you whant to do
}
}
}
};
이 방법을 사용하면 AlarmManager를 사용하는 것보다 훨씬 안정적입니다! AlarmManager에서 설정한 시간을 다시 불러올 수 있는지 여부는 형이상학입니다!