Recently I use notification channel to support android O.
But the problem is I cannot change the sound Uri dynamically.
Our app have notification sound setting which user can change app notification sound as they want.
But as you know, Android now do not allow developer to update notification channel before user reinstall app.
There I consider several possible solutions which is not looks good.
User ringtone manager to play ringtone instead of setSound. But when user disable notification in app setting, still ringtone will not stop playing. (This will be bad user experience)
Delete notification channel and create new one when user change ringtone sound. But this also looks bad because in app setting google shows the history of deleted channel info.(Actually not necessary)
Is there any good solution?
On Android O+ devices, you should remove any notification specific settings within your app and offer a link within your settings screen to open the system's notification channel settings, where the user can adjust the sound of the notification channel directly.
#RequiresApi(api = Build.VERSION_CODES.O)
private void createChannels() {
Nmanager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
AudioAttributes attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build();
ArrayList arrayList = new ArrayList<String>();
Field[] fields = R.raw.class.getFields();
for (int i = 1; i < fields.length - 1; i++) {
arrayList.add(fields[i].getName());
}
DBRingtone RDB = new DBRingtone(this);
Cursor cursor = RDB.getringtone();
if (cursor.getCount() > 0) {
int ring = parseInt(cursor.getString(0));
resID = getResources().getIdentifier((String) arrayList.get(ring), "raw", getPackageName());
i=i+resID;
uri = Uri.parse("android.resource://" + getPackageName() + "/" + resID);
} else
{
i=i+10;
uri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.default_sound);
}
CHANNEL_ID = CHANNEL_ID+i;
notificationChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
notificationChannel.enableLights(true);
notificationChannel.enableVibration(true);
notificationChannel.setDescription("Your message");
notificationChannel.setLightColor(Color.RED);
notificationChannel.setSound(uri, attributes);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
Nmanager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Nmanager.createNotificationChannel(notificationChannel);
}
Hello all, I have solved this problem using the above code and it's working. You can also assign CHANNEL_ID = CHANNEL_ID+resID directly to. For the purpose i have assigned using variable i. I have stored the user preferred Notification sounds resID is SQLite database and In the createchannels class i have retrieved that resID using cursor to create the uri's path.Hope this will help you Thank you...
Related
When the notification comes it plays a sound but it's not my custom sound. Here's my code to set the sound of the Channel. What do I need to change?
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Uri ringtone = Uri.parse("android.resource://" + getApplicationContext().getPackageName()+"/" +R.raw.videocall);
CharSequence name = getString(R.string.channel_name);
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel(CustomFirebaseMessagingService.CHANNEL_ID, name, importance);
channel.setDescription(description);
AudioAttributes.Builder audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE);
channel.setSound(ringtone,audioAttributes.build());
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
Log.d(MainActivity.TAG, "Created notification channel");
}
}
OK I didn't need to change the code. I think Android somehow cached the old sound. To fix I simply changed the channel id when creating the NotificationChannel to something else so Android woudn't use the cached sound file.
I have several notification channels in my app.
For each channel, I assigned a sound Uri to a file stored in my app res/raw folder.
Like so
// Getting the sound Uri
int resID = context.getResources().getIdentifier(soundItem.getSoundFileName(), "raw", context.getPackageName());
if (resID != 0) {
return Uri.parse("android.resource://" + getContext().getPackageName() + "/" + resID);
}
// Creating Channel
NotificationChannel notificationChannel = new NotificationChannel(androidChannelId, channelName, NotificationManager.IMPORTANCE_HIGH);
// Creating an Audio Attribute
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build();
notificationChannel.setSound(soundUri, audioAttributes);
This worked great in several versions, however, in the last version of my app, we noticed that notifications are not playing sound anymore.
Digging and debugging, and I found that the res ID for the sound file has changed.
So, if for example in version 1.2 of my app R.raw.tone1 was 12345678, now that same R.raw.tone1 is 123456799.
Which results in that the system can't find the file anymore.
Now I'm not sure what should I do? Recreate the channel each version?
Thank you for your help
Use the name of the sound resource instead. Then you only have to create a new channel once, in the next update (and delete the old one).
// using scope function to make sure resource exists in compile time
val soundUri = R.raw.tone1.run {
Uri.parse(
"${ContentResolver.SCHEME_ANDROID_RESOURCE}://"
.plus("${context.packageName}/raw/tone1")
)
}
I have made an android taxi hailing app like Uber. When a request is going to the driver, it is showing as a notification like any other notification of whatsapp and message with the default popup notification sound. I need the notification sound to ring for 15 to 20 seconds instead of the pop up sound . How do I do this ?
try to set the ring tone file which have a length of 15 to 20 sec
//App.appInstance --> Application class instance
Uri uri = Uri.parse("android.resource://" + App.appInstance.getPackageName() + "/" +
R.raw.notification_sound);
NotificationCompat.Builder builder = new NotificationCompat.Builder(App.appInstance, "")
.setSound(uri)
place the sound file in the raw folder
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Notification mNotification = new Notification.Builder(this)
................setSound(soundUri).........
.build();
In MI Note 5 Pro which has latest MI UI 10.0 with Oreo, so when I try to send push notification by default sound is disable, so i am not able to enable sound programmatically when I am creating a channel for that.
In other Oreo devices notification sound is coming but in MI custom Oreo OS Sound is by default disable
Let me show my code for notification :
var intent = Intent(mContext, HomeActivity::class.java)
intent.putExtra(Constants.EXTRA_FROM_NOTIFICATION, true)
var pendingIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
var uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
var mBuilder = NotificationCompat.Builder(mContext, NOTIFICATION_CHANNEL_ID)
.setContentTitle(mContext.getString(R.string.app_name))
.setContentText(mFirstContactName + " : " + mListChatWindow[0].message)
.setPriority(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) NotificationManager.IMPORTANCE_HIGH else Notification.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.setSound(uri)
.setSmallIcon(R.drawable.ic_app_icon)
.setColor(ContextCompat.getColor(mContext, R.color.colorPrimary))
.setVibrate(longArrayOf(0, 100, 1000, 300))
.setAutoCancel(true)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
var channel = NotificationChannel(NOTIFICATION_CHANNEL_ID, "NOTIFICATION_CHANNEL_NAME", NotificationManager.IMPORTANCE_HIGH)
channel.description = "NOTIFICATION_DESCRIPTION"
channel.lightColor = Color.LTGRAY
channel.enableVibration(true)
channel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
val attributes = AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build()
channel.setSound(uri, attributes)
var notificationManager = mContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
var notificationManager = NotificationManagerCompat.from(mContext)
notificationManager.notify(NOTIFICATION_CHAT_ID, mBuilder.build())
I am also set channel.setSound(uri, attributes) in cannel but sound not coming
Here is the screenshot of Notification channel see there sound icon is disabled, how to enable?
Plz help
I had similar problem in MIUI Global 10.1 with oreo but it was only while using custom sound and not like yours, default sound. Any way let me explain how I solve it and hope it may solve yours.
First thing to consider is where the registration of notification channel is executed. It must be executed in Application.onCreate so that the channel is created even before the notification arrives. I was doing it in onMessageReceived.
Second as I said it was working for default notification sound and not for custom one, I inserted below code while creating notification channel and it worked.
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this,CHANNEL_ID);
if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.O) {
notificationBuilder.setDefaults(Notification.DEFAULT_SOUND); // This line did the magic for me.
Uri sound = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.sound_notification_plucky);
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build();
CharSequence name = "MyChild";
String description = "All MyChild messages";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, name, importance);
notificationChannel.setDescription(description);
notificationChannel.enableVibration(true);
notificationChannel.setSound(sound, audioAttributes);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(notificationChannel);
}
I'm facing same issue and still didn't get satisfying answer, but till that time we can workaround it like so:
final Uri NOTIFICATION_SOUND = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
RingtoneManager.getRingtone(context, NOTIFICATION_SOUND).play();
You need to call this after:
notificationManager.notify(notificationId, notification);
This way you will always get sound playing even if "allow sound" was turned off for your App, and the sound played will be from the system not media (expected behavior from the notifications).
And to avoid having two sounds playing at once (for the devices that don't have this issue), you can turn the sounds off like so:
1- For the Builder:
notificationBuilder.setContentTitle(title)
.set.....
.set.....
.setSound(null);
2- For the channel:
channel.setSound(null, null);
mBuilder.setPriority(NotificationCompat.PRIORITY_HIGH)
This line of code is worked for me it enables all notification settings.
I'm working on android app with system of notifications and i need the android device to push the notification with a specific sound i stored on assets folder
this is my java code for notification :
Notification noti = new Notification.Builder(MainActivity.this)
.setTicker("Calcupital")
.setContentTitle("Calcupital")
.setContentText("User Information has been updated successfully")
.setSmallIcon(R.drawable.login)
.setContentIntent(pIntent).getNotification();
noti.flags = Notification.FLAG_AUTO_CANCEL;
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(0, noti);
Assuming that my sound stored like that : (\assets\hopo.mp3)
how to make this notification pushed with this sound without changing the push notification systems for other apps by changing the sound from the list that android device offered !!.
I hope my question is very clear to you :)
To combine the answers here and using the two answers from these questions:
How to add sound to notification?
How to get URI from an asset File?
Try this:
Uri sound = Uri.parse("file:///android_asset/hopo.mp3");
Notification noti = new Notification.Builder(MainActivity.this)
.setTicker("Calcupital")
.setContentTitle("Calcupital")
.setContentText("User Information has been updated successfully")
.setSmallIcon(R.drawable.login)
.setSound(sound);
.setContentIntent(pIntent).getNotification();
noti.flags = Notification.FLAG_AUTO_CANCEL;
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(0, noti);
You need to place your sound file to res/raw directory.
Then add this code into current code
final String packageName = context.getPackageName();
notification.sound =
Uri.parse("android.resource://" + packageName + "R.raw.hopo");
see this link for more details
http://developer.android.com/reference/android/app/Notification.Builder.html#setSound(android.net.Uri)
you can set default sound using
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
if (alarmSound != null) {
mBuilder.setSound(alarmSound);
}
if you want custom sound just use different Uri. how to get Uri from assets? check this topic
To get the resource:
Uri alarmSound = Uri.parse("android.resource://" + this.getPackageName() + "/" + R.raw.somefile);
** the raw folder must be created inside res folder and add youre sound file **
To set up:
NotificationCompat.Builder noBuilder = new NotificationCompat.Builder(this)
.setContentText(message)
.setSound(alarmSound) // -> add this one
.setVibrate(new long[] { 1000, 1000, 1000, 1000, 1000 });