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.

  • Ayudan a minimizar los requisitos de recursos de tu app. Puedes programar sin depender de temporizadores ni servicios en ejecución 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 APIs para personalizar los tiempos de entrega de alarmas inexactas.

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

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

En Android 12 (nivel de API 31) y versiones posteriores, el sistema invoca la alarma dentro de uno hora del tiempo de activación proporcionado, a menos que se apliquen restricciones 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 se orienta a Android 12 o versiones posteriores, el sistema puede retrasar la invocación de una alarma inexacta con ventana de tiempo durante 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 la app llama a setInexactRepeating(), el sistema invoca varias alarmas:

  1. La primera alarma suena dentro del período especificado, a partir de la tiempo de activación determinado.
  2. Por lo general, las alarmas posteriores se activan después del período especificado. el tiempo transcurrido. 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 del 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 el componente central de tu app depende de una alarma con una hora precisa, por ejemplo, para una aplicación de alarma o una app 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 la 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 en tiempo real.
Tarea en segundo plano programada, por ejemplo, actualizar la app y subir registros
WorkManager proporciona una forma de programar sesiones periódicas urgentes. del trabajo. 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 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 específico
Usa una alarma inexacta. Específicamente, llama setWindow() Ten en cuenta que, si tu app está orientada a Android 12 o versiones posteriores, la versión más pequeña la duración 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 manera 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()

Invocar una alarma casi en un momento preciso en el futuro, siempre que otros las medidas de ahorro de batería no están vigentes.

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

setExactAndAllowWhileIdle()

Invocar una alarma en un momento casi 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 tu app, el dispositivo consume una gran cantidad de recursos, como la duración de la batería, especialmente 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 forma más eficiente.

Te recomendamos crear una alarma inexacta siempre que como sea posible. Para realizar un trabajo más largo, prográmalo usando WorkManager o JobScheduler de la alarma BroadcastReceiver 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 la app se orienta a Android 12 o versiones posteriores, debes obtener la "Alarmas y recordatorios" acceso especial de apps. 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, puedes hacer lo siguiente: declarar SCHEDULE_EXACT_ALARM o USE_EXACT_ALARM permiso.

<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 les otorgan diferentes 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 la app datos a un dispositivo con Android 14 mediante una operación de copia de seguridad y restablecimiento, el 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 OnAlarmListener objeto, como con el setExact API, el permiso SCHEDULE_EXACT_ALARM no es necesario.

Cómo usar el permiso SCHEDULE_EXACT_ALARM

A diferencia de USE_EXACT_ALARM, el permiso SCHEDULE_EXACT_ALARM debe otorgada por el usuario. 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 habilita el permiso SCHEDULE_EXACT_ALARM se revoca para tu app, esta se detiene y todas las alarmas exactas futuras se cancelan. 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 otorga el permiso SCHEDULE_EXACT_ALARMS a tu app, el el sistema le envía el ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED transmisión. Tu app debe implementar una transmisión receptor que hace lo lo siguiente:

  1. Confirma que tu app todavía tiene 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 de forma recurrente de un proyecto.

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 el tiempo 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 estableces un que usa el mismo intent pendiente, reemplaza a la alarma original.

Para cancelar un PendingIntent(), pasa FLAG_NO_CREATE para PendingIntent.getService() para obtener una instancia del intent (si existe) y, luego, pásalo a 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 sobre el uso de una alarma repetitiva es cuál es su tipo debe ser.

Hay dos tipos de reloj 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 y el reloj en tiempo real usa 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 "activación" versión, que indica que se active la CPU del dispositivo si la pantalla está apagada. Esto garantiza que la alarma se active a la hora programada. Esto es útil si tu app tiene una dependencia de tiempo. Por ejemplo, si incluye una ventana limitada para realizar una operación en particular. Si no usas activar una versión de tu tipo de alarma, todas las alarmas repetitivas se activarán la próxima vez que actives el dispositivo.

Si solo necesitas que la 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, se pueden producir comportamientos inesperados en tu app. El uso de un tipo de alarma de reloj en tiempo real tampoco escala bien, ya que que mencionamos anteriormente. Te recomendamos que uses una ventana de “tiempo real transcurrido” alarma si puedes.

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 El tiempo transcurrido incluye cualquier tiempo en el que el dispositivo estuvo inactivo.

  • ELAPSED_REALTIME_WAKEUP: Activa el dispositivo y activa el intent pendiente después de la duración especificada. transcurrió un tiempo desde el inicio del 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, cada 30 minutos después de eso:

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 cada 20 minutos Luego de esa fecha, ocurrirá lo siguiente:

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 creando una alarma. Otra distinción es la precisión con la que necesitas la alarma ser. Para la mayoría de las apps, setInexactRepeating() es la elecció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, para una app poco común que tiene fallas requisitos de tiempo, puedes establecer una alarma exacta llamando 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 ver 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, pasando el PendingIntent ya no quieres se dispare. 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 Esta garantiza que el elemento AlarmManager continuar realizando la tarea sin que el usuario deba reiniciar manualmente la alarma.

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. Esto permite que tu app reciba el ACTION_BOOT_COMPLETED que se transmite después de que el sistema termina de iniciarse (esto solo funciona si el el usuario ya la inició 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. Esto evita que las al receptor de inicio se llame innecesariamente. 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, incluso si el usuario reinicia 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. Puedes inhabilitar un receptor (por ejemplo, si el usuario cancela una alarma) de la siguiente manera:

    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 Modo Descanso Las alarmas programadas se aplazan hasta que el dispositivo sale del modo Descanso. 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 una alarma repetitiva puede tener consecuencias en la manera en que tu app usa (o abusa) de los recursos del sistema. 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 el servidor, lo que puede generar una latencia alta o incluso “denegación del servicio”. Sigue estas prácticas recomendadas para usar las alarmas:

  • Agregar aleatorización (jitter) a cualquier solicitud de red que se activa como resultado de una alarma repetida:

    • 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 activar en algún período 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 vez de setRepeating() Cuando usas setInexactRepeating(), Android sincroniza las alarmas repetitivas de varias apps y se activa al mismo tiempo. Esto reduce la cantidad total de veces que el sistema debe activar el del dispositivo y, por lo tanto, se reduce el consumo de la batería. A partir de Android 4.4 (nivel de API 19), todas las alarmas repetitivas son una alarma inexacta. Nota que mientras setInexactRepeating() es una mejora con respecto setRepeating(), puede sobrecargar un servidor si cada instancia de una app llega a él casi al mismo tiempo. Por lo tanto, para las solicitudes de red, agrega aleatorización las alarmas, como lo analizamos 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 que puedas. La alarma diferente se describen con más detalle en la siguiente sección.