4

It is possible to play a custom notification sound when an App is in foreground, by supplying a sound file in a resources/raw folder, and then when reacting to the notification, doing something along the lines of :

Android.Net.Uri notification = Android.Net.Uri.Parse("android.resource://" + Application.Context.PackageName + "/raw/thesoundfile");                       
Ringtone rt = RingtoneManager.GetRingtone(a, notification);
rt.Play();

However. Obviously, this will not get executed when the App is in the background, and the OS will still play a (default) notification sound when the notification arrives.

How do I programmatically, set this "background" notification sound, to be the same as the custom one which is played in foreground?

I looked at the "duplicate" question that was used to close this post. That question was asked over 7 years ago when Android was still in version Jelly Bean (4.1 - 4.3.1). What worked over 7 years ago doesn't always work today. That answer is outdated and will not work on version Oreo (10).

Kuya
  • 7,280
  • 4
  • 19
  • 31
MHugh
  • 455
  • 1
  • 7
  • 20

1 Answers1

6

Firstly make the folder in Resource (res) name it raw and put the file (YOUR_SOUND_FILE.MP3) in it and than use below lines of code for custom sound

NotificationManager notificationManager = (NotificationManager) context
        .getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, message, when);

String title = context.getString(R.string.app_name);

Intent notificationIntent = new Intent(context,
        SlidingMenuActivity.class);
notificationIntent.putExtra("isInbox", true);
// set intent so it does not start a new activity
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
        | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(context, 0,
        notificationIntent, 0);
notification.setLatestEventInfo(context, title, message, intent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;

Use these lines of code for custom sound

 notification.sound =Uri.parse("android.resource://"+context.getPackageName()+"/"+R.raw.FILE_NAME);//Here is FILE_NAME is the name of file that you want to play


// Vibrate if vibrate is enabled
notification.defaults |= Notification.DEFAULT_VIBRATE;
notificationManager.notify(0, notification);

For the Oreo and higher , you need to check the SDK_VERSION and use the setSound method of the NotificationChannel

   Uri sound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName() + "/" + R.raw.FILE_NAME);  //Here is FILE_NAME is the name of file that you want to play

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


//for pre-oreo mobiles
{
 NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentTitle(context.getString(R.string.app_name))    .setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, MainActivity_.class), 0))
            .setContentText("temporary text")
            .setAutoCancel(true)
           .setSound(Uri.parse("android.resource://"
                            + context.getPackageName() + "/"
                            + R.raw.alert))
            .setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE)
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setWhen(System.currentTimeMillis())
            .setSmallIcon(R.drawable.ic_stat_notification);

    Notification notification = builder.build();
    NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(NOTIFICATION_ID, notification);
}
Abraham Baby
  • 104
  • 6
  • 1
    Thanks for this. I now have the Post-Oreo working OK, but can you clarify what triggers the two blocks of code for the pre oreo examples? Can you explain how I can get "Pre-Oreo" versions of Android working with my App so that they play the custom sound when the App is in the background? – MHugh Nov 25 '19 at 16:26
  • I assume that this code would typically be run in an Activitiy's OnCreate(). How would one use the approach above to selectively play different sound files, based upon the type of notification received. I assume that because no code can actually execute for a background alert notification, there is a limitation that only one sound file can be played, as defined at the time the above code is initialised ? – MHugh Nov 27 '19 at 06:34
  • 1
    Any comments please on whether it is possible to play more than one custom sound, pre Oreo, when App is in the background. i.e. play a different sound based upon the notification content, as is possible post oreo by using multiple channels ? – MHugh Nov 28 '19 at 09:19
  • 1
    Doesn't the last line of the pre-oreo code actually fire off a local notification? Presumably we should not be doing that when we are initialising things for later when a remote notification actually arrives and we are in background. – MHugh Nov 28 '19 at 09:32
  • 1
    Also note that NotificationCompat is "obsolete and deprecated" :-( – MHugh Nov 28 '19 at 09:33
  • Yes it is deprecated; BUT only for Oreo and above. If your app is not targeting anything below build version O the `} else {` statement can be left out; HOWEVER, if you intend for your app to run on pre-Oreo devices, it needs to be there. – Kuya Aug 20 '20 at 07:36