Android 9.0 NotificationManager.notify() throwing java.lang.SecurityException

前端 未结 2 2089
萌比男神i
萌比男神i 2021-02-09 05:50

I have been unable to reproduce this problem myself, but so far 5 users have reported it. I did recently publish an app update that changed the target SDK from 27 to 28 which I

相关标签:
2条回答
  • 2021-02-09 06:11

    Not so much a solution as a long complicated workaround.

    First, I catch the SecurityException that is thrown by the notification and set a shared preference flag

    try {
      myNM.notify(NOTIFICATION_ALERT, n);
    } catch (SecurityException ex) {
      Log.e(ex);
      ManagePreferences.setNotifyAbort(true);
      return;
    }
    

    When the app starts up it checks this flag and it is set, prompts the user to grant the READ_EXTERNAL_PERMISSION. Not including the code because it is part of a complicated system that ties permissions to different preference settings, only allowing certain settings if a required permission is granted and changing it if the permission is not granted.

    That helps, but we still means the user will not get notified the first time an alert needs to be generated. To address that, we add something to are startup initialization that checks to see if there might be a problem, and if there is, generates a regular notification and immediately cancels it.

    if (audioAlert && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
      if (! ManagePreferences.notifyCheckAbort() &&
          ! PermissionManager.isGranted(context, PermissionManager.READ_EXTERNAL_STORAGE)) {
        Log.v("Checking Notification Security");
        ManagePreferences.setNotifyCheckAbort(true);
        ManageNotification.show(context, null, false, false);
        NotificationManager myNM = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        assert myNM != null;
        myNM.cancel(NOTIFICATION_ALERT);
      }
    }
    

    Getting closer. But we still miss an alert notification if it happens after the user upgrades to Android 9 but before they open the app. To address that, I wrote a broadcast receiver that listens for android.intent.action.MY_PACKAGE_REPLACED and android.intent.action.BOOT_COMPLETED which gets called every time my app is upgraded, or the Android system is upgraded. This receiver does not do anything special. But the fact that it exists means that my app gets started up and goes through the initialization logic. Which detects that the user needs the READ_EXTERNAL_STORAGE permission and prompts them for it.

    0 讨论(0)
  • 2021-02-09 06:30

    I had this issue. Turns out that the creation of the notification channel was at fault.

    Wrong way:

    val notifictionChannel = NotificationChannel(...)
    notificationChannel.setSound(
        RingtoneManager.getActualDefaultRingtoneUri(context, RingtoneManager.TYPE_NOTIFICATION),
        AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build()
    )
    
    notificationManager.createNotificationChannel(notificationChannel)
    

    Right way:

    ...
    notificationChannel.setSound(
        Settings.System.DEFAULT_NOTIFICATION_URI,
        AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build()
    )
    ...
    
    0 讨论(0)
提交回复
热议问题