为什么NotificationManagerCompat :: cancelAll()会得到SecurityException?

使用NotificationManagerCompat取消所有通知。

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

它有一段时间(大部分时间工作)得到了例外。

在Andoid 6:

java.lang.SecurityException:Permission Denial:getCurrentUser()from pid = 22994,uid = 10184 requires android.permission.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) 

在Android 5.0,4.4.2上:

ava.lang.SecurityException:Permission Denial:getIntentSender()from pid = 5460,uid = 10135,(need uid = 1000)不允许以android.os.Parcel.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) 

问题:

  1. 可能是什么原因?
  2. 这里的身份证是什么? 它是ctx.getApplicationContext().getApplicationInfo().uidandroid.os.Process.myUid()

Solutions Collecting From Web of "为什么NotificationManagerCompat :: cancelAll()会得到SecurityException?"

答案并不能为问题提供一个可靠的解决scheme ,而是试图解释提供赏金的OP和@ 66CLSjY的原因 ,并提出类似的问题 。


检查堆栈跟踪

根据Stacktrace SecurityException在远程进程中抛出:您的应用程序进程' Binder对象(例如INotificationManager.StubActivityManagerProxy等)在远程Binder对象上创build一个Binder事务 ( mRemote.transact() )*并从该对象读取在远程调用中发生exception( _reply.readException() )。 如果有, 分析exception消息,并在您的过程中引发相应的exception 。

分析exception消息

这两个exception消息(一个使用getIntentSender() ,另一个使用getCurrentUser() )相当直接 – 你的应用程序没有通过权限检查,或者换句话说, ActivityManagerService的代码片断应该被调用system_server进程的身份 ( UID=1000 )**,但实际上, 在您的应用进程的身份下被调用。

可能的原因和解决方法

它有一段时间(大部分时间工作)得到了例外。

不做任何假设, “一段时间”就是不正确的Android行为。 用try/catch包装问题似乎是一个解决方法,直到有人提出了一个可靠的解决scheme(如果存在)。


* ActivityManagerProxy.setRequestedOrientation()和IAccessibilityManager $存根$ Proxy.sendAccessibilityEvent()
** android.permission.INTERACT_ACROSS_USERS是签名| 系统保护级别

对我来说,这听起来像有两种不同的可能性,为什么这不工作:

最可能的原因是您使用错误的上下文来拨打电话; getApplicationContext()不是100%可靠的,有时会产生奇怪的错误,总是最好避免这个调用。 如果从Service或Activity调用cancelAll() ,则使用YourClass.this而不是getApplicationContext() ,如果它来自BroadcastReceiver,则使用提供的Contextvariables。

如果这仍然不起作用,可能是NotificationManagerCompat一个错误,请尝试是否可以通过NotificationManager重现相同的问题。 解决方法是将所有通知ID保存在列表中,然后使用manager.cancel(id)取消它们。 这样系统将不会试图取消任何不属于您的应用程序的通知。