AlarmManager
) oferecem uma maneira de realizar operações baseadas em tempo fora do ciclo de vida do aplicativo.
Por exemplo, é possível usar um alarme para iniciar uma operação de longa duração, como
iniciar um serviço uma vez por dia para fazer o download de uma previsão do tempo.
Os alarmes têm estas características:
Permitem que você dispare intents em horários e/ou intervalos definidos
É possível usá-los com broadcast receivers para programar jobs ou WorkRequests para executar outras operações.
Como eles operam fora do aplicativo, você pode usá-los para acionar eventos ou ações mesmo quando o app não estiver em execução e o próprio dispositivo estiver em modo de suspensão.
Eles ajudam a minimizar os requisitos de recursos do app. É possível programar operações sem depender de timers ou da execução contínua de serviços.
Definir um alarme impreciso
Quando um app define um alarme impreciso, o sistema envia o alarme em algum momento no futuro. Alarmes imprecisos oferecem algumas garantias em relação ao tempo de entrega do alarme, respeitando restrições de economia de bateria, como o Soneca.
Os desenvolvedores podem aproveitar as garantias de API abaixo para personalizar o horário da entrega de alarmes imprecisos.
Enviar um alarme depois de um horário específico
Se o app chamar set()
,
setInexactRepeating()
ou setAndAllowWhileIdle()
,
o alarme nunca será acionado antes do tempo de acionamento fornecido.
No Android 12 (nível 31 da API) e versões mais recentes, o sistema invoca o alarme dentro de uma hora após o tempo de acionamento fornecido, a menos que haja alguma restrição de economia de bateria, como Economia de bateria ou Soneca.
Enviar um alarme durante uma janela de tempo
Se o app chamar setWindow()
, o alarme nunca será acionado antes do tempo de acionamento
fornecido. A menos que haja restrições de economia de bateria em vigor, o alarme é
enviado dentro da janela de tempo especificada, começando pelo momento de acionamento
determinado.
Caso o app seja destinado ao Android 12 ou versões mais recentes, o sistema poderá atrasar
a invocação de um alarme impreciso com intervalo de tempo em pelo menos 10 minutos. Por
esse motivo, os valores do parâmetro windowLengthMillis
em 600000
são recortados em
600000
.
Gerar um alarme recorrente em intervalos regulares
Se o app chamar setInexactRepeating()
,
o sistema invocará vários alarmes:
- O primeiro alarme é acionado dentro da janela de tempo especificada, começando a partir do tempo de acionamento determinado.
- Os alarmes subsequentes geralmente disparam após a janela de tempo especificada. O tempo entre duas invocações consecutivas do alarme pode variar.
Definir um alarme exato
O sistema invoca um alarme exato em um momento preciso no futuro.
A maioria dos apps pode programar tarefas e eventos usando alarmes imprecisos para concluir vários casos de uso comuns. Se a funcionalidade principal do app depende de um alarme com marcação de tempo precisa, como para um app de despertador ou de calendário, não há problema em usar um alarme exato.
Casos de uso que podem não exigir alarmes exatos
A lista a seguir mostra fluxos de trabalho comuns que podem não exigir um alarme exato:
- Programar operações de tempo durante o ciclo de vida do app
- A classe
Handler
inclui vários bons métodos para lidar com operações de tempo, por exemplo, fazer alguns trabalhos a cada n segundos, enquanto seu app está ativo:postAtTime()
epostDelayed()
. Observe que essas APIs dependem do tempo de atividade do sistema e não do tempo real. - Trabalho programado em segundo plano, como atualizar o app e fazer upload de registros
- O
WorkManager
oferece uma maneira de programar trabalhos periódicos sensíveis ao tempo. É possível fornecer um intervalo de repetição eflexInterval
(mínimo de 15 minutos) para definir um ambiente de execução granular para o trabalho. - Ação especificada pelo usuário que precisa acontecer após um período específico (mesmo com o sistema inativo)
- Use um alarme não exato. Chame
setAndAllowWhileIdle()
especificamente. - Ação especificada pelo usuário que acontece após um horário específico
- Use um alarme não exato. Chame
set()
especificamente. - Ação especificada pelo usuário que pode acontecer em uma janela de tempo
- Use um alarme não exato. Chame
setWindow()
especificamente. Se o app for destinado ao Android 12 ou versões mais recentes, a menor duração permitida da janela será de 10 minutos.
Maneiras de definir um alarme exato
Seu app pode definir alarmes exatos usando um dos métodos a seguir. Esses métodos são ordenados de modo que aqueles mais próximos do fim da lista ofereçam tarefas mais urgentes, mas exijam mais recursos do sistema.
setExact()
Invoque um alarme em um momento quase exato no futuro, desde que outras medidas de economia de bateria não estejam em vigor.
Use esse método para definir alarmes exatos, a menos que o trabalho do app tenha um tempo crítico para o usuário.
setExactAndAllowWhileIdle()
Invoque um alarme em um momento quase exato no futuro, mesmo se houver medidas de economia de bateria em vigor.
setAlarmClock()
Invoque um alarme em um momento preciso no futuro. Como esses alarmes são altamente visíveis para os usuários, o sistema nunca ajusta o tempo de entrega. O sistema identifica esses alarmes como os mais críticos e deixa os modos de baixo consumo de energia, se necessário, para transmiti-los.
Consumo de recursos do sistema
Quando o sistema aciona alarmes exatos que o app define, o dispositivo consome uma grande quantidade de recursos, como a duração da bateria, especialmente se estiver em um modo de economia de energia. Além disso, o sistema não pode agrupar facilmente essas solicitações para usar os recursos com mais eficiência.
É altamente recomendável criar um alarme impreciso sempre
que possível. Para realizar um trabalho mais longo, programe-o usando
WorkManager
ou
JobScheduler
no
BroadcastReceiver
do alarme. Para realizar o trabalho enquanto
o dispositivo está no modo Soneca, crie um alarme impreciso usando
setAndAllowWhileIdle()
e inicie um job usando o alarme.
Declarar a permissão de alarme exato adequada
Caso seu app seja destinado ao Android 12 ou versões mais recentes, você precisa ter o
acesso especial aos "Alarmes e lembretes". Para fazer isso, declare a permissão
SCHEDULE_EXACT_ALARM
no arquivo de manifesto do app, conforme mostrado no snippet de código abaixo:
<manifest ...> <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/> <application ...> ... </application> </manifest>
Caso o app seja destinado ao Android 13 (nível 33 da API) ou versões mais recentes, é possível
declarar a permissão SCHEDULE_EXACT_ALARM
ou
USE_EXACT_ALARM
.
<manifest ...> <uses-permission android:name="android.permission.USE_EXACT_ALARM"/> <application ...> ... </application> </manifest>
Embora as permissões SCHEDULE_EXACT_ALARM
e USE_EXACT_ALARM
sinalizem os mesmos recursos, elas são concedidas de maneira diferente e oferecem suporte a diferentes
casos de uso. O app precisa usar alarmes exatos e declarar a permissão
SCHEDULE_EXACT_ALARM
ou USE_EXACT_ALARM
somente se uma função voltada ao usuário
no app exigir ações no momento certo.
USE_EXACT_ALARM
- Concedido automaticamente
- Não pode ser revogado pelo usuário
- Sujeito a uma futura política do Google Play
- Casos de uso limitados
SCHEDULE_EXACT_ALARM
- Permissão concedida pelo usuário
- Conjunto mais amplo de casos de uso
- Os apps precisam confirmar que a permissão não foi revogada
A permissão SCHEDULE_EXACT_ALARM
não é concedida previamente a novas instalações de
apps destinados ao Android 13 (nível 33 da API) e versões mais recentes. Se um usuário transferir dados
do app para um dispositivo com o Android 14 usando uma operação de backup e restauração, a
permissão SCHEDULE_EXACT_ALARM
será negada no novo dispositivo. No entanto, se
um app já tiver essa permissão, ela será concedida previamente quando o
dispositivo for atualizado para o Android 14.
Observação: se o alarme exato for definido usando um objeto
OnAlarmListener
, como na API
setExact
, a permissão SCHEDULE_EXACT_ALARM
não será necessária.
Como usar a permissão SCHEDULE_EXACT_ALARM
Ao contrário de USE_EXACT_ALARM
, a permissão SCHEDULE_EXACT_ALARM
precisa ser
concedida pelo usuário. O usuário e o sistema podem revogar a
permissão SCHEDULE_EXACT_ALARM
.
Para conferir se a permissão foi concedida ao app, chame
canScheduleExactAlarms()
antes de tentar definir um alarme exato. Quando a permissão SCHEDULE_EXACT_ALARM
é revogada, o app é interrompido, e todos os alarmes exatos futuros
são cancelados. Isso também significa que o valor retornado por
canScheduleExactAlarms()
permanece válido durante todo o ciclo de vida do app.
Quando a permissão SCHEDULE_EXACT_ALARMS
é concedida ao app, o
sistema envia a
transmissão
ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED
. Seu app precisa implementar um broadcast
receiver que faz o
seguinte:
- Confirma que seu app ainda tem o acesso especial. Para fazer isso,
chame o método
canScheduleExactAlarms()
. Essa verificação protege o app contra o caso em que o usuário concede a permissão e a revoga quase imediatamente depois. - Reprograma os alarmes exatos que o app precisa com base no estado atual.
Essa lógica precisa ser parecida com a de quando o app recebe a
transmissão
ACTION_BOOT_COMPLETED
.
Pedir aos usuários para conceder a permissão SCHEDULE_EXACT_ALARM
Se necessário, você pode direcionar os usuários para a tela Alarmes e lembretes nas configurações do sistema, conforme mostrado na Figura 1. Para isso, siga estas etapas:
- Na IU do app, explique ao usuário por que o app precisa programar alarmes exatos.
- Invoque uma intent que inclua a
ação da intent
ACTION_REQUEST_SCHEDULE_EXACT_ALARM
.
Definir um alarme recorrente
Alarmes recorrentes permitem que o sistema notifique seu app de acordo com uma programação recorrente.
Um alarme mal projetado pode consumir bateria e sobrecarregar os servidores de maneira significativa. Por esse motivo, no Android 4.4 (API de nível 19) e versões mais recentes, todos os alarmes repetidos são alarmes imprecisos.
Um alarme recorrente tem as seguintes características:
Um tipo de alarme. Para saber mais, consulte Escolher um tipo de alarme.
Um tempo de acionamento. Se o horário do gatilho especificado estiver no passado, o alarme será acionado imediatamente.
O intervalo do alarme. Por exemplo, uma vez por dia, a cada hora ou a cada cinco minutos.
Um intent pendente que é acionado quando o alarme é disparado. Quando você define um segundo alarme que usa a mesma intent pendente, ele substitui o alarme original.
Para cancelar uma PendingIntent()
, transmita
FLAG_NO_CREATE
para PendingIntent.getService()
para acessar uma instância da intent (se existir) e transmitir essa intent para
AlarmManager.cancel()
.
Kotlin
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as? AlarmManager val pendingIntent = PendingIntent.getService(context, requestId, intent, PendingIntent.FLAG_NO_CREATE) if (pendingIntent != null && alarmManager != null) { alarmManager.cancel(pendingIntent) }
Java
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); PendingIntent pendingIntent = PendingIntent.getService(context, requestId, intent, PendingIntent.FLAG_NO_CREATE); if (pendingIntent != null && alarmManager != null) { alarmManager.cancel(pendingIntent); }
Escolher um tipo de alarme
Uma das primeiras considerações sobre o uso de um alarme recorrente é qual precisa ser o tipo dele.
Existem dois tipos gerais de relógio para alarmes: "tempo real decorrido" e "relógio em tempo real" (RTC, na sigla em inglês). O tempo real decorrido usa o "tempo desde a inicialização do sistema" como referência, e o relógio em tempo real usa o horário UTC (relógio de parede). Isso significa que o tempo real decorrido é adequado para definir um alarme com base na passagem do tempo (por exemplo, um alarme que dispara a cada 30 segundos), já que ele não é afetado por fuso horário ou localidade. O tipo de relógio em tempo real é mais adequado para alarmes que dependem da localidade atual.
Os dois tipos têm uma versão de "ativação", que diz para ativar a CPU do dispositivo se a tela estiver desligada. Isso garante que o alarme seja disparado no horário programado. Isso é útil caso seu app tenha uma dependência de tempo. Por exemplo, se ele tiver uma janela limitada para executar uma operação específica. Se você não usar a versão de ativação do seu tipo de alarme, todos os alarmes recorrentes serão acionados quando o dispositivo estiver ativado novamente.
Se você simplesmente precisa que o alarme seja disparado em um intervalo específico (por exemplo, a cada meia hora), use um dos tipos de "tempo real decorrido". Em geral, essa é a melhor escolha.
Se você precisar que o alarme seja acionado em um determinado horário do dia, escolha um dos tipos de relógio em tempo real com base em relógio. No entanto, essa abordagem pode apresentar algumas desvantagens. O app pode não funcionar bem para outras localidades e, se o usuário mudar a configuração de horário do dispositivo, ele poderá causar um comportamento inesperado no app. O uso de um tipo de alarme com relógio em tempo real também não tem uma boa escala, conforme discutido acima. Recomendamos que você use um alarme de "tempo real decorrido" se possível.
Veja a lista de tipos:
ELAPSED_REALTIME
: dispara a intent pendente com base no tempo desde a inicialização do dispositivo, mas não ativa o dispositivo. O tempo decorrido inclui qualquer momento em que o dispositivo esteve inativo.ELAPSED_REALTIME_WAKEUP
: ativa o dispositivo e dispara a intent pendente após o período especificado desde a inicialização do dispositivo.RTC
: dispara a intent pendente no horário especificado, mas não ativa o dispositivo.RTC_WAKEUP
: ativa o dispositivo para disparar a intent pendente no horário especificado.
Exemplos de alarmes de "tempo real decorrido"
Confira alguns exemplos de como usar ELAPSED_REALTIME_WAKEUP
.
Ativar o dispositivo para disparar o alarme em 30 minutos, e a cada 30 minutos depois disso:
Kotlin
// Hopefully your alarm will have a lower frequency than this! alarmMgr?.setInexactRepeating( AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR, AlarmManager.INTERVAL_HALF_HOUR, alarmIntent )
Java
// Hopefully your alarm will have a lower frequency than this! alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR, AlarmManager.INTERVAL_HALF_HOUR, alarmIntent);
Ativar o dispositivo para disparar um alarme único (não recorrente) em um minuto:
Kotlin
private var alarmMgr: AlarmManager? = null private lateinit var alarmIntent: PendingIntent ... alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent -> PendingIntent.getBroadcast(context, 0, intent, 0) } alarmMgr?.set( AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 60 * 1000, alarmIntent )
Java
private AlarmManager alarmMgr; private PendingIntent alarmIntent; ... alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, AlarmReceiver.class); alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0); alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 60 * 1000, alarmIntent);
Exemplos de alarmes de "relógio em tempo real"
Confira alguns exemplos de como usar
RTC_WAKEUP
.
Ativar o dispositivo para disparar o alarme aproximadamente às 14h e repetir uma vez por dia no mesmo horário:
Kotlin
// Set the alarm to start at approximately 2:00 p.m. val calendar: Calendar = Calendar.getInstance().apply { timeInMillis = System.currentTimeMillis() set(Calendar.HOUR_OF_DAY, 14) } // With setInexactRepeating(), you have to use one of the AlarmManager interval // constants--in this case, AlarmManager.INTERVAL_DAY. alarmMgr?.setInexactRepeating( AlarmManager.RTC_WAKEUP, calendar.timeInMillis, AlarmManager.INTERVAL_DAY, alarmIntent )
Java
// Set the alarm to start at approximately 2:00 p.m. Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.set(Calendar.HOUR_OF_DAY, 14); // With setInexactRepeating(), you have to use one of the AlarmManager interval // constants--in this case, AlarmManager.INTERVAL_DAY. alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, alarmIntent);
Desperte o dispositivo para disparar o alarme exatamente às 8h30 e a cada 20 minutos depois:
Kotlin
private var alarmMgr: AlarmManager? = null private lateinit var alarmIntent: PendingIntent ... alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent -> PendingIntent.getBroadcast(context, 0, intent, 0) } // Set the alarm to start at 8:30 a.m. val calendar: Calendar = Calendar.getInstance().apply { timeInMillis = System.currentTimeMillis() set(Calendar.HOUR_OF_DAY, 8) set(Calendar.MINUTE, 30) } // setRepeating() lets you specify a precise custom interval--in this case, // 20 minutes. alarmMgr?.setRepeating( AlarmManager.RTC_WAKEUP, calendar.timeInMillis, 1000 * 60 * 20, alarmIntent )
Java
private AlarmManager alarmMgr; private PendingIntent alarmIntent; ... alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, AlarmReceiver.class); alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0); // Set the alarm to start at 8:30 a.m. Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.set(Calendar.HOUR_OF_DAY, 8); calendar.set(Calendar.MINUTE, 30); // setRepeating() lets you specify a precise custom interval--in this case, // 20 minutes. alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60 * 20, alarmIntent);
Decidir a precisão que o alarme precisa ter
Conforme descrito anteriormente, a escolha do tipo de alarme geralmente é a primeira etapa na
criação de um alarme. Outra distinção é a precisão do alarme. Para a maioria dos apps,
setInexactRepeating()
é a escolha certa. Quando você usa esse método, o Android sincroniza vários alarmes repetidos imprecisos e os dispara
ao mesmo tempo. Isso reduz o consumo da bateria.
Evite usar alarmes exatos, se possível. No entanto, para o app raro que tem requisitos de tempo
rígidos, é possível definir um alarme exato chamando
setRepeating()
.
Com setInexactRepeating()
,
não é possível especificar um intervalo personalizado da mesma forma que com
setRepeating()
.
É necessário usar uma das constantes de intervalo, por exemplo,
INTERVAL_FIFTEEN_MINUTES
,
INTERVAL_DAY
e assim por diante. Consulte AlarmManager
para ver a lista completa.
Cancelar um alarme
Dependendo do app, convém incluir a capacidade de cancelar o alarme.
Para cancelar um alarme, chame cancel()
no Alarm Manager, transmitindo a
PendingIntent
que você não quer mais
disparar. Por exemplo:
Kotlin
// If the alarm has been set, cancel it. alarmMgr?.cancel(alarmIntent)
Java
// If the alarm has been set, cancel it. if (alarmMgr!= null) { alarmMgr.cancel(alarmIntent); }
Iniciar um alarme quando o dispositivo é reiniciado
Por padrão, todos os alarmes são cancelados quando um dispositivo é desligado.
Para evitar que isso aconteça, você pode projetar seu app
para reiniciar automaticamente um alarme recorrente se o usuário reinicializar o dispositivo. Isso
garante que o AlarmManager
continue
realizando a tarefa sem que o usuário precise reiniciar manualmente o alarme.
Veja as etapas:
Defina a permissão
RECEIVE_BOOT_COMPLETED
no manifesto do app. Isso permite que o app receba oACTION_BOOT_COMPLETED
que é transmitido após a inicialização do sistema. Isso só funciona se o app já tiver sido iniciado pelo usuário pelo menos uma vez:<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
Implemente um
BroadcastReceiver
para receber a transmissão:Kotlin
class SampleBootReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (intent.action == "android.intent.action.BOOT_COMPLETED") { // Set the alarm here. } } }
Java
public class SampleBootReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { // Set the alarm here. } } }
Adicione o receptor ao arquivo de manifesto do app com um filtro de intent que filtre a ação
ACTION_BOOT_COMPLETED
:<receiver android:name=".SampleBootReceiver" android:enabled="false"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"></action> </intent-filter> </receiver>
No manifesto, o receptor de inicialização está definido como
android:enabled="false"
. Isso significa que o receptor não será chamado, a menos que o aplicativo o ative explicitamente. Isso evita que o receptor de inicialização seja chamado desnecessariamente. Você pode ativar um receptor (por exemplo, se o usuário definir um alarme) da seguinte maneira:Kotlin
val receiver = ComponentName(context, SampleBootReceiver::class.java) context.packageManager.setComponentEnabledSetting( receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP )
Java
ComponentName receiver = new ComponentName(context, SampleBootReceiver.class); PackageManager pm = context.getPackageManager(); pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
Depois de ativar o receptor dessa forma, ele permanecerá ativado, mesmo que o usuário reinicie o dispositivo. Em outras palavras, a ativação do receptor programaticamente modifica a configuração do manifesto, mesmo em reinicializações. O receptor permanecerá ativado até que o app o desative. Você pode desativar um receptor (por exemplo, se o usuário cancelar um alarme) da seguinte maneira:
Kotlin
val receiver = ComponentName(context, SampleBootReceiver::class.java) context.packageManager.setComponentEnabledSetting( receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP )
Java
ComponentName receiver = new ComponentName(context, SampleBootReceiver.class); PackageManager pm = context.getPackageManager(); pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
Invocar alarmes enquanto o dispositivo está no modo Soneca
Dispositivos com o Android 6.0 (API de nível 23) oferecem suporte ao modo Soneca, que ajuda a prolongar a duração da bateria. Os alarmes não são disparados quando o dispositivo está no modo Soneca. Todos os alarmes programados são adiados até que o dispositivo saia desse modo. Se você precisar concluir o trabalho mesmo quando o dispositivo estiver inativo, há várias opções disponíveis:
Defina um alarme exato.
Use a API WorkManager, que foi criada para executar trabalhos em segundo plano. Você pode indicar que o sistema precisa acelerar seu trabalho para que ele seja concluído o mais rápido possível. Para saber mais, consulte Programar tarefas com o WorkManager
Práticas recomendadas
Cada escolha que você faz ao criar um alarme recorrente pode ter consequências na forma como o app usa (ou abusa) os recursos do sistema. Por exemplo, imagine um app conhecido que sincroniza com um servidor. Se a operação de sincronização for baseada no horário do relógio e todas as instâncias do app forem sincronizadas às 23h, a carga no servidor poderá resultar em alta latência ou até mesmo "negação de serviço". Siga estas práticas recomendadas para o uso de alarmes:
Adicione aleatoriedade (instabilidade) a todas as solicitações de rede acionadas como resultado de um alarme recorrente:
Faça qualquer trabalho local quando o alarme for acionado. "Trabalho local" significa qualquer coisa que não chegue a um servidor ou exija os dados dele.
Ao mesmo tempo, programe o alarme que contém as solicitações de rede para disparar em um período aleatório.
Mantenha a frequência do alarme em um nível mínimo.
Não ative o dispositivo desnecessariamente. Esse comportamento é determinado pelo tipo de alarme, conforme descrito em Escolher um tipo de alarme.
Não faça com que o horário de acionamento do alarme seja mais preciso do que o necessário.
Use
setInexactRepeating()
em vez desetRepeating()
. Quando você usa osetInexactRepeating()
, o Android sincroniza alarmes recorrentes de vários apps e os aciona ao mesmo tempo. Isso reduz o número total de vezes que o sistema precisa ativar o dispositivo, reduzindo o consumo da bateria. A partir do Android 4.4 (nível 19 da API), todos os alarmes recorrentes são alarme impreciso. Embora osetInexactRepeating()
seja uma melhoria em relação aosetRepeating()
, ele ainda poderá sobrecarregar um servidor se todas as instâncias de um app chegarem ao servidor ao mesmo tempo. Portanto, para solicitações de rede, adicione alguma aleatoriedade aos seus alarmes, conforme discutido anteriormente.Evite basear seu alarme na hora do relógio, se possível.
Alarmes recorrentes baseados em um gatilho preciso não funcionam bem. Use
ELAPSED_REALTIME
, se possível. Os diferentes tipos de alarme são descritos em mais detalhes na seção a seguir.