Programar alarmes exatos não é permitido por padrão

Alarmes exatos são destinados a notificações pretendidas pelo usuário ou ações que precisam acontecer em um momento preciso.

A permissão SCHEDULE_EXACT_ALARM, apresentada no Android 12 para programar alarmes exatos em apps, não é mais concedida previamente à maioria dos apps recém-instalados destinados ao Android 13 e mais recentes. Em vez disso, ela é negada por padrão. Mesmo que o usuário transfira dados do app para um dispositivo com o Android 14 usando uma operação de backup e restauração, essa permissão ainda será negada. Se um app já tiver essa permissão, ela será concedida previamente quando o dispositivo upgrades para o Android 14.

A permissão SCHEDULE_EXACT_ALARM é necessária para iniciar alarmes exatos pelas APIs a seguir. Caso contrário, uma SecurityException será gerada.

As práticas recomendadas atuais para a permissão SCHEDULE_EXACT_ALARM ainda se aplicam, incluindo as seguintes:

Apps afetados

Se um dispositivo estiver executando o Android 14 ou mais recente, essa mudança vai afetar um app recém-instalado com as seguintes características:

  • É destinado ao Android 13 (nível 33 da API) ou mais recente.
  • Declara a permissão SCHEDULE_EXACT_ALARM no manifesto.
  • Não se enquadra em um cenário de isenção ou pré-concessão.
  • Não é um app de agenda ou alarme.

Os apps de calendário e alarme precisam declarar USE_EXACT_ALARM

Apps de agenda ou alarme precisam enviar lembretes, despertadores ou alertas quando o app não está mais em execução. Eles podem solicitar a permissão normal USE_EXACT_ALARM. A permissão USE_EXACT_ALARM será concedida na instalação, e esses apps poderão programar alarmes exatos, assim como apps com a permissão SCHEDULE_EXACT_ALARM.

Casos de uso que podem não exigir alarmes exatos

Como a permissão SCHEDULE_EXACT_ALARM agora é negada por padrão e o processo de concessão exige etapas extras dos usuários, é recomendável que os desenvolvedores avaliem os casos de uso e determinem se alarmes exatos ainda fazem sentido para eles.

A lista a seguir mostra fluxos de trabalho comuns que podem não exigir um alarme exato:

Programação de um trabalho repetido durante o ciclo de vida do app
O método set() é útil quando a tarefa precisa ter restrições em tempo real, como disparar às 14h amanhã ou em 30 minutos. Caso contrário, é recomendável usar os métodos postAtTime() ou postDelayed().
Trabalho programado em segundo plano, como atualizar o app e fazer upload de registros
O WorkManager oferece uma maneira de programar trabalhos periódicos com condição de tempo. É possível fornecer um intervalo de repetição mínimo de 15 minutos para definir o ambiente de execução granular para o trabalho.
O alarme precisa ser disparado em um horário aproximado enquanto o sistema está 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. A menor duração permitida da janela é de 10 minutos.

Etapas de migração para continuar usando alarmes exatos

No mínimo, os apps precisam conferir se têm a permissão antes de programar alarmes exatos. Se os apps não tiverem a permissão, eles precisarão invocar uma intent para solicitar ao usuário.

É o mesmo fluxo de trabalho padrão usado para solicitar uma permissão especial:

  1. Os apps precisam chamar AlarmManager.canScheduleExactAlarms() para confirmar se têm a permissão adequada.
  2. Se o app não tiver a permissão, invoque uma intent que inclua o ACTION_REQUEST_SCHEDULE_EXACT_ALARM e o nome do pacote do app para pedir que os usuários a concedam.

    Confira a decisão do usuário no método onResume() do app.

  3. Detecte as transmissões AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED que são enviadas quando o usuário concede a permissão.

  4. Se o usuário tiver concedido a permissão, o app poderá definir alarmes exatos. Se a permissão tiver sido negada, faça uma degradação suave da experiência no app para que ele funcione sem as informações protegidas pela permissão.

O snippet de código abaixo demonstra como conferir a permissão SCHEDULE_EXACT_ALARM:

val alarmManager: AlarmManager = context.getSystemService<AlarmManager>()!!
when {
   // If permission is granted, proceed with scheduling exact alarms.
   alarmManager.canScheduleExactAlarms() -> {
       alarmManager.setExact(...)
   }
   else -> {
       // Ask users to go to exact alarm page in system settings.
       startActivity(Intent(ACTION_REQUEST_SCHEDULE_EXACT_ALARM))
   }
}

Exemplo de código para conferir a permissão e processar as decisões do usuário em onResume():

override fun onResume() {
     
   if (alarmManager.canScheduleExactAlarms()) {
       // Set exact alarms.
       alarmManager.setExact(...)
   }
   else {
       // Permission not yet approved. Display user notice and revert to a fallback  
       // approach.
       alarmManager.setWindow(...)
   }
}

Faça uma degradação suave da negação de permissão

Alguns usuários não concederão a permissão. Nesse cenário, recomendamos que os apps façam uma degradação suave da experiência e ainda tentem fornecer a melhor experiência de usuário possível ao identificar os casos de uso.

Isenções

Estes tipos de apps sempre podem chamar os métodos setExact() ou setExactAndAllowWhileIdle():

  • Apps assinados com o certificado da plataforma.
  • Apps privilegiados.
  • Apps que estão na lista de permissões de energia (se o app atende aos requisitos, é possível solicitar a entrada na lista usando a ação ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS da intent).

Pré-concessões

  • Os detentores de papéis de SYSTEM_WELLBEING receberão a permissão SCHEDULE_EXACT_ALARM previamente.

Diretrizes de teste

Para testar essa mudança, desative a permissão de Alarmes e lembretes para o app na página Acesso especial para apps nas configurações do sistema (Configurações > Apps > Acesso especial para apps > Alarmes e lembretes) e observe o comportamento do seu app.