Java.lang.SecurityException:!@Trop d'alarmes (500) enregistrées à partir du pid 10790 uid 10206
je reçois cette erreur au moment de l'alarme programmée en utilisant le Gestionnaire D'alarme
am.setExact(AlarmManager.RTC_WAKEUP, timeMillis, pendingIntent);
Erreur est le suivant
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)
pourquoi cette erreur arrive et comment nous pouvons la corriger.
6 réponses
contrairement à ce que suggère le commentaire, ce n'est peut-être pas votre faute. Cela a commencé pour nous dans le code de production quelque part à la mi-Mars, cela ne se produit que sur Samsung avec Lollipop qui n'a commencé à être déployé que récemment.
mise à Jour: Ce problème s'est finalement produit sur l'un des téléphones disponibles.
comme @goncalossilva dit le problème est dû à l'utilisation de FLAG_CANCEL_CURRENT
, il semble que Samsung introduit un plafond de 500 sur le nombre d'alarmes et aucune autre fournisseur de cette limite.
lors de la création d'un PendingIntent
FLAG_CANCEL_CURRENT
il annulera l'intention en attente (évidemment) n'annulera pas l'alarme (également évidente), plus tard si vous annulez l'alarme en utilisant la nouvelle intention en attente il n'annulera pas l'alarme (moins évidente que Intent.filterEquals
doit être true
). Cela étant dit, parce que l'intention en attente a été annulée la vieille alarme ne va pas vraiment le feu, de sorte qu'il n'y a pas de crainte à introduire des bogues en changeant FLAG_UPDATE_CURRENT
.
en ce qui concerne la nécessité de redémarrez l'appareil après avoir changé en FLAG_UPDATE_CURRENT
, vous n'avez pas à redémarrer, vous avez juste besoin d'attendre pour l'un des alarmes d'incendie, de sorte que vous avez un nouveau logement pour une nouvelle alarme.
vous pouvez tester ce code pour reproduire le problème, puis FLAG_UPDATE_CURRENT
pour voir ce qui se passe.
vous devez également exécuter "adb shell dumpsys alarm"
voir toutes les alarmes générées
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);
}
pour ceux rencontrant ce problème uniquement sur les appareils Samsung exécutant Lollipop, vous utilisez probablement FLAG_CANCEL_CURRENT
de votre PendingIntent
S. Passez à FLAG_UPDATE_CURRENT
(d'autres ajustements, si nécessaire), et le problème devrait disparaître.
ma supposition totalement infondée est que Samsung fait quelques "optimisations" avec FLAG_CANCEL_CURRENT
d'où ils n'enlevez pas annulé PendingIntent
tout de suite, mais marquez seulement pour la suppression et puis faites-le trop rarement (ou pas à tous?).
Modifier
nous avons trouvé que les appareils où ce problème se produit seront dans un état cassé (rempli avec PendingIntent
s?) jusqu'à ce qu'ils sont redémarrés ou l'application est réinstallé.
Jamais utilisez FLAG_CANCEL_CURRENT avec PendingIntents que vous utilisez lors du paramétrage des alarmes. Si vous voulez reprogrammer l'alarme pour une heure différente, vous n'avez pas besoin de drapeau du tout; il suffit de créer un PendingIntent double avec des drapeaux de zéro, puis de l'utiliser pour définir() une alarme: cela annulera implicitement l'alarme existante, puis la réglera pour l'heure nouvellement spécifiée. Si vous avez utilisé FLAG_CANCEL_CURRENT lorsque vous avez créé le nouveau PendingIntent, cependant, il casse le Gestionnaire D'alarme capacité de reconnaître que c'est "la même chose" que le PendingIntent désormais annulé, et vous vous retrouvez avec l'ancien qui traîne autour, non distribuable, prenant la mémoire et CPU. J'ai vu des applications avec ce rack de bugs littéralement des centaines d'alarmes périmées dans le système, assez pour être une performance perceptible et l'utilisation de la mémoire hit.
si vous voulez simplement changer les extras sans rééchelonner l'alarme existante, C'est à ça que sert FLAG_UPDATE_CURRENT. Si vous voulez simplement reprogrammer ou annulez l'alarme, utilisez 0 pour les drapeaux.
il semble que la toute nouvelle Sucette construite sur les appareils Samsung limite le nombre d'alarmes que vous pouvez enregistrer. J'ai Temporairement corrigé le problème dans mon application en n'enregistrant que la plupart des alarmes X à tout moment (j'ai arbitrairement choisi X = 50 mais à en juger par le message d'erreur je crois que vous pouvez aller jusqu'à 499. Je n'ai pas testé).
j'ai sorti une version avec ce correctif temporaire il y a une semaine et je n'ai pas eu ce crash signalé depuis.
Pour moi, le passage à FLAG_UPDATE_CURRENT
seul n'a pas aidé à se débarrasser des entrées multiples de mes pendentifs (regardé avec adb shell dumpsys alarm > dump.txt
).
Je l'ai corrigé en changeant la façon dont j'annule ces intentions en attente de
PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT).cancel();
PendingIntent pi = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT).cancel();
alarmManager.cancel(pi);
cela a été nécessaire pour .getBroadcast()
et .getService()
. Fait intéressant avec .getActivity()
il ne l'était pas. Malheureusement, je n'ai aucune idée de pourquoi c'est le cas.
tous sur un Samsung Galaxy S4 avec Android 5.0.1. Peut-être que cela aide quelqu'un le reste aussi.
Je l'ai corrigé en utilisant le drapeau: PendingIntent.FLAG_UPDATE_CURRENT
PendingIntent pendingIntent = PendingIntent.getService(
MainActivity.this, 200, intent, PendingIntent.FLAG_UPDATE_CURRENT
);
am.setExact(AlarmManager.ELAPSED_REALTIME, realtime + 2000, pendingIntent);
Je l'ai testé dans un Galaxy S4 tournant sous Android 5.0.1.