Notifications fail to display in Android Oreo (API

2020-01-27 04:28发布

问题:

I get this message when trying to display a notification on Android O.

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

The notification is straight from the example docs, and displays fine on Android 25.

回答1:

Per the comments on this Google+ post:

those [warnings] are currently expected when using NotificationCompat on Android O devices (NotificationCompat always calls setSound() even if you never pass in custom sound).

until the Support Library changes their code to use the AudioAttributes version of setSound, you'll always get that warning.

Therefore there's nothing that you can do about this warning. As per the notification channels guide, Android O deprecates setting a sound on an individual notification at all, instead having you set the sound on a notification channel used by all notifications of a particular type.



回答2:

Starting with Android O, you are required to configure a NotificationChannel, and reference that channel when you attempt to display a notification.

private static final int NOTIFICATION_ID = 1;
private static final String NOTIFICATION_CHANNEL_ID = "my_notification_channel";

...

NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
  NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_DEFAULT);

  // Configure the notification channel.
  notificationChannel.setDescription("Channel description");
  notificationChannel.enableLights(true);
  notificationChannel.setLightColor(Color.RED);
  notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
  notificationChannel.enableVibration(true);
  notificationManager.createNotificationChannel(notificationChannel);
}

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
  .setVibrate(new long[]{0, 100, 100, 100, 100, 100})
  .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
  .setSmallIcon(R.mipmap.ic_launcher)
  .setContentTitle("Content Title")
  .setContentText("Content Text");

  notificationManager.notify(NOTIFICATION_ID, builder.build());

A couple of important notes:

  1. Settings such as vibration pattern specified in the NotificationChannel override those specified in the actual Notification. I know, its counter-intuitive. You should either move settings that will change into the Notification, or use a different NotificationChannel for each configuration.
  2. You cannot modify most of the NotificationChannel settings after you've passed it to createNotificationChannel(). You can't even call deleteNotificationChannel() and then try to re-add it. Using the ID of a deleted NotificationChannel will resurrect it, and it will be just as immutable as when it was first created. It will continue to use the old settings until the app is uninstalled. So you had better be sure about your channel settings, and reinstall the app if you are playing around with those settings in order for them to take effect.


回答3:

All that @sky-kelsey has described is good, Just minor additions:

You should not register same channel every time if it has been already registered, so I have Utils class method that creates a channel for me:

public static final String NOTIFICATION_CHANNEL_ID_LOCATION = "notification_channel_location";

public static void registerLocationNotifChnnl(Context context) {
    if (Build.VERSION.SDK_INT >= 26) {
        NotificationManager mngr = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
        if (mngr.getNotificationChannel(NOTIFICATION_CHANNEL_ID_LOCATION) != null) {
            return;
        }
        //
        NotificationChannel channel = new NotificationChannel(
                NOTIFICATION_CHANNEL_ID_LOCATION,
                context.getString(R.string.notification_chnnl_location),
                NotificationManager.IMPORTANCE_LOW);
        // Configure the notification channel.
        channel.setDescription(context.getString(R.string.notification_chnnl_location_descr));
        channel.enableLights(false);
        channel.enableVibration(false);
        mngr.createNotificationChannel(channel);
    }
}

strings.xml:

<string name="notification_chnnl_location">Location polling</string>
<string name="notification_chnnl_location_descr">You will see notifications on this channel ONLY during location polling</string>

And I call the method every time before I'm going to show a notification of the type:

    ...
    NotificationUtil.registerLocationNotifChnnl(this);
    return new NotificationCompat.Builder(this, NotificationUtil.NOTIFICATION_CHANNEL_ID_LOCATION)
            .addAction(R.mipmap.ic_launcher, getString(R.string.open_app),
                    activityPendingIntent)
            .addAction(android.R.drawable.ic_menu_close_clear_cancel, getString(R.string.remove_location_updates),
                    servicePendingIntent)
            .setContentText(text)
            ...

Another typical problem - channel default sound - described here: https://stackoverflow.com/a/45920861/2133585



回答4:

In Android O it's a must to use a NotificationChannel and NotificationCompat.Builder is deprecated (reference).

Below is a sample code :

NotificationCompat.Builder mBuilder =
        new NotificationCompat.Builder(mContext.getApplicationContext(), "notify_001");
Intent ii = new Intent(mContext.getApplicationContext(), RootActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, ii, 0);

NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle();
bigText.bigText(verseurl);
bigText.setBigContentTitle("Today's Bible Verse");
bigText.setSummaryText("Text in detail");

mBuilder.setContentIntent(pendingIntent);
mBuilder.setSmallIcon(R.mipmap.ic_launcher_round);
mBuilder.setContentTitle("Your Title");
mBuilder.setContentText("Your text");
mBuilder.setPriority(Notification.PRIORITY_MAX);
mBuilder.setStyle(bigText);

NotificationManager mNotificationManager =
        (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    NotificationChannel channel = new NotificationChannel("notify_001",
            "Channel human readable title",
            NotificationManager.IMPORTANCE_DEFAULT);
    mNotificationManager.createNotificationChannel(channel);
}

mNotificationManager.notify(0, mBuilder.build());