Cómo programar alarmas

Alarmas (según el AlarmManager clase) te brindan una forma de realizar en tiempo real fuera del ciclo de vida de tu aplicación. Por ejemplo, podrías usar una alarma para iniciar una operación prolongada, como como iniciar un servicio una vez al día para descargar el pronóstico del tiempo.

Las alarmas tienen las siguientes características:

  • Te permiten activar intents en horas o intervalos determinados.

  • Puedes usarlos junto con receptores de emisión para programar trabajos o WorkRequests para realizar otras las operaciones.

  • Funcionan fuera de tu aplicación, por lo que puedes usarlas para activar eventos o acciones incluso cuando la app no se está ejecutando y si el dispositivo en sí está dormida.

  • Te ayudan a minimizar los requisitos de recursos de tu app. Puedes programar operaciones sin depender de temporizadores o ejecutar servicios de forma continua.

Cómo establecer una alarma inexacta

Cuando una app establece una alarma inexacta, el sistema la emite en algún momento en el futuro. Las alarmas inexactas brindan algunas garantías sobre la sincronización la entrega de la alarma y, al mismo tiempo, se respetan las restricciones de ahorro de batería, Descanso

Los desarrolladores pueden aprovechar las siguientes garantías de la API para personalizar los tiempos de entrega de alarmas inexactas.

Cómo activar una alarma después de una hora específica

Si tu app llama a set(), setInexactRepeating() o setAndAllowWhileIdle(), la alarma nunca se activa antes de la hora de activación proporcionada.

En Android 12 (nivel de API 31) y versiones posteriores, el sistema invoca la alarma en un plazo de una hora a partir del tiempo de activación proporcionado, a menos que haya restricciones de ahorro de batería en efecto, como el ahorro de batería o Descanso.

Mostrar una alarma durante un período determinado

Si la app llama a setWindow(), la alarma nunca sonará antes del horario indicado. tiempo de activación. A menos que se apliquen restricciones de ahorro de batería, la alarma se entregados dentro del período especificado, a partir del activador determinado tiempo.

Si tu app está orientada a Android 12 o versiones posteriores, el sistema puede retrasar la invocación de una alarma inexacta con ventana de tiempo por al menos 10 minutos. Para Por este motivo, los valores del parámetro windowLengthMillis en 600000 se ajustan a 600000

Publicar una alarma que se repite en intervalos aproximadamente regulares

Si tu app llama a setInexactRepeating(), el sistema invoca varias alarmas:

  1. La primera alarma suena dentro del período especificado, a partir de la hora de activación determinada.
  2. Por lo general, las alarmas posteriores suenan después de que transcurre el período especificado. El tiempo entre dos invocaciones consecutivas de la alarma puede variar.

Cómo establecer una alarma exacta

El sistema invoca una alarma exacta en un momento preciso en el futuro.

La mayoría de las apps pueden programar tareas y eventos con alarmas inexactas para hacer lo siguiente: completan varios casos de uso comunes. Si la funcionalidad principal de tu app depende de una alarma con una hora precisa, como una app de alarma o de calendario, está bien usar una alarma exacta.

Casos de uso que podrían no exigir alarmas exactas

En la siguiente lista, se muestran los flujos de trabajo comunes que pueden no requerir una alarma exacta:

Programa operaciones de tiempo durante el ciclo de vida de tu app
La clase Handler incluye varias prácticas recomendadas para manejar las operaciones de sincronización, como hacer un trabajo cada n segundos, mientras la app está activa: postAtTime() y postDelayed(). Ten en cuenta que estas APIs dependen del tiempo de actividad del sistema y no del tiempo real.
Tarea en segundo plano programada, por ejemplo, actualizar la app y subir registros
WorkManager proporciona una forma de programar tareas periódicas sujetas a horarios específicos. Puedes proporcionar un intervalo de repetición y flexInterval (15 minutos como mínimo) para definir el entorno de ejecución detallado para el trabajo.
Acción especificada por el usuario que debe ocurrir después de un tiempo específico (incluso si el sistema está inactivo)
Usa una alarma inexacta. Específicamente, llama a setAndAllowWhileIdle().
Acción especificada por el usuario que debe ocurrir después de un tiempo específico
Usa una alarma inexacta. Específicamente, llama set()
Acción especificada por el usuario que puede ocurrir dentro de un período especificado
Usa una alarma inexacta. Específicamente, llama setWindow() Ten en cuenta que, si tu app se orienta a Android 12 o versiones posteriores, la duración mínima permitida del período es de 10 minutos.

Formas de establecer una alarma exacta

Tu app puede establecer alarmas exactas con uno de los siguientes métodos. Estos métodos se ordenan de modo que las que están más cerca de la parte inferior de la lista publiquen más tareas urgentes, pero demandan más recursos del sistema.

setExact()

Invoca una alarma en un momento casi preciso en el futuro, siempre que no haya otras medidas para ahorrar batería en efecto.

Usa este método para establecer alarmas exactas, a menos que el trabajo de tu app urgentes para el usuario.

setExactAndAllowWhileIdle()

Invocar una alarma casi en un momento preciso en el futuro, incluso si ahorras batería medidas de seguridad estén vigentes.

setAlarmClock()

Invoca una alarma en un momento preciso en el futuro. Como las alarmas son altamente visible para los usuarios, el sistema nunca ajusta su tiempo de entrega. El el sistema identifica estas alarmas como las más críticas y deja las modos si es necesario para entregar las alarmas.

Consumo de recursos del sistema

Cuando el sistema activa alarmas exactas que establece la app, el dispositivo consume una gran cantidad de recursos, como la duración de batería, en especial si está en un modo de ahorro de energía. Además, el sistema no puede agrupar en lotes estas solicitudes con facilidad para usar los recursos de manera más eficiente.

Te recomendamos crear una alarma inexacta siempre que como sea posible. Para realizar trabajos más largos, programarlos con WorkManager o JobScheduler desde el BroadcastReceiver de tu alarma. Para realizar un trabajo mientras que el dispositivo esté en Descanso, crea una alarma inexacta usando setAndAllowWhileIdle(), y comenzar un trabajo con la alarma.

Declara el permiso adecuado de alarmas exactas

Si tu app se orienta a Android 12 o versiones posteriores, debes obtener el acceso especial de apps a "Alarmas y recordatorios". Para hacerlo, declara el SCHEDULE_EXACT_ALARM permiso en el archivo de manifiesto de tu app, como se muestra en el siguiente fragmento de código:

<manifest ...>
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
    <application ...>
        ...
    </application>
</manifest>

Si tu app se orienta a Android 13 (nivel de API 33) o versiones posteriores, tienes la opción de declarar el permiso SCHEDULE_EXACT_ALARM o el permiso USE_EXACT_ALARM.

<manifest ...>
    <uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
    <application ...>
        ...
    </application>
</manifest>

Si bien los permisos SCHEDULE_EXACT_ALARM y USE_EXACT_ALARM señalan las mismas capacidades, se otorgan de forma diferente y admiten distintas para cada caso de uso. Tu app debe usar alarmas exactas y declarar cualquiera de ellas los permisos SCHEDULE_EXACT_ALARM o USE_EXACT_ALARM, solo si un permiso en tu app requiere acciones con tiempos precisos.

USE_EXACT_ALARM

SCHEDULE_EXACT_ALARM

  • Otorgado por el usuario
  • Conjunto más amplio de casos de uso
  • Las apps deben confirmar que no se revocó el permiso

El permiso SCHEDULE_EXACT_ALARM no se otorga de forma previa a instalaciones nuevas de apps orientadas a Android 13 (nivel de API 33) y versiones posteriores. Si un usuario transfiere datos de la app a un dispositivo que ejecuta Android 14 mediante una operación de copia de seguridad y restablecimiento, se rechazará el permiso SCHEDULE_EXACT_ALARM en el dispositivo nuevo. Sin embargo, si una app existente ya tiene este permiso, se otorgará de forma previa cuando la se actualiza a Android 14.

Nota: Si la alarma exacta se configura con un objeto OnAlarmListener, como con la API de setExact, no se requiere el permiso SCHEDULE_EXACT_ALARM.

Cómo usar el permiso SCHEDULE_EXACT_ALARM

A diferencia de USE_EXACT_ALARM, el usuario debe otorgar el permiso SCHEDULE_EXACT_ALARM. Tanto el usuario como el sistema pueden revocar el SCHEDULE_EXACT_ALARM.

Para verificar si se otorgó el permiso a tu app, llama a canScheduleExactAlarms() antes de intentar establecer una alarma exacta. Cuando se revoca el permiso SCHEDULE_EXACT_ALARM para tu app, esta se detiene y se cancelan todas las alarmas exactas futuras. Esto también significa que el valor devuelto por canScheduleExactAlarms() sigue siendo válido durante todo el ciclo de vida de tu app.

Cuando se le otorga a la app el permiso SCHEDULE_EXACT_ALARMS, el sistema le envía la emisión ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED. Tu app debe implementar una transmisión receptor que hace lo lo siguiente:

  1. Confirma que la app todavía tenga el acceso especial de apps. Para ello, llama a canScheduleExactAlarms(). Esta verificación protege a tu app contra el caso en el que el usuario le otorga la permiso y lo revoca casi inmediatamente después.
  2. Reprograma las alarmas exactas que necesita la app, en función de su estado actual. Esta lógica debería ser similar a lo que hace la app cuando recibe la emisión ACTION_BOOT_COMPLETED.

Solicita a los usuarios que otorguen el permiso SCHEDULE_EXACT_ALARM

La opción se denomina &quot;Permitir configuración de alarmas y recordatorios&quot;
Figura 1: Página de acceso especial a "Alarmas y recordatorios" en la configuración del sistema, en la que los usuarios pueden permitir que la app establezca alarmas exactas.

Si es necesario, puedes dirigir a los usuarios a la sección Alarmas y de recordatorios en el sistema de seguridad, como se muestra en la Figura 1. Para ello, completa los siguientes pasos:

  1. En la IU de la app, explícale al usuario por qué la app debe programar alarmas exactas.
  2. Invoca un intent que incluya la acción de intent ACTION_REQUEST_SCHEDULE_EXACT_ALARM.

Cómo establecer una alarma repetitiva

Las alarmas repetidas permiten que el sistema notifique a tu app en un programa recurrente.

Una alarma mal diseñada puede agotar la batería y generar una carga significativa servidores. Por este motivo, en Android 4.4 (nivel de API 19) y versiones posteriores, todas las alarmas repetitivas son alarmas inexactas.

Una alarma repetitiva tiene las siguientes características:

  • Un tipo de alarma. (Para obtener más información, consulta Cómo elegir un tipo de alarma)

  • Una hora de activación Si la hora de activación que especificas es en el pasado, la alarma se activa de inmediato.

  • El intervalo de la alarma Por ejemplo, una vez al día, cada hora o cada 5 minutos.

  • Un intent pendiente que se activa cuando se activa la alarma Cuando configuras una segunda alarma que usa el mismo intent pendiente, esta reemplaza a la alarma original.

Para cancelar un PendingIntent(), pasa FLAG_NO_CREATE a PendingIntent.getService() para obtener una instancia del intent (si existe). 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);
}

Cómo elegir un tipo de alarma

Una de las primeras consideraciones al usar una alarma repetitiva es el tipo.

Hay dos tipos de relojes generales para las alarmas: "tiempo real transcurrido" y "reloj en tiempo real" (RTC). El tiempo real transcurrido usa el "tiempo desde que se inició el sistema" como referencia, y el reloj en tiempo real usa la hora UTC (reloj de pared). Esto significa que tiempo real transcurrido es adecuado para establecer una alarma basada en el paso del tiempo (por ejemplo, una alarma que se activa cada 30 segundos), ya que no se ve afectada por a la zona horaria o a la configuración regional. El tipo de reloj en tiempo real es más adecuado para las alarmas que dependen de la configuración regional actual.

Ambos tipos tienen una versión de "activación", que indica que se debe activar la CPU del dispositivo si la pantalla está apagada. De esta manera, se garantiza que la alarma se active a la hora programada. Esto es útil si tu app tiene una dependencia de tiempo. Por ejemplo, si tiene un período limitado para realizar una operación específica. Si no usas la versión de activación de tu tipo de alarma, entonces todas las alarmas repetitivas se activarán cuando vuelva a activarse el dispositivo.

Si solo necesitas que tu alarma se active en un intervalo determinado (por ejemplo, cada media hora), usa uno de los tipos de tiempo real transcurrido. En general, este es la mejor opción.

Si necesitas que la alarma se active a una hora determinada del día, elige una de los tipos de reloj en tiempo real. Sin embargo, ten en cuenta que este enfoque puede tienen algunas desventajas. Es posible que la app no se traduzca bien a otras configuraciones regionales y, si el usuario cambia la configuración de hora del dispositivo, podría provocar un comportamiento inesperado en la app. El uso de un tipo de alarma de reloj en tiempo real tampoco se ajusta bien, como se mencionó anteriormente. Te recomendamos que uses una alarma de "tiempo real transcurrido" si es posible.

A continuación, se muestra una lista de los tipos:

  • ELAPSED_REALTIME: Activa el intent pendiente según la cantidad de tiempo que transcurrió desde que se inició el dispositivo se inició, pero no activa el dispositivo. El tiempo transcurrido incluye cualquier intervalo de tiempo durante el cual estuvo inactivo el dispositivo.

  • ELAPSED_REALTIME_WAKEUP: Despierta el dispositivo y activa el intent pendiente después de que transcurrió la cantidad de tiempo especificada desde que se inició el dispositivo.

  • RTC: Activa el intent pendiente a la hora especificada, pero no activa el dispositivo.

  • RTC_WAKEUP: Activaciones activar el dispositivo para activar el intent pendiente en el momento especificado

Ejemplos de alarmas de tiempo real transcurrido

Estos son algunos ejemplos del uso de ELAPSED_REALTIME_WAKEUP.

Activa el dispositivo para activar la alarma en 30 minutos, y cada 30 minutos después de la primera activación:

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);

Activa el dispositivo para activar una única alarma (no repetitiva) en un 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);

Ejemplos de alarmas de reloj en tiempo real

Estos son algunos ejemplos de cómo usar RTC_WAKEUP

Activar el dispositivo para activar la alarma aproximadamente a las 2:00 p.m. repetirse una vez al día a la misma hora:

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);

Activa el dispositivo para activar la alarma precisamente a las 8:30 a.m. y, desde entonces, cada 20 minutos:

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);

Cómo decidir qué tan precisa debe ser la alarma

Como se describió anteriormente, elegir el tipo de alarma suele ser el primer paso para crear una. Otra distinción es qué tan precisa debe ser. Para la mayoría de las apps, setInexactRepeating() es la opción correcta. Cuando usas este método, Android sincroniza varias alarmas y activaciones inexactas al mismo tiempo. De esta manera, se reduce el consumo de batería.

Si es posible, evita usar alarmas exactas. Sin embargo, en el caso de una app particular que tenga requisitos de tiempo rígidos, puedes establecer una alarma exacta llamando a setRepeating().

Con setInexactRepeating(), no puede especificar un intervalo personalizado como lo hace con setRepeating() Debes usar una de las constantes de intervalo, como INTERVAL_FIFTEEN_MINUTES, INTERVAL_DAY, etcétera. Consulta AlarmManager para obtener la lista completa.

Cancela una alarma

Según tu app, es posible que quieras incluir la capacidad para cancelar la alarma. Para cancelar una alarma, llama a cancel() en el Administrador de alarmas y pasa el PendingIntent que ya no quieras activar. Por ejemplo:

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);
}

Cómo iniciar una alarma cuando se reinicia el dispositivo

De manera predeterminada, todas las alarmas se cancelan cuando se apaga un dispositivo. Para evitar que esto suceda, puedes diseñar tu aplicación para reiniciar automáticamente una alarma recurrente si el usuario reinicia el dispositivo De esta manera, se garantiza que el AlarmManager siga realizando las tareas sin que el usuario deba restablecer la alarma manualmente.

A continuación, se indican los pasos que debes seguir:

  1. Establece el elemento RECEIVE_BOOT_COMPLETED. permiso en el manifiesto de tu aplicación. De esta manera, tu app podrá recibir el ACTION_BOOT_COMPLETED que se transmite una vez que el sistema finaliza el inicio (solo funciona si el usuario ya inició la app al menos una vez):

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
  2. Implementa un BroadcastReceiver para recibir la transmisión:

    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.
            }
        }
    }
    
  3. Agrega el receptor al archivo de manifiesto de tu app con un filtro de intents que filtros en ACTION_BOOT_COMPLETED acción:

    <receiver android:name=".SampleBootReceiver"
            android:enabled="false">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"></action>
        </intent-filter>
    </receiver>

    Ten en cuenta que, en el manifiesto, el receptor de inicio está configurado para android:enabled="false" Esto significa que el receptor a menos que la aplicación lo habilite explícitamente. De esta manera, evitas que se llame innecesariamente al receptor de inicio. Puedes habilitar un receptor (por ejemplo, si el usuario establece una alarma) de la siguiente manera:

    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);
    

    Una vez que habilites el receptor de esta manera, permanecerá habilitado aunque el usuario reinicie el dispositivo. En otras palabras, habilitar de manera programática el receptor anula la configuración del manifiesto, incluso luego de un reinicio. El receptor permanecerá habilitado hasta que tu app la inhabilite. Para inhabilitar un receptor (por ejemplo, si el usuario cancela una alarma), haz lo siguiente:

    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 alarmas mientras el dispositivo está en modo Descanso

Dispositivos compatibles con Android 6.0 (nivel de API 23) Descanso general, que ayuda a extender la duración de batería del dispositivo. Las alarmas no se activan cuando el dispositivo está en el modo Descanso. Cualquier alarma programada se pospone hasta que el dispositivo salga de este modo. Si necesitas completar el trabajo incluso cuando el dispositivo está inactivo, hay varias opciones disponibles:

  • Establece una alarma exacta.

  • Usa la API de WorkManager, que se creó para realizar el trabajo en segundo plano. Puedes indicar que el sistema debería acelerar tu trabajo para que el trabajo termine lo antes posible. Para obtener más información, consulta Cómo programar tareas con WorkManager.

Prácticas recomendadas

Cada decisión que tomes al diseñar tu alarma repetitiva puede afectar la manera en que tu app usa los recursos del sistema (o abusa de ellos). Por ejemplo, imagina un app popular que se sincroniza con un servidor. Si la operación de sincronización se basa en el reloj y cada instancia de la aplicación se sincroniza a las 11:00 p.m., la carga del un servidor web podría generar una latencia alta o incluso “denegación del servicio”. Sigue estas prácticas recomendadas para usar las alarmas:

  • Agrega aleatorización (jitter) en cualquier solicitud de red que se active a causa de una alarma repetitiva:

    • Realiza las tareas locales cuando se active la alarma. "Trabajo local" significa todo lo que no llegue a un servidor ni requiera los datos de este.

    • Al mismo tiempo, programa la alarma que contenga las solicitudes de red para que se active en algún momento aleatorio.

  • Mantén la frecuencia de la alarma al mínimo.

  • No actives el dispositivo innecesariamente (este comportamiento lo determina la según se describe en Cómo elegir un tipo de alarma).

  • No hagas que el tiempo de activación de tu alarma sea más preciso de lo necesario.

    Usa setInexactRepeating() en lugar de setRepeating(). Cuando usas setInexactRepeating(), Android sincroniza las alarmas repetitivas de varias apps y las activa al mismo tiempo. De esta manera, se reduce la cantidad total de veces que el sistema debe activar el dispositivo, lo que minimiza el consumo de la batería. A partir de Android 4.4 (nivel de API 19), todas las alarmas repetitivas son una alarma inexacta. Ten en cuenta que, si bien setInexactRepeating() es una mejora con respecto a setRepeating(), de igual manera puede sobrecargar el servidor si cada instancia de una app interactúa con él al mismo tiempo. Por lo tanto, en el caso de las solicitudes de red, agrega aleatorización a tus alarmas, como se explicó anteriormente.

  • Si es posible, evita basar tu alarma en la hora del reloj.

    Las alarmas repetitivas que se basan en una hora de activación precisa no se escalan bien. Usa ELAPSED_REALTIME si puedes. La alarma diferente se describen con más detalle en la siguiente sección.