Pourquoi NotificationManagerCompat:: cancelAll() gets SecurityException?

utilisant NotificationManagerCompat pour annuler toute notification.

NotificationManagerCompat manager =  
    NotificationManagerCompat.from(ctx.getApplicationContext());
manager.cancelAll();

Il a obtenu l'exception d'un certain temps (la plupart du temps).

sur Andoid 6:

de java.lang.SecurityException: Autorisation de Déni: getCurrentUser() à partir pid=22994, uid=10184 nécessite android.autorisation.INTERACT_ACROSS_USERS

Fatal Exception: java.lang.SecurityException: Permission Denial: getCurrentUser() from pid=22994, uid=10184 requires android.permission.INTERACT_ACROSS_USERS
   at android.os.Parcel.readException(Parcel.java:1602)
   at android.os.Parcel.readException(Parcel.java:1555)
   at android.app.INotificationManager$Stub$Proxy.cancelAllNotifications(INotificationManager.java:649)
   at android.app.NotificationManager.cancelAll(NotificationManager.java:323)
   at android.support.v4.app.NotificationManagerCompat.cancelAll(NotificationManagerCompat.java:197)

sur Android 5.0, 4.4.2:

ava.lang.SecurityException: Autorisation de Déni: getIntentSender() à partir pid=5460, uid=10135, (besoin uid=1000) n'est pas autorisé à envoyer en tant que package android au android.OS.Colis.readException (Parcel.java: 1465)

Fatal Exception: java.lang.SecurityException: Permission Denial: getIntentSender() from pid=3109, uid=10153, (need uid=1000) is not allowed to send as package android
   at android.os.Parcel.readException(Parcel.java:1472)
   at android.os.Parcel.readException(Parcel.java:1426)
   at android.app.INotificationManager$Stub$Proxy.cancelAllNotifications(INotificationManager.java:271)
   at android.app.NotificationManager.cancelAll(NotificationManager.java:220)
   at android.support.v4.app.NotificationManagerCompat.cancelAll(NotificationManagerCompat.java:197)

Questions:

  1. quelle pourrait en être la cause?
  2. C'est quoi ces papiers? Est-ce ctx.getApplicationContext().getApplicationInfo().uid ou android.os.Process.myUid() ?
25
demandé sur Onik 2016-04-15 00:06:32

2 réponses

La réponse ne fournit pas une solution solide pour les le problème, on essaie de donner une explication de la cause à la fois pour l'OP et @66CLSjY , qui a offert le bounty, avec un problème similaire .


inspection de la chaîne de stockage

selon le stacktrace SecurityException est lancé dans le processus à distance: votre app process" Binder objet (par exemple INotificationManager.Stub , ActivityManagerProxy etc.) fait un Binder transaction ( mRemote.transact() ) * sur la télécommande Binder de l'objet et de le lire à partir de l'objet d'une exception ( _reply.readException() ) a eu lieu au sein de l'appel distant(s). Le cas échéant, le message d'exception est analysé et une exception correspondante est lancée dans votre processus.

analyse du message d'exception

les deux messages d'exception (un avec getIntentSender() et un autre avec getCurrentUser() ) sont assez simples - votre application n'a pas passé un contrôle de permission, ou en d'autres termes, les extraits de code de ActivityManagerService qui étaient censés être appelés sous le system_server processus d'identité ( UID=1000 ) **, mais, en fait, étaient appelé sous l'identité .

cause Possible et solution de contournement

Il a obtenu l'exception d'un certain temps (la plupart du temps).

sans faire de supposition, ce que vous obtenez "un certain temps" est un comportement inapproprié Android . enveloppant l'appel de problème avec try/catch semble être une solution de contournement jusqu'à ce que quelqu'un suggère une solution solide (si elle existe).


* ActivityManagerProxy.setRequestedOrientation () et IAccessibilityManager$Stub$Proxy.sendAccessibilityEvent()

** android.permission.INTERACT_ACROSS_USERS est de signature | système de niveau de protection

4
répondu Onik 2017-05-23 12:30:34

pour moi, il semble qu'il y ait deux possibilités différentes pourquoi cela ne fonctionne pas:

la cause La plus probable est que vous utilisez le mauvais contexte pour faire l'appel; getApplicationContext() n'est pas fiable à 100% et produit parfois des erreurs étranges, il est toujours préférable d'éviter cet appel. Si vous appelez cancelAll() d'un Service ou D'une activité, utilisez YourClass.this au lieu de getApplicationContext() , s'il s'agit d'un émetteur de radiodiffusion, utilisez la variable de contexte fournie.

Si cela ne fonctionne toujours pas, il peut-être un bug dans NotificationManagerCompat , essayez si vous pouvez reproduire le même problème avec NotificationManager . Une solution de rechange pour cela serait de sauvegarder tous vos ID de Notification dans une liste et puis de les annuler chacun avec manager.cancel(id) . De cette façon, le système ne sera pas essayer d'annuler les Notifications qui n'appartiennent pas à votre application.

0
répondu Force 2016-11-10 09:58:19