Почему NotificationManagerCompat :: cancelAll () получает SecurityException?

Использование NotificationManagerCompat для отмены всех уведомлений.

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

Он получил какое-то время (большинство работает).

На Andoid 6:

Java.lang.SecurityException: Разрешение: getCurrentUser () из pid = 22994, uid = 10184 требует 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: отказ от разрешения: getIntentSender () из pid = 5460, uid = 10135, (требуется uid = 1000) не разрешено отправлять как пакетный Android в 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().uid или android.os.Process.myUid() ?

Solutions Collecting From Web of "Почему NotificationManagerCompat :: cancelAll () получает SecurityException?"

Ответ не дает твердого решения проблемы, он скорее пытается дать объяснение причины как для OP, так и для @ 66CLSjY , предложивших щедрость, с аналогичной проблемой .


Проверка stacktrace

В соответствии с stacktrace SecurityException вызывается в удаленном процессе: ваш процесс приложения «Объект Binder (например, INotificationManager.Stub , ActivityManagerProxy и т. Д.) Делает транзакцию Binder ( mRemote.transact() ) * на удаленном объекте Binder и считывает с объекта Исключение ( _reply.readException() ) произошло в удаленных вызовах. Если таковые имеются, сообщение об исключении анализируется, и в вашем процессе генерируется соответствующее исключение .

Анализ сообщения об исключении

Оба сообщения об исключениях (одно с getIntentSender() и другое с getCurrentUser() ) довольно просто – ваше приложение не прошло проверку на наличие разрешений или, другими словами, фрагменты кода ActivityManagerService , которые должны были вызываться под system_server процесса system_server ( UID=1000 ) **, но на самом деле были вызваны в соответствии с идентификатором вашего приложения .

Возможная причина и обходной путь

Он получил какое-то время (большинство работает).

Не делая предположения, то, что вы получаете «некоторое время», является неправильным поведением Android . Обход вызова проблемы с try/catch кажется обходным путем, пока кто-то не предложит твердое решение (если оно существует).


* ActivityManagerProxy.setRequestedOrientation () и IAccessibilityManager $ Stub $ Proxy.sendAccessibilityEvent ()
** android.permission.INTERACT_ACROSS_USERS имеет подпись | Уровень защиты системы

Мне кажется, что есть две разные возможности, почему это не работает:

Наиболее вероятная причина заключается в том, что вы используете неправильный контекст для вызова; getApplicationContext() не на 100% надежнее и иногда вызывает странные ошибки, всегда лучше избегать этого вызова. Если вы вызываете cancelAll() из Сервиса или Действия, используйте YourClass.this вместо getApplicationContext() , если это из BroadcastReceiver, используйте предоставленную Контекстную переменную.

Если это все еще не работает, это может быть ошибка в NotificationManagerCompat , попробуйте, если вы можете воспроизвести ту же проблему с NotificationManager . Обходным путем для этого было бы сохранить все идентификаторы уведомлений в списке, а затем отменить их каждый с помощью manager.cancel(id) . Таким образом, система не будет пытаться отменить любые уведомления, которые не принадлежат вашему приложению.