AlarmManager no funciona en varios dispositivos


85

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/


8
Los fabricantes culpan a las aplicaciones por el consumo de energía y siguen comercializando los Octa-cores, que consumen más batería en comparación con la CPU con menos núcleos. ¿Creen que simplemente agregar un núcleo aceleraría sus teléfonos?
FrozenFire

1
@AviLevinshtein Tal vez no entendí tu pregunta. Estoy creando las alarmas en mi actividad. Luego, cuando suena la alarma, se ejecuta un receptor de transmisión y, finalmente, se ejecuta un WakefulIntentService (clase de @commonsware).
Sergio Viudes

2
@JFValdes Sigo buscando una solución. AlarmManager funciona perfectamente en dispositivos con Android Vanilla. El problema es que los fabricantes están tratando de "mejorar" las funciones de Android y rompieron AlarmManager ... Los fabricantes no deberían implementar sus propios "ahorradores de batería", si usan el modo Doze estándar, AlarmManager funcionaría perfectamente ... para una solución ...
Sergio Viudes

1
¿Hay alguna solución todavía? ¿Cómo hacen eso otras aplicaciones como recordatorios o algo así? Tiene que haber otra opción que setAlarm, que es para alarmas, no para recordatorios
kv1dr

1
@SergioViudes también tengo el mismo problema con los dispositivos Xiomi para el seguimiento. y si mantengo mi aplicación fuera de la restricción de ahorro de batería, entonces funciona correctamente en 3 de los 4 dispositivos mediante la siguiente configuración: -> Ir a la batería -> Energía -> Ahorro de batería de la aplicación -> su aplicación Ahora seleccione Sin restricciones (para la configuración de fondo), luego la opción Permitir para la ubicación de fondo
Imran Khan Saifi

Respuestas:


17

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.


Igual que yo, también lo intento pero no hay forma de solucionar este problema en alguna marca Xiaomi, Oppo, Huawei. A veces matan el proceso en segundo plano y la alarma para ahorrar batería.
Andi Susilo

1
Tengo un teléfono Huawei, cambiar el nombre del paquete a alarma / calendario no hace nada. La única forma de evitar esto agrega tu aplicación en la lista de aplicaciones protegidas del administrador del teléfono
Ashish Pardhiye

9

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


Me estoy volviendo loco porque no tengo ningún dispositivo Samsung para probarlo. Solo sé lo que me dicen los usuarios de mi aplicación. ¿Sabe si el problema es que AlarmManager no funciona porque la aplicación se mata? ¿O el problema es que el dispositivo no puede activarse cuando suena la alarma debido a ese administrador?
Sergio Viudes

@SergioViudes Recientemente, muchas empresas han implementado las suyas propias. Como LG tiene uno que funciona de manera similar a Samsung, ¿tal vez su teléfono tiene uno? El problema no es la alarma, la aplicación de alarma se empuja a un estado en el que está completamente inactiva. Smart Manager cree que es solo una aplicación aleatoria que no necesitas. Noté que ciertas aplicaciones pueden superarlo, tal vez algunas aplicaciones sean aceptadas por el administrador inteligente.
SA

1
@SergioViudes Tengo un Samsung para probar y puedo decirte que no hay mucho que puedas obtener de él. Cuando el administrador inteligente optimiza su aplicación, no hay ningún error ni nada, simplemente muere, similar a forzar la detención. Sin embargo, todavía está en la lista de aplicaciones recientes
Tim

Gracias Tim. Sería genial resolver este problema sin tener que excluir aplicaciones del Administrador "inteligente".
Sergio Viudes

dispositivos como xiaomi (miui), vivo y htc establecen una gran cantidad de permisos como falsos de forma predeterminada, a menos que sea una aplicación en la lista de aplicaciones "confiables" que parecen determinar por sí mismas (whatsapp, truecaller, etc.son confiables de manera predeterminada ). Esto se está convirtiendo en una pesadilla para los codificadores
desidigitalnomad

3

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


2

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.


2
Desafortunadamente, a diferencia de la clase AlarmManager, el tiempo no es exacto cuando se usa JobScheduler. En mi aplicación, el tiempo debe ser exacto :(
Sergio Viudes

Lo intenté y algunos optimizadores (Samsung al menos) eliminan todas las tareas pendientes en JobScheduler cuando se apaga la pantalla. Entonces también está roto. Esto sucede en 5.0. Después de actualizar a 6.0 funciona bien, supongo que lo arreglaron. Todavía no pude probarlo con otros fabricantes.
Sloy

Para conocer el tiempo exacto, no puede utilizar un servicio en segundo plano o un servicio programado. Puede probar un servicio en primer plano, pero esto creará una notificación persistente para el usuario (probablemente indeseable) y algunos teléfonos tienen asesinos de tareas integrados que destruirán automáticamente el servicio en primer plano. WorkManager es la mejor solución, pero desafortunadamente no le dará los tiempos exactos.
Tom

1

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.


Gracias por tu respuesta. ¿Hay alguna forma de eliminar el icono del despertador?
Sergio Viudes

Desafortunadamente, setAlarmClock no funciona a veces. Lo probé en un dispositivo Oreo con poca memoria.
Boris Salimov

0

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.


Debería haber otra forma de hacerlo ... Los usuarios no leerán el descargo de responsabilidad. No puedo pensar que los teléfonos Samsung no permitan que las aplicaciones usen AlarmManager ...
Sergio Viudes

Las alarmas no se dispararán "a tiempo", pero eventualmente lo harán
Gavriel

Esta es (lamentablemente) la respuesta más útil, diría yo. Ojalá hubiera una solución mejor, pero los fabricantes de hardware están dañando el Android vainilla que funciona perfectamente.
caw

0

dejé de usar AlarmManager hace un tiempo ... una alternativa mejor y más estable

  1. crear un servicio
  2. registrar un BroadcastReceiver para BOOT_COMPLETED
  3. despedir su servicio desde el receptor
  4. inicie un nuevo controlador dentro de su servicio que se repita cada X minutos ( Android: ejecutar un método periódicamente usando la llamada postDelayed () )
  5. compruebe si ha llegado el momento de ejecutar la tarea: ahora - tiempo de ejecución> 0 ( ¿Cómo encontrar la duración de la diferencia entre dos fechas en java? )
  6. si es así, ejecute la tarea y detenga el controlador

sí ... es un dolor ... pero el trabajo se hace NO IMPORTA QUÉ


3
Gracias por su sugerencia, pero me gustaría evitar ese enfoque, porque el uso de AlarmManager no consumirá RAM ni ningún recurso. Y, si se mata su aplicación, el servicio se detendría, ¿verdad?
Sergio Viudes

No dije que este enfoque sea BOOLETPROOF, pero al menos consiste en diferentes versiones de API :)
ymz

Para funcionar de manera confiable, esta solución probablemente también necesitaría usar wake locks y eso consumiría enormes cantidades de batería.
Paweł Nadolski

supongo que tienes razón en esto ... la única pregunta es: ¿qué sería peor: un código poco confiable o un mal rendimiento? de todos modos, personalmente creo que hay formas alternativas de bloqueo que pueden ser adecuadas en algunos casos (por ejemplo: stackoverflow.com/questions/5346694/… )
ymz

0

¿Estás escuchando BOOT_COMPLETED? Debe volver a configurar las alarmas cuando se reinicia un dispositivo.


Si. Como dije, las alarmas funcionaban desde 2012, hasta ahora. Cuando se reinicia el dispositivo, reprogramo las alarmas en el receptor de transmisión BOOT_COMPLETED.
Sergio Viudes

1
Requerir un reinicio para que su aplicación funcione nuevamente no es ni la mitad de una solución
Tim

1
@TimCastelijns, eso no es en absoluto lo que estoy diciendo. SI el dispositivo se reinicia, todas las alarmas configuradas con el administrador de alarmas deben configurarse nuevamente.
Tyler Pfaff

@TylerPfaff sí, pero el reinicio del dispositivo no está relacionado con el problema en esta pregunta
Tim

0

¿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()y setExactAndAllowWhileIdle().

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.


Los dispositivos Samsung con Smart Manager ejecutan Lollipop. Ya estoy usando setExactAndAllowWhileIdle para dispositivos Marshmallow. Echaré un vistazo a JobScheduler y GCM. De todos modos, no sé si el problema es que la alarma no se dispara o si ese dispositivo no se despierta cuando suena la alarma.
Sergio Viudes

0

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


1
Gracias por tu respuesta. Pero, si no es así, ¿por qué la aplicación funciona perfectamente cuando la "optimización de la batería" está desactivada en Smart Manager?
Sergio Viudes

¿Está ejecutando la aplicación en un dispositivo rooteado ... si es así, el administrador de la aplicación también puede deshabilitar la aplicación?
rupesh jain

No, no lo estoy ejecutando en un dispositivo rooteado.
Sergio Viudes

@rupeshjain "es decir, si programa una alarma cada 2 minutos, no se activará ... Debe haber una ventana de 15 minutos". esto no es completamente cierto, es un problema real si fuera cierto. Puede leer exactamente cuál es el límite de tiempo para programar dentro de los Documentos de Android para el método setExactAndAllowWhileIdle. Existen restricciones sobre la frecuencia con la que se activan estas alarmas para una aplicación en particular. En el funcionamiento normal del sistema, no enviará estas alarmas más de aproximadamente cada minuto cuando en los modos inactivos de baja potencia esta duración puede ser significativamente mayor a 15 minutos.
eyadMhanna

0

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


0

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.


0

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


0

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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.