Meu aplicativo usa AlarmManager e está funcionando há 4 anos. Mas percebi que começou a falhar em alguns dispositivos.
Tenho quase certeza de que o código está correto (estou usando WakefulBroadcastReceiver e setExactAndAllowWhileIdle para dispositivos com Doze) porque está funcionando perfeitamente em dispositivos Nexus, mas falha em dispositivos de alguns fabricantes (Huawei, Xiaomi ...).
Dispositivos Huawei, por exemplo, têm um tipo de gerenciador de bateria que mata aplicativos e, quando um aplicativo é encerrado, os alarmes programados são cancelados. Portanto, definir um aplicativo como "protegido" no gerenciador de bateria da Huawei resolve o problema.
Mas recentemente percebi que ele não está funcionando com mais dispositivos: Xiaomi, Samsung (talvez seja relacionado ao novo "Smart Manager"?) ... Parece que esse comportamento está se tornando um padrão: matar aplicativos em segundo plano.
Alguém sabe algo sobre isso? Há alguma maneira de garantir que o alarme seja disparado?
EDITAR: Este problema é causado por "economizadores de bateria" adicionados por diferentes fabricantes. Mais informações aqui: https://dontkillmyapp.com/
fonte
Respostas:
Estou tentando resolver isso há várias semanas. Não encontrei nada. Huawei acaba com todos os alarmes depois de algum tempo. Se eu colocar o aplicativo no aplicativo protegido na economia de bateria, isso não ajudará. Mas se eu alterar o nome do pacote do meu aplicativo para conter palavras como alarme, relógio ou calendário, ele funciona absolutamente normal como em qualquer outro dispositivo. Não entendo como o Google pode dar certificação para essa porcaria. Eu acho que o OEM não deve modificar a plataforma central dessa forma. Eu entendo que eles têm o próprio protetor de bateria que mata o aplicativo depois de algum tempo, quando o usuário não o usa. Mas isso matando alarmes também de aplicativos protegidos.
Também setAlarmClock () para alarmes de temporização exata ajuda. Mas não é possível usar isso para pensar como atualização de widget.
Atualização: a proteção por palavras-chave do nome do pacote já não está funcionando nos dispositivos Huawei atuais, era verdade em 2017.
fonte
O problema é o Smart Manager. A Samsung possui um gerenciador de bateria que às vezes desativa a execução de certos aplicativos em segundo plano. Ele tentou "retomar" ao voltar ao aplicativo, mas desabilitou completamente o aplicativo ou pode retomar a cada 5 minutos ou mais (dependendo de como a Samsung o possui).
Isso funcionaria em versões de estoque do Android, pois não há Gerenciador Samsung. Você também pode instalar a versão personalizada do Android, que possui alguns recursos para habilitar o SM (dependendo da rom).
fonte
A maioria dos dispositivos Android modernos vem com um aplicativo ou mecanismo, que tenta automagicamente descobrir como economizar bateria e, como resultado, pode matar alguns aplicativos de terceiros. Isso pode resultar na remoção de tarefas e trabalhos agendados (por exemplo, alarmes que não disparam, notificação push que não funciona, etc.). Em muitos casos, isso acontece completamente independente dos mecanismos de economia de bateria do Android, no meu caso não consegui otimizar mais a bateria quando detectei o modelo de alguns dispositivos, redirecionei o usuário para o gerenciador de inicialização para colocar meu aplicativo na lista de permissões
Você encontrou neste link para cada modelo a intenção que você deve invocar https://android-arsenal.com/details/1/6771
fonte
Use AlarmManager para dispositivos <5.0 e JobScheduler para dispositivos 5.0+. Não posso dizer com certeza se o JobScheduler não será afetado pelas travessuras do fabricante, mas parece muito menos provável para mim, visto que o Android está tentando mover as pessoas do AlarmManager para o JobScheduler.
EDIT: O Google lançou uma solução primária para este problema chamada WorkManager . Ele abstrai várias estruturas de agendamento e usa a mais adequada para o dispositivo.
fonte
Eu também tenho um aplicativo que define alarmes. A solução é usar AlarmManager.setAlarmClock () em api> = 21. Isso não é afetado por doze afaik e tem o bônus adicional de colocar um ícone de despertador na bandeja do sistema.
fonte
Pode ser tarde, mas espero que ajude alguém.
Eu estava preso no mesmo problema por tanto tempo. Mas agora eu sei como resolver esse problema. Isso é para qualquer pessoa que possa ter o mesmo problema. As pessoas continuam dizendo que você tem que habilitar o AutoStart, mas eu consegui sem usar o auto start.
Primeiro de tudo, WakeFullBroadcastaReceiver agora está obsoleto e você deve usar BroadcastReceiver. Em segundo lugar, você deve usar o ForegroudService em vez do BackgroundService.
Vou te dar o exemplo a seguir:
IntentService.class
public class NotificationService extends IntentService { //In order to send notification when the app is close //we use a foreground service, background service doesn't do the work. public NotificationService() { super("NotificationService"); } @Override public void onCreate() { super.onCreate(); } @Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { super.onStartCommand(intent, flags, startId); //There is no difference in the result between start_sticky or start_not_sticky at the moment return START_NOT_STICKY; } @Override protected void onHandleIntent(@Nullable Intent intent) { //TODO check if the app is in foreground or not, we can use activity lifecyclecallbacks for this startForegroundServiceT(); sendNotification(intent); stopSelf(); } /*** * you have to show the notification to the user when running foreground service * otherwise it will throw an exception */ private void startForegroundServiceT(){ if (Build.VERSION.SDK_INT >= 26) { String CHANNEL_ID = "my_channel_01"; NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Channel human readable title", NotificationManager.IMPORTANCE_DEFAULT); ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel); Notification notification = new Notification.Builder(this, CHANNEL_ID) .setContentTitle("") .setContentText("").build(); startForeground(1, notification); } } private void sendNotification(Intent intent){ //Send notification //Use notification channle for android O+ } }
inicie o serviço de primeiro plano em BroadcastReceiver.class
public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Intent service = new Intent(context, NotificationService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { context.startForegroundService(service); } else { context.startService(service); } } }
E o setAlarms assim:
public static void setAlarm(Context context, int requestCode, int hour, int minute){ AlarmManager alarmManager =( AlarmManager) context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context//same activity should be used when canceling the alarm , AlarmReceiver.class); intent.setAction("android.intent.action.NOTIFY"); //setting FLAG_CANCEL_CURRENT makes some problems. and doest allow the cancelAlarm to work properly PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1001, intent, 0); Calendar time = getTime(hour, minute); //set Alarm for different API levels if (Build.VERSION.SDK_INT >= 23){ alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,time.getTimeInMillis(),pendingIntent); } else{ alarmManager.set(AlarmManager.RTC_WAKEUP,time.getTimeInMillis(),pendingIntent); }
Em seguida, você deve declarar o destinatário e o foregroundservice no manifesto.
<receiver android:name=".AlarmReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.NOTIFY"> </action> </intent-filter> </receiver> <service android:name=".NotificationService" android:enabled="true" android:exported="true"></service>
Espero que isso ajude alguém.
fonte
a maioria dos novos telefones hoje em dia vem com algum tipo de gerenciador de bateria / economia de energia que faz a mesma coisa que você descreveu. sem contar duboosters e mestres limpos.
Acho que você precisa colocar um aviso de isenção de responsabilidade ou faq na sua lista de aplicativos / loja do jogo informando que este aplicativo precisa ser colocado em exceção do seu aplicativo de gerenciamento de bateria para funcionar corretamente.
fonte
parei de usar AlarmManager há um tempo ... uma alternativa melhor e mais estável
sim .. é uma dor .. mas o trabalho é feito NÃO IMPORTA O QUE
fonte
Você está ouvindo BOOT_COMPLETED? Você precisa definir alarmes novamente quando um dispositivo é reiniciado.
fonte
Qual versão do Android esses dispositivos estão executando?
A partir da API 23, o próprio sistema operacional entrará em um modo ocioso de baixo consumo de energia quando não for usado por um tempo e, nesse modo, os alarmes não serão emitidos. No entanto, há uma maneira de os aplicativos dizerem explicitamente "Preciso que este alarme toque neste momento, independentemente do uso da bateria"; os novos métodos AlarmManager chamados
setAndAllowWhileIdle()
esetExactAndAllowWhileIdle()
.Pela sua descrição, parece que essa pode não ser a causa específica de seus problemas em determinados dispositivos OEMs, mas isso é algo que todos os desenvolvedores que usam o Alarm Manager devem estar cientes.
Finalmente, muitos usos do Alarm Manager são melhor tratados usando os mecanismos do Job Scheduler. Para compatibilidade com versões anteriores, o Play Services "GCM Network Manager" é, na verdade, muito próximo do Job Scheduler em funcionalidade - ele usa o Job Scheduler internamente em versões mais recentes do Android - e não é necessariamente sobre rede, apesar do nome da classe.
fonte
Não acho que matar o aplicativo irá impedir que o gerenciador de alarme desperte seu aplicativo.
Somente quando você "forçar a parada" ou desabilitar o aplicativo, você não receberá retornos de chamada do gerenciador de alarme.
A causa raiz pode ser outra coisa.
Também no M ... setExactAndAllowWhileIdle faz o throttling ... ou seja, se você programar um alarme a cada 2 minutos, ele não será acionado. .. Deve haver uma janela de 15 minutos. .
fonte
Para Xiaomi, pode ser necessário habilitar o AutoStart para seu aplicativo. Estou tentando fazer uma lista de modificações do Android (geralmente do fabricante do telefone) que podem afetar um processo em segundo plano. Se você tem algo novo, adicione uma resposta aqui Lista de assassinos de tarefas Android
fonte
Precisamos habilitar nosso aplicativo no gerenciador de inicialização automática no gerenciador de aplicativos, alguns aparelhos como vivo v5,
In vivo v5, podemos encontrar este menu em iManager -> App Manager -> Auto Start Manager. Habilite nosso aplicativo aqui.
Em seguida, seu alarme / gerenciador de alarmes disparará o alarme se o aplicativo for encerrado ou fechado.
fonte
Eu estava procurando uma resposta e depois de várias horas encontrei o seguinte:
https://stackoverflow.com/a/35220476/3174791
Em resumo, é uma forma de saber se seu aplicativo foi interrompido por 'Aplicativos protegidos' e isso só funciona em dispositivos Huawei. deixe-me saber se existe alguma solução para outros dispositivos (Samsung, Sony, Xiaomi, etc).
fonte