28
Uri sound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName() + "/" + R.raw.notification_mp3);
            mBuilder.setSound(sound);

I had copied the mp3 (notification_mp3.mp3) file into the raw folder in the res folder. When the notification is triggered it produces given mp3 sound upto Android Nougat but default sound in Android Oreo. I had referred many sites but nothing worked on Android Oreo. I didn't find any changes in Android Docs regarding notification sound in Android O & above. What changes should be done to make this code working in Android O too?

Anshika Bansal
  • 320
  • 2
  • 9
Ashish John
  • 1,867
  • 2
  • 23
  • 38

9 Answers9

57

To set a sound to notifications in Oreo, you must set sound on NotificationChannel and not on Notification Builder itself. You can do this as follows

Uri sound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName() + "/" + R.raw.notification_mp3);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

        NotificationChannel mChannel = new NotificationChannel("YOUR_CHANNEL_ID",
            "YOUR CHANNEL NAME",
            NotificationManager.IMPORTANCE_DEFAULT)

        AudioAttributes attributes = new AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_NOTIFICATION)
                .build();

        NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, 
                context.getString(R.string.app_name),
                NotificationManager.IMPORTANCE_HIGH);

        // Configure the notification channel.
        mChannel.setDescription(msg);
        mChannel.enableLights(true);
        mChannel.enableVibration(true);
        mChannel.setSound(sound, attributes); // This is IMPORTANT


        if (mNotificationManager != null)
            mNotificationManager.createNotificationChannel(mChannel);
    }

This will set a custom sound to your notifications. But if the app is being updated and the notification channel is used before, it won't be updated. i.e. you need to create a different channel and set sound to it to make it work. But this will show multiple channels in the notifications section of app info of your app. If you are setting sound to an entirely new channel that is fine, but if you want the channel being used before, you have to delete the existing channel and recreate the channel. To do that you can do something like that before creating channel

if (mNotificationManager != null) {
            List<NotificationChannel> channelList = mNotificationManager.getNotificationChannels();

            for (int i = 0; channelList != null && i < channelList.size(); i++) {
                mNotificationManager.deleteNotificationChannel(channelList.get(i).getId());
            }
        }
Ankush
  • 1,888
  • 20
  • 22
  • 1
    it's working perfectly, but only when app is in foreground. I stil have the default sound when app is in backgroun(for oreo). Do you have a solution for that? – Najoua Mahi Sep 10 '18 at 13:13
  • @NajouaMahi Are you using Firebase Push Notifications? – Ankush Sep 11 '18 at 04:55
  • yes i'm using Firebase, they offer meta-data for default notification icon and color if none of them exists, but I didn't find a meta-data for sound.Can you help please! – Najoua Mahi Sep 11 '18 at 13:26
  • 2
    Have a look at this answer https://stackoverflow.com/a/37845174/2577750 – Ankush Sep 12 '18 at 04:48
  • 2
    Yes we need to send data messages, thank you Ankush, that helped – Najoua Mahi Sep 12 '18 at 08:02
  • I am facing same type of problem on my case everything is working fine except the custom sound when application in background or kill. Can you suggest any solution. – Biswanath Maity Sep 27 '18 at 15:05
  • @BiswanathMaity Have a look at this answer stackoverflow.com/a/37845174/2577750 – Ankush Sep 27 '18 at 18:29
  • 2
    When creating the notification channel after deleting it, the system uses the old channel settings only. Anyone who has been able to change the sound of the notification channel using the above method, can you comment if anything else needs to be done. – Tulika Jun 03 '19 at 08:02
  • 6
    Don't forget you need to reinstall the app otherwise it recycles the old notification channels some how – Daniel Wilson Nov 05 '19 at 11:19
  • 1
    Unfortunately I tried lots of solution and this too but I am getting same default notification tone not custom anyone help?(I have copy pasted above code changed channel id also and then reinstalled it several times but still problem is not solved – Nilesh Lathe Aug 05 '21 at 20:23
  • In Android Oreo and above. even deleting the channels and recreating them, is not working. In any case, you have to go for the new channels only. – Abhinav Suman Jun 30 '22 at 12:02
  • @DanielWilson in dev environment we can easily resinstall and it works too! but what happens for play store version? will the next update automatically refresh notification channels? – Shikhar Feb 02 '23 at 08:24
5

This might help the new comers.

Here is a code for a working notification sample on all android versions with all kinds of possible setups.

1 -> sound and vibration
2 -> sound but no vibration
3 -> no sound but vibration
4 -> no sound no vibration

OUTPUT

enter image description here

Github Repo -> https://github.com/usman14/Notification

CODE

MainActivity

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.Switch;

public class MainActivity extends AppCompatActivity {

    public boolean shouldSound;
    public boolean shouldVibrate;
    NotificationManager notificationManager;

    Button button;
    Switch soundSwitch;
    Switch vibrationSwitch;

    @TargetApi(Build.VERSION_CODES.O)
    public void registerNormalNotificationChannel(android.app.NotificationManager notificationManager) {

        NotificationChannel channel_all = new NotificationChannel("CHANNEL_ID_ALL", "CHANNEL_NAME_ALL", NotificationManager.IMPORTANCE_HIGH);
        channel_all.enableVibration(true);
        notificationManager.createNotificationChannel(channel_all);

        NotificationChannel channel_sound = new NotificationChannel("CHANNEL_ID_SOUND", "CHANNEL_NAME_ALL", NotificationManager.IMPORTANCE_HIGH);
        channel_sound.enableVibration(false);
        notificationManager.createNotificationChannel(channel_sound);

        NotificationChannel channel_vibrate = new NotificationChannel("CHANNEL_ID_VIBRATE", "CHANNEL_NAME_ALL", NotificationManager.IMPORTANCE_HIGH);
        channel_vibrate.setSound(null, null);
        channel_vibrate.enableVibration(true);
        notificationManager.createNotificationChannel(channel_vibrate);


        NotificationChannel channel_none = new NotificationChannel("CHANNEL_ID_NONE", "CHANNEL_NAME_ALL", NotificationManager.IMPORTANCE_HIGH);
        channel_none.setSound(null, null);
        channel_none.enableVibration(false);
        notificationManager.createNotificationChannel(channel_none);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = findViewById(R.id.btn);
        soundSwitch = findViewById(R.id.switch_sound);
        vibrationSwitch = findViewById(R.id.switch_vibration);
        notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        if (isOreoOrAbove()) {
            setupNotificationChannels();
        }

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                makeNotification();
            }
        });

        soundSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                if (b) {
                    shouldSound = true;
                } else {
                    shouldSound = false;
                }
            }
        });

        vibrationSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                if (b) {
                    shouldVibrate = true;
                } else {
                    shouldVibrate = false;
                }
            }
        });
    }

    private void setupNotificationChannels() {
        registerNormalNotificationChannel(notificationManager);
    }

    public void makeNotification() {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this, getChannelId())
                .setContentTitle("Hi")
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentText("Welcome to Android");

        Intent intent = new Intent(MainActivity.this, MainActivity.class);

        PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        builder.setContentIntent(pendingIntent);
        if (shouldSound && !shouldVibrate) {
            builder.setDefaults(Notification.DEFAULT_SOUND)
                    .setVibrate(new long[]{0L});
        }
        if (shouldVibrate && !shouldSound) {
            builder.setDefaults(Notification.DEFAULT_VIBRATE)
                    .setSound(null);
        }
        if (shouldSound && shouldVibrate) {
            builder.setDefaults(Notification.DEFAULT_ALL);
        }


        notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0, builder.build());
    }

    private String getChannelId() {
        if (shouldSound && shouldVibrate) {
            return "CHANNEL_ID_ALL";
        } else if (shouldSound && !shouldVibrate) {
            return "CHANNEL_ID_SOUND";
        } else if (!shouldSound && shouldVibrate) {
            return "CHANNEL_ID_VIBRATE";
        } else {
            return "CHANNEL_ID_NONE";
        }
    }

    private boolean isOreoOrAbove() {
        return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O;
    }
}

activity_main (xml)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">



    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:id="@+id/sound_layout"
        android:orientation="horizontal"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="SOUND SWITCH"></TextView>


        <Switch
            android:layout_marginLeft="50dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:id="@+id/switch_sound">

        </Switch>

    </LinearLayout>

    <LinearLayout
        android:id="@+id/vibration_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/sound_layout">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="VIBRATION SWITCH"></TextView>


        <Switch
            android:layout_marginLeft="50dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:id="@+id/switch_vibration">

        </Switch>

    </LinearLayout>


    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Send Notification"
        android:id="@+id/btn"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/vibration_layout"></Button>

</androidx.constraintlayout.widget.ConstraintLayout>
Usman Zafer
  • 1,261
  • 1
  • 10
  • 15
  • Hey , I have an [issue](https://stackoverflow.com/questions/71809011/how-to-change-notification-sound-in-android-7-1) with Android 7 which is the channels are not supposed to be working there, so is there a way to change the notifications sound for it? – Oliver D Apr 10 '22 at 07:12
0

Create a channel (I use this method in Application.clss to create the channel )

  public void initChannels(Context context) {
    if (Build.VERSION.SDK_INT < 26) {
        return;
    }
    NotificationManager notificationManager =
            (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    NotificationChannel channel = new NotificationChannel("default"/*CHANNEL ID*/,
            "CHANNEL_NAME",
            NotificationManager.IMPORTANCE_DEFAULT);
    channel.setDescription("Channel description");
    assert notificationManager != null;
    notificationManager.createNotificationChannel(channel);
}

And use this channel default while creating instance of NotificationCompat

 .... notificationBuilder = new NotificationCompat.Builder(this,"default") ....
Jay Thummar
  • 2,281
  • 1
  • 14
  • 22
0
mBuilder.setPriority(NotificationCompat.PRIORITY_HIGH)

This line of code is worked for me. But you have to delete old channel and create new one.

0

Hi, Mates firstly to use a the default notification sound of the device, add the following.

Uri uri = getDefaultUri(TYPE_NOTIFICATION); // To get the URI of default notification uri
AudioAttributes audioAttributes = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build();

And then, sorry this may sound silly. But you also need to make sure the device has a default notification and sound set to something other than none. I believe it is quite easy to overlook.

Cheerio!

Jagadish Nallappa
  • 814
  • 1
  • 10
  • 11
0

A note might help in emulator testing.

don't forget to enable alarm sound as highlighted below:- enter image description here

0

For those its not working make sure send Channel Id and Sound Name

 "notification" : {
      "body" : "Pass body here",
      "title" : "Title For Notification",
      "icon" : " icon ",
      "sound" : "my_alert.mp3" //Important
    }

and also channel id in payload from your server

"channel_id": "myapp_notification_channel", // important

Make sure to pass same channel id to builder

//pre oreo
 builder = NotificationCompat.Builder(applicationContext, channelId)

//oreo
     val notificationChannel =
                    NotificationChannel(channelId, "my_app", NotificationManager.IMPORTANCE_HIGH)

Make sure you same file is res/raw/my_alert.mp3

and use below method , don't user R.id.my_alert use as below

val alertSound = Uri.parse("${ContentResolver.SCHEME_ANDROID_RESOURCE}://${this.packageName}/raw/my_alert")

// and set like this
notificationChannel.setSound(alertSound, Notification.AUDIO_ATTRIBUTES_DEFAULT)
Char
  • 11
  • 2
-1

Android O comes with NotificationChannel use that instead

 int importance = NotificationManager.IMPORTANCE_HIGH;
            NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "NOTIFICATION_CHANNEL_NAME", importance);
            notificationChannel.enableLights(true);
            notificationChannel.setLightColor(Color.RED);
            notificationChannel.enableVibration(true);
            notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
            assert mNotificationManager != null;
            mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
            mNotificationManager.createNotificationChannel(notificationChannel);
Nawrez
  • 3,314
  • 8
  • 28
  • 42
-1

try this:

/**
 * show notification
 *
 * @param message
 */
private static void showNotification(RemoteMessage message, Context baseContext) {
    Context context = baseContext.getApplicationContext();
    NotificationManagerCompat managerCompat = NotificationManagerCompat.from(context.getApplicationContext());
    NotificationCompat.Builder builder = new NotificationCompat.Builder(context, null)
            .setSmallIcon(R.drawable.ic_logo_xxxdpi)
            .setContentTitle(message.getData().get(TITLE))
            .setContentText(message.getData().get(BODY))
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setAutoCancel(true)
            .setVibrate(new long[]{500, 500})
            .setLights(Color.RED, 3000, 3000)
            .setSound(Settings.System.DEFAULT_NOTIFICATION_URI)
            .setContentIntent(getPendingIntent(context, message));
    managerCompat.notify(getRandom(), builder.build());
}