Подтвердить что ты не робот

Почему 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        at 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)

Вопросы:

  • Что может быть причиной?
  • Что это за идентификатор? Это ctx.getApplicationContext().getApplicationInfo().uid или android.os.Process.myUid()?
4b9b3361

Ответ 1

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


Проверка stacktrace

В соответствии с stacktrace SecurityException выбрасывается в удаленном процессе: ваш процесс приложения Binder (например, INotificationManager.Stub, ActivityManagerProxy и т.д.) выполняет транзакцию Binder (mRemote.transact()) * на удаленном объекте Binder и считывает с объекта исключение (_reply.readException()) в удаленных вызовах. Если есть, анализируется сообщение об ошибке getIntentSender() и другое с getCurrentUser()) - ваше приложение не прошло проверку разрешений или, другими словами, фрагменты кода ActivityManagerService, которые должны были называться под идентификатором процесса system_server (UID=1000) **, но на самом деле они назывались в вашем приложении 'identity.

Возможная причина и обходное решение

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

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


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

Ответ 2

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

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

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