Custom Notification Sound not working in Android Oreo

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>

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());
            }
        }