usando tutorial studio notification manager developer android alarmmanager android-6.0-marshmallow

android - studio - tutorial alarmmanager



setExactAndAllowWhileIdle: no es exacto como referencia de desarrollador (5)

Entonces, ¿cómo puedo lograr una alarma exacta con AlarmManager en 6.0?

Puede probar setAlarmClock() , ya que AFAIK no se ve afectado por el modo Doze. De lo contrario, AlarmManager no es una opción viable para usted. Incluso tener su aplicación en la lista blanca de optimización de la batería no ayudará, ya que el comportamiento de AlarmManager no cambia en función de la lista blanca.

Puede usar GCM, ya que un mensaje de alta prioridad debería darle la oportunidad de alertar al usuario. Esto, por supuesto, requiere conectividad de red.

La única solución fuera de línea que conozco, y que estoy probando actualmente, es hacer que el usuario agregue su aplicación a la lista blanca de optimización de la batería, luego use un servicio en primer plano (para tratar de mantener su proceso), un servicio ScheduledExecutorService (para el tiempo) y un WakeLock parcial (para mantener la CPU encendida). Esto será bastante devastador para la batería del usuario.

AlarmManager en API19 tiene el método setExact () para establecer una alarma exacta.

Medios exactos -> Si configuro una alarma a las 2:01 pm, se activará a las 2:01 pm

En API 23 - Marhsmwallow (6.0) hay un nuevo método setExactAndAllowWhileIdle () , pero a partir de la referencia no es EXACTO porque se activará solo cada minuto y en modo inactivo de baja potencia solo cada 15 minutos .

¡Exacto! = Cada 15 minutos :-)

Entonces, ¿cómo puedo lograr una alarma exacta con AlarmManager en 6.0 ?

Si un usuario agrega un recordatorio o una cita de calendario y desea ser informado 10 minutos antes del evento, debe mostrar la alarma EXACTA 10 minutos antes del evento. Con setExactAndAllowWhileIdle () parece que esto no es posible.

Enlace de referencia: http://developer.android.com/reference/android/app/AlarmManager.html#setExactAndAllowWhileIdle(int, long, android.app.PendingIntent)


¡Aquí está mi discusión con Ian Lake en Google+!

setExactAndAllowWhileIdle () es exacto y debería funcionar. El marco de tiempo de 15 minutos es incorrecto en el documento de Java.


El uso de setExactAndAllowWhileIdle () para una alarma de una sola vez se disparará exactamente en el momento dado, incluso en modo inactivo Doze. Entonces este es probablemente el camino a seguir.

Los problemas comienzan si desea repetir la alarma a una velocidad de <15 min (o configurar cualquier otra a una hora <15 min de distancia de la última) , ya que esto no funcionará en modo inactivo Doze, donde tales alarmas son forzadas a los siguientes 15 minutos o se ejecutan cuando comienza el mantenimiento inactivo, que ocurre durante unos diez minutos primero después de 1 hora, luego después de otras 2 horas, luego después de otras 4 horas y así sucesivamente.

- EDITAR -

A partir de hoy 17 de noviembre, Dianne Hackborn escribe en los comentarios de esta publicación : " Por lo que vale, el tiempo mínimo entre las alarmas inactivas cambiará a 9 minutos en algún momento relativamente pronto (incluso en dispositivos que ejecutan las versiones actuales de Marshmallow) " .

Sin embargo, esto no cambia nada fundamentalmente.


Estaba tratando de crear un sistema de automatización que se ejecuta en segundo plano. Mi rango de frecuencia fue entre 1-15 minutos. Mi deseo no era utilizar un servicio en primer plano. Al observar el nombre del método "setExactAndAllowWhileIdle", pensé que sí, es seguro usar alarmas que suenan una sola vez, y programar la siguiente cuando haya terminado.

Sin embargo, no pude encontrar una manera de ejecutar código en modo de reposo con alarmas que se ejecutan con más frecuencia que 15 minutos. En cambio, elijo iniciar un servicio en primer plano cuando se activa el modo de reposo y detener ese servicio en primer plano cuando se despierta el teléfono. El usuario no verá su notificación de primer plano mientras usa su teléfono. No me importan mucho los que están en modo de reposo.

PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if(intent.getAction().equals("android.os.action.DEVICE_IDLE_MODE_CHANGED")){ if (pm.isDeviceIdleMode()) { //startAutomationForegroundService(); } else { //stopAutomationForegroundService(); return; } AutomationReceiver.completeWakefulIntent(intent); return; } }

Debe registrar el filtro de intención "android.os.action.DEVICE_IDLE_MODE_CHANGED" en su WakefulBroadcastReceiver. El cuidado de ponerlo en manifiesto puede no ayudar.


He descubierto que hasta ahora la mejor opción es usar un SyncAdapter que extienda AbstractThreadedSyncAdapter. Lo programo para seguir ejecutando automáticamente mi código en el intervalo requerido:

ContentResolver.setSyncAutomatically(account, AUTHORITY, true); ContentResolver.addPeriodicSync(account, AUTHORITY, settingsBundle, syncInterval);