android - tutorial - java.lang.SecurityException:! @Demasiadas alarmas(500) registradas desde pid 10790 uid 10206
ejecutar una tarea programada android studio (6)
Recibo este error en el momento de programar la alarma mediante el Administrador de alarmas
am.setExact(AlarmManager.RTC_WAKEUP, timeMillis, pendingIntent);
El error es como sigue
java.lang.SecurityException: !@Too many alarms (500) registered from pid 10790 uid 10206
at android.os.Parcel.readException(Parcel.java:1540)
at android.os.Parcel.readException(Parcel.java:1493)
at android.app.IAlarmManager$Stub$Proxy.set(IAlarmManager.java:206)
at android.app.AlarmManager.setImpl(AlarmManager.java:428)
at android.app.AlarmManager.setExact(AlarmManager.java:376)
Por qué viene este error y cómo podemos solucionarlo.
A diferencia de lo que sugiere el comentario, esto podría no ser tu culpa. Esto comenzó a suceder para nosotros en el código de producción en algún lugar a mediados de marzo, esto solo sucede en Samsung con Lollipop, que recientemente comenzó a implementarse.
Actualización: este problema finalmente ocurrió en uno de los teléfonos que tenemos disponibles.
como @goncalossilva dijo que el problema se debe al uso de FLAG_CANCEL_CURRENT
, parece que Samsung introduce un límite máximo de 500 en la cantidad de alarmas y ningún otro proveedor tiene este límite.
al crear un PendingIntent
con FLAG_CANCEL_CURRENT
, cancelará el intento pendiente (obviamente) no cancelará la alarma (también es obvio), más adelante, si cancela la alarma con el nuevo intento pendiente, no cancelará la alarma (menos obvio como Intent.filterEquals
debería ser true
). Dicho esto, debido a que el intento pendiente se canceló, la alarma anterior no se activará, por lo que no hay temor al introducir errores al cambiar FLAG_UPDATE_CURRENT
.
con respecto a la necesidad de reiniciar el dispositivo después de cambiar a FLAG_UPDATE_CURRENT
, no tiene que reiniciarlo, solo tiene que esperar a que se FLAG_UPDATE_CURRENT
una de las alarmas para tener una nueva ranura para una nueva alarma.
Puedes probar este código para reproducir el problema, luego cambiar a FLAG_UPDATE_CURRENT
para ver qué sucede. también debe ejecutar "adb shell dumpsys alarm"
para ver todas las alarmas generadas
AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
for (int i = 0; i<1000; i++)
{
Intent intent = new Intent("FOOFOOFOO");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.cancel(pendingIntent);
long firstTime = SystemClock.elapsedRealtime() + 1000;
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, pendingIntent);
}
Lo arreglé utilizando el indicador: PendingIntent.FLAG_UPDATE_CURRENT
PendingIntent pendingIntent = PendingIntent.getService(
MainActivity.this, 200, intent, PendingIntent.FLAG_UPDATE_CURRENT
);
am.setExact(AlarmManager.ELAPSED_REALTIME, realtime + 2000, pendingIntent);
Lo probé en un Galaxy S4 que se ejecuta en Android 5.0.1.
Para aquellos que encuentran este problema únicamente en los dispositivos Samsung que ejecutan Lollipop, probablemente FLAG_CANCEL_CURRENT
usando FLAG_CANCEL_CURRENT
con tus PendingIntent
. Cambie a FLAG_UPDATE_CURRENT
(haciendo cualquier otro ajuste, si es necesario), y el problema debería desaparecer.
Mi suposición completamente infundada es que Samsung está haciendo algunas "optimizaciones" con FLAG_CANCEL_CURRENT
donde no eliminan el PendingIntent
cancelado de inmediato, sino que solo lo marcan para su eliminación y lo hacen con poca frecuencia (¿o no lo hacen en absoluto?).
Editar
Hemos descubierto que los dispositivos donde se produce este problema estarán en un estado descompuesto (rellenos con PendingIntent
s?) Hasta que se reinicien o la aplicación se reinstale.
Para mí, el cambio a FLAG_UPDATE_CURRENT
solo no ayudó a deshacerme de las múltiples entradas de mis elementos pendientes (observados con adb shell dumpsys alarm > dump.txt
).
Lo arreglé cambiando la forma en que cancelo los intentos pendientes de
PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT).cancel();
a
PendingIntent pi = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT).cancel();
alarmManager.cancel(pi);
Esto fue necesario para .getBroadcast()
y .getService()
. Curiosamente con .getActivity()
no lo fue. Lamentablemente, no tengo idea de por qué este es el caso.
Todo en un Samsung Galaxy S4 con Android 5.0.1. Quizás esto ayude a alguien más, también.
Parece que la versión más reciente de Lollipop en dispositivos Samsung restringe la cantidad de alarmas que puede registrar. He solucionado temporalmente el problema en mi aplicación al registrar solo la mayoría de las X alarmas en un momento dado (he elegido arbitrariamente X = 50, pero a juzgar por el mensaje de error, creo que puede subir hasta 499. No he probado esto sin embargo).
He lanzado una versión con esta solución temporal hace una semana y no he tenido este fallo desde entonces.
Nunca use FLAG_CANCEL_CURRENT con PendingIntents que usa cuando configura alarmas. Si desea reprogramar la alarma por un tiempo diferente, no necesita ninguna marca; solo crea un PendingIntent duplicado con flags de cero y luego úsalo para establecer () una alarma: esto cancelará implícitamente la alarma existente y luego la configurará por el tiempo especificado recientemente. Sin embargo, si usó FLAG_CANCEL_CURRENT cuando creó el nuevo PendingIntent, se rompe la capacidad del Administrador de alarmas para reconocer que es "el mismo" que el PendingIntent ahora cancelado, y usted termina con el antiguo por ahí, sin poder ser entregado, sin memoria, ocupando memoria. y CPU. He visto aplicaciones con este error acumular literalmente cientos de alarmas obsoletas en el sistema, lo suficiente como para ser un notable golpe de rendimiento y uso de memoria.
Si solo desea cambiar los extras sin volver a programar la alarma existente, para eso es FLAG_UPDATE_CURRENT. Si solo desea reprogramar o cancelar la alarma, solo use 0 para las banderas.