java.lang.SecurityException:! @Too muchas alarmas (500) registradas desde pid 10790 uid 10206

Recibo este error al momento de progtwigr la alarma usando Alarm Manager

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 momento a mediados de marzo, esto solo sucede en Samsung con Lollipop, que recién comenzó a implementarse recientemente.

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 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 bash pendiente (obviamente) no cancelará la alarma (también es obvio), luego, si cancela la alarma con el nuevo bash pendiente, no cancelará la alarma (menos obvio como Intent.filterEquals debería ser true ). Dicho esto, debido a que el bash 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 necesita esperar a que se FLAG_UPDATE_CURRENT una de las alarmas para que tenga una nueva ranura para una nueva alarma.

Puede probar este código para reproducir el problema, luego cambie 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); } 

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 (realice cualquier otro ajuste, si es necesario) y el problema 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, solo lo marcan para eliminarlo y luego 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.

Nunca use FLAG_CANCEL_CURRENT con PendingIntents que usa cuando configura las alarmas. Si desea reprogtwigr la alarma para una hora diferente, no necesita ninguna bandera; 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 usaste FLAG_CANCEL_CURRENT cuando creaste el nuevo PendingIntent, se rompe la capacidad del Administrador de alarmas de reconocer que es “lo mismo” que PendingIntent ahora cancelado, y terminas con el anterior, no se puede entregar, ocupando la memoria y CPU. He visto aplicaciones con este bug que literalmente acumula cientos de alarmas obsoletas en el sistema, lo suficiente como para ser un rendimiento notable y un golpe de uso de memoria.

Si solo desea cambiar los extras sin reprogtwigr la alarma existente, para eso es FLAG_UPDATE_CURRENT. Si solo desea reprogtwigr o cancelar la alarma, simplemente use 0 para las banderas.

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 registrando solo la mayoría de las X alarmas en un momento determinado (he elegido arbitrariamente X = 50 pero a juzgar por el mensaje de error, creo que puedes subir hasta 499. No lo he probado sin embargo).

Lancé una versión con esta corrección temporal hace una semana y no he tenido esta falla reportada desde entonces.

Para mí, cambiar a FLAG_UPDATE_CURRENT solo no me ayudó a deshacerme de las múltiples entradas de mis pendientes (vistos con adb shell dumpsys alarm > dump.txt ).

Lo arreglé cambiando la forma en que cancelo esos bashs 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 fue así. 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.

Lo arreglé usando la bandera: 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.