34

I have a custom mp3 sound that I use on my notifications. It works fine on all devices below API 26. I tried to set the sound on Notification Channel also, but still no work. It plays the default sound.

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId)
            .setAutoCancel(true)
            .setSmallIcon(R.drawable.icon_push)
            .setColor(ContextCompat.getColor(this, R.color.green))
            .setContentTitle(title)
            .setSound(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.notification))
            .setDefaults(Notification.DEFAULT_VIBRATE)
            .setStyle(new NotificationCompat.BigTextStyle().bigText(message))
            .setContentText(message);
        Notification notification = builder.build();
        NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT);
            AudioAttributes audioAttributes = new AudioAttributes.Builder()
                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                    .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
                    .build();
            channel.setSound(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.notification), audioAttributes);
            notificationManager.createNotificationChannel(channel);
        }
        notificationManager.notify(1, notification);
Fakhriddin Abdullaev
  • 4,169
  • 2
  • 35
  • 37
Rodrigo Manguinho
  • 1,411
  • 3
  • 21
  • 27
  • did you make the default notification sound mute? i am also facing same problem. i dont want to play any tone on notification with NotificationManager.IMPORTANCE_MAX. Can you please help me in this. – BHARAT GUPTA Jan 02 '18 at 09:53
  • The only way i got this to work was with RingtoneManager, but I removed it from my code. With RingtoneManager users can't mute notifications. My app is using the default sound on Android 8. I still don't know how to make custom sound work with channels. – Rodrigo Manguinho May 21 '18 at 21:16

6 Answers6

52

You may have created the channel originally with default sound. Once channel is created it cannot be changed. You need to either reinstall the app or create channel with new channel ID.

Paweł Nadolski
  • 8,296
  • 2
  • 42
  • 32
  • 2
    To alter the importance, sound, lights, vibration, lock screen, or DND setting uninstall the app and install again to clear the channel. See https://developer.android.com/guide/topics/ui/notifiers/notifications.html#ManageChannels, esp section titled "Deleting a notification channel" – BitByteDog Nov 21 '17 at 06:25
  • This enlightened me to ditch all the existing channels and create a "ChannelManager" to manage channels and setup during app initialization. – Vishnu Haridas Mar 31 '19 at 19:51
  • That's weird. Isn't user is allowed to change Channel notification sound in settings ? – neobie Oct 22 '19 at 17:29
  • @neobie if you use default ringtones like `RingtoneManager.TYPE_ALARM` then yes, user can change it in settings. But the OP used custom sound. – Vadim Kotov Dec 30 '19 at 11:38
16

I used RingtoneManager, and it is work for me. Try thius code:

 NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this);
    builder.setSmallIcon(android.R.drawable.ic_dialog_alert);
    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com/"));
    PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 0, intent, 0);
    builder.setContentIntent(pendingIntent);
    builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
    builder.setContentTitle("Notification title");
    builder.setContentText("Notification message.");
    builder.setSubText("Url link.");

    try {
        Uri notification = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.custom_ringtone);
        Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
        r.play();
    } catch (Exception e) {
        e.printStackTrace();
    }

    NotificationManager notificationManager = (NotificationManager) this.getSystemService(NOTIFICATION_SERVICE);
    notificationManager.notify(1, builder.build());
Fakhriddin Abdullaev
  • 4,169
  • 2
  • 35
  • 37
  • In my experience that is replaying the sound over and over. – Hosein Hamedi Dec 16 '17 at 08:21
  • 7
    The problem with this solution is that users cannot mute the notification sound. It always plays the sound. – Rodrigo Manguinho Jan 10 '18 at 13:02
  • 4
    `NotificationCompat.Builder(Context)` is depreacted, notifications must specify a NotificationChannel Id using `NotificationCompat.Builder(context, String)`. So it's not the best solution for Oreo / API 26. – Mudar Jan 31 '18 at 23:09
  • 3
    I wonder why the `setSound` function doesn't work? As said in documentation the importance of the notification channel must be at least `IMPORTANCE_HIGH` to play a sound. But it does not work anyway – Nolesh Apr 12 '18 at 05:13
  • @Nolesh on your code has builder.setDefault() function? If you use it you can't set custom sounf on notification, it get default notification sound. notificationBuilder.setDefaults(Notification.DEFAULT_LIGHTS) .setVibrate(new long[]{0L}); – Fakhriddin Abdullaev Apr 12 '18 at 07:50
  • @FaxriddinAbdullayev, nope. It doesn't have `setDefault` function. – Nolesh Apr 12 '18 at 23:50
  • notificationBuilder.setDefaults(Notification.DEFAULT_LIGHTS) .setVibrate(new long[]{0L}); Add above code please. I hope it will help you – Fakhriddin Abdullaev Apr 12 '18 at 23:56
  • 1
    @FaxriddinAbdullayev, it doesn't work. Moreover, `setDefaults` is deprecated in `Oreo`. – Nolesh Apr 17 '18 at 00:22
  • 4
    This question is aimed at API 26, but this answer did not even mention NotificationChannel. You won't receive a notification on Android 8.0+ devices at all, not even mention change the sound of notification. – Chandler Oct 05 '18 at 21:54
2

In Oreo you need to create a channel for that. https://developer.android.com/reference/android/app/NotificationChannel.html

Chris
  • 87
  • 3
  • 7
1

The default sound overrides any sound.

You need to put this in your code:

notification.defaults = Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE;

Reference:

Android notifications

Şafak Gezer
  • 3,928
  • 3
  • 47
  • 49
Towfik Alrazihi
  • 536
  • 3
  • 8
  • 25
0

In addition to the Faxriddin's answer you can determine when you should to turn off the notification sound by checking the importance of the notification channel and are enabled notifications parameters.

NotificationChannel channel = notificationManager.getNotificationChannel(NOTIFICATION_CHANNEL_ID);
if(notificationManager.areNotificationsEnabled() && channel.getImportance() != NotificationManager.IMPORTANCE_NONE) {
  try {
     Ringtone r = RingtoneManager.getRingtone(ctx, soundUri);
     r.play();
  } catch (Exception e) { }
}
Nolesh
  • 6,848
  • 12
  • 75
  • 112
0

I've been developing app with similar functionality. And as mentioned Paweł Nadolski we have to recreate channel each time to change ringtone. For this I wrote helper. Hope it can help someone.

@RequiresApi(Build.VERSION_CODES.O)
object ChannelHelper {
    // channel id for 8.0 OS version and higher
    private const val OREO_CHANNEL_ID = "com.ar.app.notifications"
    private const val CHANNEL_ID_PREF = "com.ar.app.notifications_prefs"

    @JvmStatic
    fun createChannel(context: Context, playSound: Boolean, isVibrated: Boolean, uri: Uri) {
        // establish name and importance of channel
        val name = context.getString(R.string.main_channel_name)
        val importance = if (playSound) {
            NotificationManager.IMPORTANCE_DEFAULT
        } else {
            NotificationManager.IMPORTANCE_LOW
        }

        // create channel
        val channelId = OREO_CHANNEL_ID + UUID.randomUUID().toString()
        saveChannelId(context, channelId)

        val channel = NotificationChannel(channelId, name, importance).apply {
            enableLights(true)
            lightColor = Color.GREEN

            lockscreenVisibility = Notification.VISIBILITY_PUBLIC

            // add vibration
            enableVibration(isVibrated)
            vibrationPattern = longArrayOf(0L, 300L, 300L, 300L)

            // add sound
            val attr = AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
                    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                    .build()

            setSound(uri, attr)
        }

        // register the channel in the system
        val notificationManager = context.getSystemService(NotificationManager::class.java)
        notificationManager.createNotificationChannel(channel)
    }

    @JvmStatic
    fun rebuildChannel(context: Context, playSound: Boolean, isVibrated: Boolean, uri: Uri) {
        val notificationManager = context.getSystemService(NOTIFICATION_SERVICE)
                as NotificationManager
        notificationManager.deleteNotificationChannel(
            getChannelId(context) ?: OREO_CHANNEL_ID
        )

        createChannel(context, playSound, isVibrated, uri)
    }

    @JvmStatic
    fun getChannel(context: Context): NotificationChannel? {
        val notificationManager = context.getSystemService(NOTIFICATION_SERVICE)
                as NotificationManager

        return notificationManager.getNotificationChannel(
                getChannelId(context) ?: OREO_CHANNEL_ID
        )
    }

    @JvmStatic
    fun isChannelAlreadyExist(context: Context) = getChannel(context) != null

    @JvmStatic
    fun getChannelId(context: Context) =
            PreferenceManager.getDefaultSharedPreferences(context)
                    .getString(CHANNEL_ID_PREF, OREO_CHANNEL_ID)

    private fun saveChannelId(context: Context, channelId: String) =
            PreferenceManager.getDefaultSharedPreferences(context)
                    .edit()
                    .putString(CHANNEL_ID_PREF, channelId)
                    .apply()
}
Artem Botnev
  • 2,267
  • 1
  • 14
  • 19