44

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.

JerabekJakub
  • 5,268
  • 4
  • 26
  • 33
Sky Kelsey
  • 19,192
  • 5
  • 36
  • 77
  • 1
    That error has nothing to do with why your notification doesn't show. Please include your full `NotificationCompat` code you are using and your `targetSdkVersion`. – ianhanniballake Jul 30 '17 at 02:31
  • I originally planned to answer my own question, with the quoted error being what others would search for. Now I realize the error has nothing to do with the fact that it didn't show. It's because I didn't have a NotificationChannel. Android should be logging when it can't show a notification, or throw an exception or something. – Sky Kelsey Jul 30 '17 at 04:15
  • Related post - [NotificationCompat.Builder doesn't accept 2nd argument](https://stackoverflow.com/q/50765964/465053) – RBT Sep 03 '18 at 04:50

4 Answers4

63

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.

Community
  • 1
  • 1
ianhanniballake
  • 191,609
  • 30
  • 470
  • 443
  • Thanks @ianhanniballake. I'm curious why NotificationChannels can't be modified after they are created. I get that a user can override the configuration to, for instance, lower importance on the channel, but if they haven't done so, why prevent the app from modifying the channel? – Sky Kelsey Jul 30 '17 at 03:28
  • What if users went into the settings, confirmed they were appropriate, and then you later changed them? Setting the user expectation that they never change unless they themselves change it is a useful gaurantee. – ianhanniballake Jul 30 '17 at 03:47
  • Why not keep a copy of the configured settings, and the settings specified by the user, if they have changed them. For each setting that changed, apply it on top of the NotificationChannel configuration. Otherwise let them change. The current behavior makes it hard to test things out, and it's crazy to think that the moment you register a channel, it's set in stone for the life of the app. Like you can never change that channel. You just have to move on and create a new one -- which is exactly what app developers will do, and then you are essentially back to users not having control. – Sky Kelsey Jul 30 '17 at 04:10
  • You are going to see users frustrated that notifications they have hidden in the past are back. Devs who are trying to do the right thing will not be able to do anything about that, but users will blame Android as being buggy. – Sky Kelsey Jul 30 '17 at 04:12
  • Android O is finalized. Please feel free to add a [feature request](http://issuetracker.google.com) for a future version of Android. – ianhanniballake Jul 30 '17 at 04:27
  • I created an issue a while back to track this: https://issuetracker.google.com/issues/64180616 – Sky Kelsey Oct 09 '17 at 18:57
48

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.
Sky Kelsey
  • 19,192
  • 5
  • 36
  • 77
  • "You should either move settings that will change into the Notification, or..." -- Does that work? Or does the NotificationChannel have (overriding) default settings for vibration pattern etc. even if you didn't set them? – Jerry101 Aug 07 '17 at 04:42
  • I think that at least for some of the settings that are optional, leaving them unset in the channel config allows the Notification's settings to take precedence. – Sky Kelsey Aug 21 '17 at 16:35
  • 1
    Well, that hypothesis did not pan out. Leaving a channel parameter unset has the effect of selecting the default notification sound, Public LockscreenVisibility, Vibration off, or Notification light off. And once the app creates a channel, the user can see and change its settings even before the app creates any notifications. – Jerry101 Aug 25 '17 at 07:52
8

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

Kirill Vashilo
  • 1,559
  • 1
  • 18
  • 27
2

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());
Md Imran Choudhury
  • 9,343
  • 4
  • 62
  • 60