Mi aplicación usa AlarmManager y ha estado funcionando desde hace 4 años. Pero noté que comenzó a fallar en algunos dispositivos.
Estoy bastante seguro de que el código es correcto (estoy usando WakefulBroadcastReceiver y setExactAndAllowWhileIdle para dispositivos con Doze) porque funciona perfectamente en dispositivos Nexus, pero falla en dispositivos de algunos fabricantes (Huawei, Xiaomi ...).
Los dispositivos Huawei, por ejemplo, tienen una especie de administrador de batería que mata las aplicaciones y, cuando se mata una aplicación, se cancelan las alarmas programadas. Por lo tanto, configurar una aplicación como "protegida" en el administrador de batería de Huawei resuelve el problema.
Pero recientemente noté que no funciona con más dispositivos: Xiaomi, Samsung (¿quizás esté relacionado con el nuevo "Smart Manager"?) ... Parece que este comportamiento se está convirtiendo en un estándar: matar aplicaciones en segundo plano.
¿Alguien sabe algo al respecto? ¿Alguna forma de garantizar que se active la alarma?
EDITAR: Este problema es causado por "ahorradores de batería" agregados por diferentes fabricantes. Más información aquí: https://dontkillmyapp.com/
fuente
Respuestas:
Estoy tratando de resolverlo desde hace varias semanas. No encontré nada. Huawei acaba de apagar todas las alarmas después de un tiempo. Si coloco la aplicación en la aplicación protegida en su ahorro de batería, no ayuda. Pero si cambio el nombre del paquete de mi aplicación para que contenga palabras como alarma, reloj o calendario, funciona de forma absolutamente normal como en cualquier otro dispositivo. No entiendo cómo Google puede otorgar una certificación para esta basura. Creo que los OEM no deberían modificar la plataforma central de esa manera. Entiendo que tienen su propio protector de batería que mata la aplicación después de un tiempo, cuando el usuario no la usa. Pero esto mata las alarmas también de las aplicaciones protegidas.
También ayuda setAlarmClock () para alarmas de tiempo exacto. Pero no es posible usar esto para pensamientos como la actualización de widgets.
Actualización: la protección por palabras clave de nombre de paquete ya no funciona en los dispositivos Huawei actuales, era cierto en 2017.
fuente
El problema es Smart Manager. Samsung tiene un administrador de batería que a veces impide que ciertas aplicaciones se ejecuten en segundo plano. Intentó "reanudar" al volver a la aplicación, pero la desactiva por completo o puede reanudarla cada 5 minutos aproximadamente (dependiendo de cómo la tenga Samsung).
Esto funcionaría en versiones de stock de Android, ya que no hay Samsung Manager. También puede instalar una versión personalizada de Android que tiene algunas características para habilitar SM (según la rom).
fuente
La mayoría de los dispositivos Android modernos vienen con una aplicación o mecanismo, que automáticamente intenta averiguar cómo ahorrar batería y, como resultado, puede acabar con ciertas aplicaciones de terceros. Esto puede resultar en la eliminación de tareas y trabajos programados (por ejemplo, las alarmas que no suenan, las notificaciones push no funcionan, etc.). En muchos casos, esto sucede de manera completamente independiente de los mecanismos de ahorro de batería de Android, en mi caso no pude hacer más optimización de la batería cuando detecto el modelo de algunos dispositivos, redirijo al usuario al administrador de inicio para incluir mi aplicación en la lista blanca
Encontraste en este enlace para cada modelo la intención que debes invocar https://android-arsenal.com/details/1/6771
fuente
Utilice AlarmManager para dispositivos <5.0 y JobScheduler para dispositivos 5.0+. No puedo decir con certeza que JobScheduler no se vea afectado por las travesuras del fabricante, pero me parecería mucho menos probable, dado que Android está tratando de alejar a las personas de AlarmManager y colocarlas en JobScheduler.
EDITAR: Google ha presentado una solución propia para este problema llamada WorkManager . Abstrae múltiples marcos de programación y utiliza el más apropiado para el dispositivo.
fuente
También tengo una aplicación que establece alarmas. La solución es usar AlarmManager.setAlarmClock () en api> = 21. Esto no se ve afectado por doze afaik y tiene la ventaja adicional de poner un icono de reloj de alarma en la bandeja del sistema.
fuente
la mayoría de los teléfonos nuevos de hoy en día vienen con algún tipo de administrador de ahorro de batería / energía que hace lo mismo que usted describió. sin contar los duboosters y los clean masters.
Creo que debe incluir una exención de responsabilidad o una pregunta frecuente en su aplicación / lista de Play Store que indique que esta aplicación debe colocarse en la excepción de su aplicación de administrador de batería para que funcione correctamente.
fuente
dejé de usar AlarmManager hace un tiempo ... una alternativa mejor y más estable
sí ... es un dolor ... pero el trabajo se hace NO IMPORTA QUÉ
fuente
¿Estás escuchando BOOT_COMPLETED? Debe volver a configurar las alarmas cuando se reinicia un dispositivo.
fuente
¿Qué versión de Android ejecutan estos dispositivos?
A partir de la API 23, el sistema operativo entrará en un modo inactivo de bajo consumo cuando no se haya utilizado durante un tiempo, y en ese modo no se entregarán alarmas. Sin embargo, hay una forma de que las aplicaciones digan explícitamente "Necesito que esta alarma se active en este momento independientemente del uso de la batería"; los nuevos métodos de AlarmManager llamados
setAndAllowWhileIdle()
ysetExactAndAllowWhileIdle()
.Según su descripción, parece que esta podría no ser la causa particular de sus problemas en los dispositivos de ciertos OEM, pero esto es algo que todos los desarrolladores que utilizan el Administrador de alarmas deben tener en cuenta.
Finalmente, muchos usos del Administrador de alarmas se abordan mejor utilizando los mecanismos del Programador de trabajos. Para compatibilidad con versiones anteriores, el "Administrador de red GCM" de Play Services tiene una funcionalidad muy similar al Programador de trabajos (utiliza el Programador de trabajos internamente en las versiones más recientes de Android) y no se trata necesariamente de redes, a pesar del nombre de la clase.
fuente
No creo que eliminar la aplicación evite que el administrador de alarmas active su aplicación.
Es solo cuando "fuerza la detención" o deshabilita la aplicación que no recibe devoluciones de llamada del administrador de alarmas.
La causa raíz podría ser otra cosa.
También en M ... setExactAndAllowWhileIdle hace estrangulamiento ... es decir, si programa una alarma cada 2 minutos, no se activará. .. Debe haber una ventana de 15 minutos. .
fuente
Para Xiaomi, es posible que deba habilitar AutoStart para su aplicación. Estoy tratando de hacer una lista de modificaciones de Android (generalmente del fabricante del teléfono) que pueden afectar un proceso en segundo plano. Si tiene algo nuevo, agregue una respuesta aquí Lista de asesinos de tareas de Android
fuente
Necesitamos habilitar nuestra aplicación en el administrador de inicio automático en el administrador de aplicaciones, algunos teléfonos como vivo v5,
En vivo v5, podemos encontrar este menú en iManager -> Administrador de aplicaciones -> Administrador de inicio automático. Habilite nuestra aplicación aquí.
Entonces su alarma / administrador de alarmas activará la alarma si la aplicación se mata o se cierra.
fuente
Estaba buscando una respuesta y después de varias horas encontré esto:
https://stackoverflow.com/a/35220476/3174791
En resumen, es una forma de saber si su aplicación fue eliminada por 'Aplicaciones protegidas' y esto solo funciona en dispositivos Huawei. avíseme si hay alguna solución para otros dispositivos (Samsung, Sony, Xiaomi, etc.).
fuente
Esto puede ser tarde, pero espero que ayude a alguien.
Estuve atrapado en el mismo problema durante tanto tiempo. Pero ahora sé cómo resolver este problema. Esto es para cualquiera que pueda tener el mismo problema. La gente sigue diciendo que tienes que habilitar AutoStart , sin embargo me a ella sin utilizar inicio automático.
En primer lugar, WakeFullBroadcastaReceiver ahora está en desuso y debería utilizar BroadcastReceiver. En segundo lugar, debe usar ForegroudService en lugar de BackgroundService.
Les daré el ejemplo a continuación:
IntentService.class
public class NotificationService extends IntentService { //In order to send notification when the app is close //we use a foreground service, background service doesn't do the work. public NotificationService() { super("NotificationService"); } @Override public void onCreate() { super.onCreate(); } @Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { super.onStartCommand(intent, flags, startId); //There is no difference in the result between start_sticky or start_not_sticky at the moment return START_NOT_STICKY; } @Override protected void onHandleIntent(@Nullable Intent intent) { //TODO check if the app is in foreground or not, we can use activity lifecyclecallbacks for this startForegroundServiceT(); sendNotification(intent); stopSelf(); } /*** * you have to show the notification to the user when running foreground service * otherwise it will throw an exception */ private void startForegroundServiceT(){ if (Build.VERSION.SDK_INT >= 26) { String CHANNEL_ID = "my_channel_01"; NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Channel human readable title", NotificationManager.IMPORTANCE_DEFAULT); ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel); Notification notification = new Notification.Builder(this, CHANNEL_ID) .setContentTitle("") .setContentText("").build(); startForeground(1, notification); } } private void sendNotification(Intent intent){ //Send notification //Use notification channle for android O+ } }
iniciar el servicio de primer plano en BroadcastReceiver.class
public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Intent service = new Intent(context, NotificationService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { context.startForegroundService(service); } else { context.startService(service); } } }
Y el setAlarms así:
public static void setAlarm(Context context, int requestCode, int hour, int minute){ AlarmManager alarmManager =( AlarmManager) context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context//same activity should be used when canceling the alarm , AlarmReceiver.class); intent.setAction("android.intent.action.NOTIFY"); //setting FLAG_CANCEL_CURRENT makes some problems. and doest allow the cancelAlarm to work properly PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1001, intent, 0); Calendar time = getTime(hour, minute); //set Alarm for different API levels if (Build.VERSION.SDK_INT >= 23){ alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,time.getTimeInMillis(),pendingIntent); } else{ alarmManager.set(AlarmManager.RTC_WAKEUP,time.getTimeInMillis(),pendingIntent); }
Luego, debe declarar el receptor y el servicio de primer plano en el manifiesto.
<receiver android:name=".AlarmReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.NOTIFY"> </action> </intent-filter> </receiver> <service android:name=".NotificationService" android:enabled="true" android:exported="true"></service>
Espero que esto ayude a alguien.
fuente