How to use Custom Notification Sounds on Android?
On Android 8.0 and higher, notification sounds are managed using Notification Channels. Users can reconfigure those channels. You control the default settings (including the sound and importance), but users can change them at any time. The system always applies the user-defined configuration.
Batch automatically registers a default channel when displaying the first notification if no channel override is set. You cannot change the sound of this channel. You must implement your own channel to define a custom sound.
You must declare your notification channels before sending notifications. Register them during your application’s startup phase. Then, configure Batch to use them by overriding the default channel or by implementing a NotificationChannelIdInterceptor
.
Once a channel has been created, you cannot update it. To change the notification sound, you must create a new channel. During development, uninstall and reinstall your application if changes do not apply after updating your code.
Change the Default Sound
To change the default notification sound:
Create your own notification channel and register it with Android.
Implement Multiple Sounds Based on the Notification Payload
To implement multiple notification sounds:
Create multiple notification channels (one per sound).
Implement a
NotificationChannelIdInterceptor
and return the appropriate channel based on the custom payload.
Ensure backwards compatibility
Notification channels are not available on versions earlier than Android 8.0. You must implement a NotificationInterceptor
to change the notification sound.
Code example
This code implements multiple notification sounds based on the payload content:
A payload of
{ "channel": "win" }
playssound_win
from raw resources.A payload of
{ "channel": "defeat" }
playssound_defeat
from raw resources.Any other value falls back on Batch's default channel.
This snippet works on Android 4.1 and higher. It uses a notification interceptor for devices that do not support channels:
public class MyApplication extends Application {
public static final String CHANNEL_WIN = "win";
public static final String CHANNEL_DEFEAT = "defeat";
public static final String SOUND_RESOURCE_WIN = "sound_win";
public static final String SOUND_RESOURCE_DEFEAT = "sound_defeat";
@Override
public void onCreate() {
super.onCreate();
// This code should be in your Application subclass' onCreate, not in your Activity's! It is required so that Batch can call your interceptor while your app is in the background
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
setupNotificationChannels(this);
setupBatchChannelInterceptor();
} else {
setupLegacyBatchSoundInterceptor();
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void setupNotificationChannels(@NonNull Context context) {
// This sample assumes that your sounds are named "sound_win"/"sound_defeat"
// and placed in the "raw" resource folder.
AudioAttributes soundAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build();
@SuppressLint("WrongConstant")
NotificationChannel winChannel = new NotificationChannel(
CHANNEL_WIN,
"Win notifications",
NotificationManager.IMPORTANCE_DEFAULT);
winChannel.setSound(getUriForSoundName(context, SOUND_RESOURCE_WIN), soundAttributes);
@SuppressLint("WrongConstant")
NotificationChannel defeatChannel = new NotificationChannel(
CHANNEL_DEFEAT,
"Defeat notifications",
NotificationManager.IMPORTANCE_DEFAULT);
defeatChannel.setSound(getUriForSoundName(context, SOUND_RESOURCE_DEFEAT), soundAttributes);
NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(winChannel);
notificationManager.createNotificationChannel(defeatChannel);
}
@NonNull
private Uri getUriForSoundName(@NonNull Context context, @NonNull String soundName) {
return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName()
+ "/raw/" + soundName);
}
private void setupBatchChannelInterceptor() {
Batch.Push.getChannelsManager().setChannelIdInterceptor((payload, deductedChannelId) -> {
// custom payload: {"channel":"win"}/{"channel":"defeat"}
String channel = payload.getPushBundle().getString("channel");
switch (channel) {
case "win":
return CHANNEL_WIN;
case "defeat":
return CHANNEL_DEFEAT;
}
return deductedChannelId;
});
}
private void setupLegacyBatchSoundInterceptor() {
Batch.Push.setNotificationInterceptor(new BatchNotificationInterceptor() {
@Override
public NotificationCompat.Builder getPushNotificationCompatBuilder(@NonNull Context context,
@NonNull NotificationCompat.Builder defaultBuilder,
@NonNull Bundle pushIntentExtras,
int notificationId) {
String sound = pushIntentExtras.getString("channel", null);
Uri soundUri = null;
switch (sound) {
case "win":
soundUri = getUriForSoundName(context, SOUND_RESOURCE_WIN);
break;
case "defeat":
soundUri = getUriForSoundName(context, SOUND_RESOURCE_DEFEAT);
break;
}
if (soundUri != null) {
defaultBuilder.setSound(soundUri);
}
return defaultBuilder;
}
});
}
}
Last updated
Was this helpful?