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.

30
demandé sur Vadim Kotov 2015-03-30 14:25:03

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 PendingIntentFLAG_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);
    } 
40
répondu sagiema 2015-10-20 14:54:14

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

4
répondu goncalossilva 2015-04-17 18:09:52

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.

2
répondu ctate 2016-10-08 00:11:50

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.

1
répondu jguerinet 2015-05-05 13:09:32

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.

1
répondu Dominikus K. 2016-06-02 12:45:50

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.

-1
répondu David 2016-06-20 12:37:12