Recentemente, os produtos de nossa empresa foram reclamados por clientes de que o desligamento programado não é pontual e ocasionalmente não funciona. A operação de recorrência específica é desligar automaticamente após um período de tempo relativamente longo, e esse problema de probabilidade é fácil de ocorrer.
Como essa função de desligamento programado foi implementada por um ex-colega, tive que verificar o código, verificar o código de rastreamento e descobri que o método de temporização usava o método set() no AlarmManager:
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, setTime, pendingIntent);
Eu mesmo depurei e descobri que o tempo de curto prazo pode realizar a função normalmente e, em seguida, ajustei um temporizador de dez horas para desligar e descobri que realmente havia um erro, e o desligamento foi atrasado por três minutos.
Consulte documentos e outras informações:
Documentos oficiais sugerem que o API19 (android4.4) seja iniciado, a fim de economizar energia (reduzir o despertar do sistema e o uso da bateria). Usar Alarm.set() e Alarm.setRepeating() não garante precisão. API19 e superior devem usar dois outros métodos de alarme precisos, setWindow() e setExact().
No entanto, depois de usar o método setExact() no Android 8.0, ainda achei que o tempo não seria pontual por muito tempo. Continuei verificando as informações e descobri que o oficial adicionou uma nova interface de aplicativo após a API23 (android 6.0) :
Em seguida, altere pacientemente o método de interface para setExactAndAllowWhileIdle().
Mas uma coisa estranha ainda aconteceu. Depois de usar esta interface no Android 8.0 e definir um timer de longo prazo para dez horas e, em seguida, desligar a tela, descobriu-se que ainda havia um problema de não chegar no horário e atrasou por dois minutos completos.
Neste momento, não tenho paciência, então decidi mudar para outro método de implementação, em vez de usar o AlarmManager para o tempo, a estabilidade é realmente preocupante.
Solução
Por fim, o polling é usado para comparar o tempo de desligamento definido com o horário atual.
Aqui eu me inscrevo para ouvir a transmissão do sistema ACTION_TIME_TICK, e o sistema enviará uma transmissão ACTION_TIME_TICK a cada minuto:
Uma comparação é feita toda vez que uma transmissão é recebida e o timestamp de desligamento definido é comparado com o horário atual.Se o valor absoluto do tempo comparado for menor que 60, a operação correspondente será executada.
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
}
}
}
};
Usar este método é muito mais estável do que usar o AlarmManager! Se o tempo definido pelo AlarmManager pode ser chamado de volta é uma metafísica!