setExactAndAllowWhileIdle – no es exacto como referencia de desarrollador

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 p.m.

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 EXACTAMENTE 10 minutos antes del evento. Con setExactAndAllowWhileIdle () esto parece que no es posible.

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

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

Le invitamos a 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.

Le invitamos a 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 actualmente estoy probando, 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 el proceso), un ScheduledExecutorService (para el tiempo) y un WakeLock parcial (para mantener la CPU encendida). Esto será bastante devastador para la batería del usuario.

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

Los problemas comienzan, si desea repetir la alarma a una velocidad <15 min (o configurar cualquier otra a la vez <15 minutos de la última) , ya que esto no funcionará en el modo inactivo Doze, donde tales alarmas son forzadas a los siguientes 15 minutos o se ejecutan cuando se inicia el mantenimiento inactivo, que ocurre durante aproximadamente 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 del día de hoy 17 de noviembre, Dianne Hackborn escribe en los comentarios de este Post : ” 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 con las versiones actuales de Marshmallow)

Sin embargo, esto no cambia nada fundamentalmente.

¡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.

enter image description here

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

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

Estaba intentando crear un sistema de automatización ejecutándose en segundo plano. Mi rango de frecuencia fue entre 1-15 minutos. Mi deseo no era usar un servicio de primer plano. Al ver el nombre del método “setExactAndAllowWhileIdle”, pensé que sí, es seguro ir con alarmas de una sola vez, progtwigr el siguiente cuando haya terminado.

Sin embargo, no pude encontrar una forma de ejecutar código en modo dormido 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 dormitar y detener ese servicio en primer plano cuando el teléfono se activa. El usuario no verá su notificación en primer plano mientras usa su teléfono. No me importan mucho los que están en modo dormido.

 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. Cuidar ponerlo en manifiesto puede no ser de ayuda.