Layui

On Android 8.1 API 27 notification does not display

匿名 (未验证) 提交于 2018-03-17 14:58:17

问题:

I get Toast on Android 8.1 API 27:

Developer warning for package "my_package_name"
Failed to post notification on ...

Logcat includes next strings:

Notification: Use of stream types is deprecated for operations other than volume control

W/Notification: See the documentation of setSound() for what to use instead with android.media.AudioAttributes to qualify your playback use case

E/NotificationService: No Channel found for pkg=my_package_name

The full information in the Toast and in Logcat can help in the localization this problem.

回答1:

If you get this error should be paid attention to 2 items and them order:

  1. NotificationChannel mChannel = new NotificationChannel(id, name, importance);
  2. builder = new NotificationCompat.Builder(this, id);

Also NotificationManager notifManager and NotificationChannel mChannel are created only once. And setChannelId(id) is required for deprecated in API level >= 26 constructor .Builder(this).

if you used deprecated in API level >= 26 constructor .Builder(this) then builder.setChannelId(id) is required for Android 8 Oreo API 26 and later.

There are required setters for Notification on Android 8 Oreo API 26 and later:

  • builder.setContentTitle() // required
  • .setSmallIcon() // required
  • .setContentText() // required
  • .setChannelId(id) // required for deprecated in API level >= 26 constructor .Builder(this)

The example:

        private NotificationManager notifManager;

        public void createNotification(String aMessage) {
             final int NOTIFY_ID = 1002;

             // There are hardcoding only for show it's just strings
             String name = "my_package_channel";
             String id = "my_package_channel_1"; // The user-visible name of the channel.
             String description = "my_package_first_channel"; // The user-visible description of the channel.

             Intent intent;
             PendingIntent pendingIntent;
             NotificationCompat.Builder builder;

             if (notifManager == null) {
                 notifManager =
    (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
             }

             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                 int importance = NotificationManager.IMPORTANCE_HIGH;
                 NotificationChannel mChannel = notifManager.getNotificationChannel(id);
                 if (mChannel == null) {
                    mChannel = new NotificationChannel(id, name, importance);
                    mChannel.setDescription(description);
                    mChannel.enableVibration(true);
                    mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
                    notifManager.createNotificationChannel(mChannel);
                 }
                 builder = new NotificationCompat.Builder(this, id);

                 intent = new Intent(this, MainActivity.class);
                 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
                 pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

                 builder.setContentTitle(aMessage)  // required
                        .setSmallIcon(android.R.drawable.ic_popup_reminder) // required
                        .setContentText(this.getString(R.string.app_name))  // required         
                        .setDefaults(Notification.DEFAULT_ALL)
                        .setAutoCancel(true)
                        .setContentIntent(pendingIntent)
                        .setTicker(aMessage)
                        .setVibrate(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
           } else {

                builder = new NotificationCompat.Builder(this);

                intent = new Intent(this, MainActivity.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
                pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

                builder.setContentTitle(aMessage)                           // required
                       .setSmallIcon(android.R.drawable.ic_popup_reminder) // required
                       .setContentText(this.getString(R.string.app_name))  // required
                       .setDefaults(Notification.DEFAULT_ALL)
                       .setAutoCancel(true)
                       .setContentIntent(pendingIntent)
                       .setTicker(aMessage)
                       .setVibrate(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400})
                       .setPriority(Notification.PRIORITY_HIGH);
             } // else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

          Notification notification = builder.build();
          notifManager.notify(NOTIFY_ID, notification);
}


回答2:

Andy's answer is working however I wanted to avoid to deprecated Builder and follow the FireBase Official Document. I just added code before notify from manager.

String channelId = "default_channel_id";
String channelDescription = "Default Channel";
//Check if notification channel exists and if not create one
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
    NotificationChannel notificationChannel = notificationManager.getNotificationChannel(channelId);
    if (notificationChannel == null) {
        int importance = NotificationManager.IMPORTANCE_HIGH;
        notificationChannel = new NotificationChannel(channelId, channelDescription, importance);
        notificationChannel.setLightColor(Color.GREEN);
        notificationChannel.enableVibration(true);
        notificationManager.createNotificationChannel(notificationChannel);
    }
}

//notificationManager.notify as usual


回答3:

I have set channel id, but notification still not shown.

Finally i found my problem is had not invoke "setContentText()" method.

It was really help me that @Andy Sander mentioned "required setters"!

here are required setters for Notification on Android 8 Oreo API 26 and later:

builder.setContentTitle() // required
.setSmallIcon() // required
.setContentText() // required
.setChannelId(id) // required for deprecated in API level >= 26 constructor .Builder(this)