android - studio - tutorial alarmmanager
¿Cómo hacer que Alarm Manager funcione cuando Android 6.0 está en modo Doze? (3)
Soy un desarrollador de dos aplicaciones de reloj despertador en Google Play. Estoy tratando de hacer que funcionen con Android 6.0. Sin embargo, el modo Doze lo hace para que no suenen. Los puse en la lista blanca, puse un ícono de notificación en primer plano, no estoy seguro de qué más puedo hacer, cuando estoy en el modo Doze, las alarmas de Alarm Manager aún se ignoran. La aplicación Reloj (que es una aplicación Google Play en lugar de AOSP), sin embargo, es diferente. Cuando la alarma está activada en la aplicación Reloj, "paso de adb deviceidle" siempre leerá "activo" y nunca "inactivo", "inactivo" o cualquier otra cosa.
Es Android engañando aquí, dando a su propia aplicación más poder, también conocido como. "tirando una manzana"? ¿Están a punto de dejar de funcionar todas las aplicaciones de reloj despertador en Google Play? Algo preocupado aquí, estas son aplicaciones de calidad que cada una tomó un año de tiempo de desarrollo a tiempo parcial, y son grandes fuentes de ingresos para mí. Cualquier pista sobre cómo podría hacer que funcionen sería una gran ayuda.
Estableciendo la intención del AlarmManager:
Intent intent = new Intent(context, ReceiverAlarm.class);
if (android.os.Build.VERSION.SDK_INT >= 16) {
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
}
amSender = PendingIntent.getBroadcast(context, 1, intent, PendingIntent.FLAG_CANCEL_CURRENT); //FLAG_CANCEL_CURRENT seems to be required to prevent a bug where the intent doesn''t fire after app reinstall in KitKat
am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, scheduleToTime+1, amSender);
y la clase ReceiverAlarm:
public class ReceiverAlarm extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
if (wakeLock == null) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Theme.appTitle);
wakeLock.acquire();
}
X.alarmMaster.startRingingAlarm(true);
}
y las partes relevantes del método X.alarmMaster.startRingingAlarm ():
if (wakeLock == null) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Theme.appTitle);
wakeLock.acquire();
}
if (screenWakeLock == null) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
screenWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, Theme.appTitle+" scr");
screenWakeLock.acquire();
}
Intent alarmIntent = new Intent(Intent.ACTION_VIEW);
alarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
alarmIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
alarmIntent.setClass(context, ActivityAlarmAlarm.class);
context.startActivity(alarmIntent);
Algunos de los métodos se han pegado en línea para facilitar la lectura.
Doze y App Standby definitivamente cambian el comportamiento en lo que respecta a alarmas y wakelocks, ¡pero definitivamente no son el fin del mundo para ti!
¿Has intentado utilizar el método setAlarmclock()
lugar de set()
? Está diseñado específicamente para despertadores y es posible que pueda atravesar el sopor. Hay algunos comandos de adb que puede usar para poner un teléfono en modo dormido o en modo de espera de la aplicación manualmente: https://developer.android.com/preview/features/power-mgmt.html
Si eso no es capaz de reactivar su aplicación, existe el método seguro setExactAndAllowWhileIdle()
está diseñado para despertar al teléfono de la setExactAndAllowWhileIdle()
que setExactAndAllowWhileIdle()
. En el peor de los casos, puede reactivar su aplicación con este método y usar la activación para programar la próxima alarma.
Otra página que vale la pena leer es esta publicación de blog con su diagrama de flujo para el trabajo de fondo y las alarmas: https://plus.google.com/+AndroidDevelopers/posts/GdNrQciPwqo
Poner la aplicación en la lista blanca solo permite la red en modo dormido. AlarmManager no se ve afectado por la lista blanca.
Para el método setExactAndAllowWhileIdle (), compruebe la descripción siguiente del SDK. No despertará al teléfono de la siesta.
Cuando se envía la alarma, la aplicación también se agregará a la lista blanca temporal del sistema durante aproximadamente 10 segundos para permitir que esa aplicación adquiera cerraduras adicionales para completar su trabajo.
Quizás te ayude:
Si nuestra aplicación se dirige a un nivel de API inferior a 19 (KitKat), las alarmas programadas se ejecutarán exactamente a la hora de la alarma. Para las aplicaciones que se dirigen a KitKat o posterior, el programa se considera inexacto y el sistema puede reordenar o agrupar alarmas para minimizar los despertares y ahorrar batería.
Después del nivel API 23, el equipo de desarrollo de Android fue un poco más allá y se introdujo el modo Doze en el sistema Android para reducir el consumo de batería cuando el dispositivo se desenchufa del adaptador de alimentación, permanece inmóvil y el usuario no lo utiliza durante un largo período de tiempo. .
El sistema Doze intentará disminuir la frecuencia de activación del dispositivo difiriendo los trabajos en segundo plano, actualizaciones de red, sincronizaciones y nuestra preciosa alarma hasta que el dispositivo salga del modo Doze o se ejecute una ventana de mantenimiento recurrente para ejecutar trabajos pendientes, ciertas alarmas o sincronización con el red. Después de que se borre la ventana de mantenimiento, el dispositivo volverá a entrar en el modo Doze si no se usó mientras tanto:
El modo Doze puede afectar su aplicación y diferirá sus alarmas hasta que entre una ventana de mantenimiento, a menos que use los métodos setAndAllowWhileIdle () y setExactAndAllowWhileIdle () para permitir la ejecución de sus alarmas en un estado inactivo profundo.
Además, la cantidad de veces que se ejecuta la ventana de mantenimiento del modo Doze será menos frecuente en casos de inactividad a largo plazo, por lo que el impacto de este nuevo mecanismo en nuestra programación aumentará, causando más nervios impredecibles a la hora de la alarma.
Durante el modo dormido, las aplicaciones tampoco pueden acceder a la red, las WakeLocks se ignoran y las exploraciones con Wi-Fi no se ejecutan.
Si necesitamos una programación de precisión y está apuntando a Marshmallow o posterior, usaremos el nuevo método setExactAndAllowWhileIdle () introducido en el nivel 23 de la API:
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, pending);
Aviso :
El sistema Android tiene protección que evita el abuso de alarmas exactas que se activan con demasiada frecuencia. AlarmManager solo activa el dispositivo y envía una alarma por minuto, y en el modo de baja potencia puede ser tan bajo como uno cada 15 minutos.
Si su aplicación está orientada a una versión entre KitKat (nivel de API 19) y Marshmallow (nivel de API 23), el método setExact es suficiente para la precisión de tiempo:
am.setExact(AlarmManager.RTC_WAKEUP, time, pending);
Pero necesitaremos verificar que los métodos existan antes de tratar de llamarlo; de lo contrario, nuestra aplicación se bloqueará cuando se ejecute en niveles de API anteriores. Vamos a esbozar nuestro nuevo código de alarma exacta:
if (Build.VERSION.SDK_INT >= 23) {
// Wakes up the device in Doze Mode
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time,
pending);
} else if (Build.VERSION.SDK_INT >= 19) {
// Wakes up the device in Idle Mode
am.setExact(AlarmManager.RTC_WAKEUP, time, pending);
} else {
// Old APIs
am.set(AlarmManager.RTC_WAKEUP, time, pending);
}
Esto enviará nuestra alarma exactamente a la hora especificada en todas las plataformas.