I am having a situation in which I need to update two notifications simultaneously. I have a service which plays audio and while playing the audio I used to show a notification of the player. Also in another activity I have a download method which downloads some audio and during download I need to show a notification of the download progress. So in some case if both the above thing is occuring then I need to show two different notifications together both having different Notification ID and different Notification Channel.
During download its progress changes every seconds and therefore the download notification get updated every seconds. And during this if anyone changes the audio source then the player notification is required to update and this cause my problem, the player notification doesn't get updated and I saw this happen only when the download notification is getting updated otherwise when there is no download notification to be updated then everything works fine.
I am using AsyncTask to download and showing notification using
#Override
protected void onPreExecute() {
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationBuilder = new NotificationCompat.Builder(context.get(), NOTIFICATION_CHANNEL_DOWNLOADING_ID)
.setProgress(100, 0, true)
.setContentTitle(context.get().getString(R.string.downloading) + "-" + name)
.setContentText("0%")
.setSmallIcon(R.mipmap.notification)
.setChannelId(NOTIFICATION_CHANNEL_DOWNLOADING_ID)
.setContentIntent(pendingIntent)
.addAction(0, context.get().getResources().getString(R.string.cancel), cancelIntent)
.setAutoCancel(true);
NotificationChannel mChannel;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Download Notification";
int importance = NotificationManager.IMPORTANCE_LOW;
mChannel = new NotificationChannel(NOTIFICATION_CHANNEL_DOWNLOADING_ID, name, importance);
notificationManager.createNotificationChannel(mChannel);
}
notificationManager.notify(102, notificationBuilder.build());
}
#Override
protected String doInBackground(String... strings) {
//all the downloading stuff
publishProgress(progress_value);
....
}
#Override
protected void onProgressUpdate(Integer... progress) {
notificationBuilder.setContentText(progress[0] + "%");
notificationBuilder.setProgress(100, progress[0], false);
//notification getting update every seconds due to continuous change in progress
notificationManager.notify(102, notificationBuilder.build());
}
Now in my player service -
notification = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.app_icon2))
.setContentTitle(getString(R.string.app_name))
.setContentIntent(pendingIntent)
.setSmallIcon(R.mipmap.notification)
.setTicker(Constant.arrayList_play.get(Constant.playPos).getMp3Name())
.setChannelId(NOTIFICATION_CHANNEL_ID)
.setOnlyAlertOnce(true);
NotificationChannel mChannel;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Music Playback";
int importance = NotificationManager.IMPORTANCE_LOW;
mChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, name, importance);
mNotificationManager.createNotificationChannel(mChannel);
}
mNotificationManager.notify(101, notification.build());
I have tried changing the progress update duration by increasing the interval then the player notification works properly when the later's notification is not getting update.
Can anyone please help me a little in this matter and thanks in advance.
The Notification IDs should be different
mNotificationManager.notify(Notification_ID, notification.build());
Related
I can't seem to figure out why I can'y get my actions to show up on a remote notification. I have seen several tutorials on making it happen, and followed them, still no actions show up. The end goal is to have a "Reply" action where you can type in a response and send a reply through the notification, much like the standard text message notification.
I couldn't get that to show up, so I decided to add a second action, that is just a basic action, neither are showing up. I'll post up my sendNotification method, hopefully someone can see what I am doing wrong...
private void sendNotification(String body, String id) {
Intent i;
PendingIntent pi;
if(user.role.equals(Strings.roleMember) { //This is just to separate logic
i = new Intent(this, NotificationReceiver.class);
pi = PendingIntent.getBroadcast(this, 0, i, 0);
} else {
i = new Intent(this, AgentChatActivity.class);
pi = PendingIntent.getActivity(this, 0, i, 0);
}
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.putExtra(Strings.chatID, id);
RemoteInput input = new RemoteInput.Builder(Strings.textReply).setLabel("Reply").build();
NotificationCompat.Action replyAction = new NotificationCompat.Action.Builder(android.R.drawable.ic_dialog_info, "Reply", pi)
.addRemoteInput(input).build();
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, Strings.channelID)
.setSmallIcon(R.drawable.ic_stat_notify)
.setContentTitle("New Message")
.setContentText(body)
.setAutoCancel(true)
.setCategory(NotificationCompat.CATEGORY_MESSAGE) //I have tried without this too
.setPriority(NotificationCompat.PRIORITY_MAX)
.addAction(replyAction)
.addAction(android.R.drawable.ic_dialog_alert, "reply", pi); //this is the second I added just to test
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(Strings.channelID, "General Messages", NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(channel);
}
manager.notify(0, builder.build());
}
According to everything I have seen online, that should have actions attached to the notification, however I run it in the emulator (Pixel 6 API 27) and the notification shows up, but no actions are on it. I have tried without the second action, I have tried with only the second action, nothing shows up, just the basic notification. My build settings are set to minSdk 21, compileSdk and targetSdk 33. I would be more than happy to post any more code or anything else anyone needs, I can't figure it out. Thank you.
In my app I use Foreground Service to show a notification when the app goes in background. I created a Notification Channel in the following way:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.app_name);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(TransactionsUtil.getNotificationChannelId(this), name, importance);
channel.setDescription("some description");
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
Notification notification = new NotificationCompat.Builder(this, TransactionsUtil.getNotificationChannelId(this))
.setSmallIcon("some icon")
.setContentTitle("some content")
.setContentText("some content")
.setContentIntent(pendingIntent)
.setChannelId(TransactionsUtil.getNotificationChannelId(this))
.build();
startForeground(NOTIFICATION_ID, notification);
The I delete the notification channel in this way:
private void terminateService() {
stopForeground(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.deleteNotificationChannel(getNotificationChannelId(this));
}
stopSelf();
}
Recently, I'm having some crashes in my app releated to this; in particular, I have the following error:
Fatal Exception: java.lang.SecurityException
Not allowed to delete channel "channel name" with a foreground service
The problem is releated to the function terminateService, in particular in deleteNotificationChannel.
Caused by android.os.RemoteException
Remote stack trace: at com.android.server.notification.NotificationManagerService$11.enforceDeletingChannelHasNoFgService(NotificationManagerService.java:3859) at com.android.server.notification.NotificationManagerService$11.deleteNotificationChannel(NotificationManagerService.java:3872) at android.app.INotificationManager$Stub.onTransact(INotificationManager.java:1813) at android.os.Binder.execTransactInternal(Binder.java:1170) at android.os.Binder.execTransact(Binder.java:1134)
It happens only in Android 11 devices. Does someone has a solution or suggestion, please?
You don't need to delete the channel, you can share the channel with your normal notification channel.
You get crash because stopForeground is binder call through ActivityManagerService, it cross process, same as the deleteNotificationChannel through NotificationManagerService, if the NotificationManagerService goes fast, the method enforceDeletingChannelHasNoFgService will return true, which is added from android-11.0.0_r38, and you will get a crash.
I am sharing two images please have a look on it you will understand my problem
in fist image notification comes successfully as shown better me notification but
I want it to come and show first on main screen as shown in second image just this telegram notification.
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
// r.play();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
r.setLooping(false);
}
// vibration
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
long[] pattern = {100, 300, 300, 300};
v.vibrate(pattern, -1);
int resourceImage = getResources().getIdentifier(remoteMessage.getNotification().getIcon(), "drawable", getPackageName());
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "CHANNEL_ID");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder.setSmallIcon(R.mipmap.betterme);
} else {
builder.setSmallIcon(R.mipmap.betterme);
}
Intent resultIntent = new Intent(this, SplashScreen.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentTitle(remoteMessage.getNotification().getTitle());
builder.setContentText(remoteMessage.getNotification().getBody());
builder.setContentIntent(pendingIntent);
builder.setStyle(new NotificationCompat.BigTextStyle().bigText(remoteMessage.getNotification().getBody()));
builder.setAutoCancel(true);
builder.setOngoing(true);
builder.setPriority(NotificationCompat.PRIORITY_MAX);
builder.setSound(notification);
mNotificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channelId = "Your_channel_id";
NotificationChannel channel = new NotificationChannel(
channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_HIGH);
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build();
channel.setSound(notification, audioAttributes);
mNotificationManager.createNotificationChannel(channel);
builder.setChannelId(channelId);
}
mNotificationManager.notify(100, builder.build());
}
}
first image
second image
If I understand correctly, you would like to have a heads up notification.
Note, that the android system decides when to make a notification a heads up notification and has the final say - not you the developer. Here you can find some examples when it does so: https://developer.android.com/guide/topics/ui/notifiers/notifications#Heads-up
Make sure that your setup reflects these. From your sample it seems to be the case, but maybe you have changed the notification channel settings (from the app settings), which override your code preferences (the user has precedence over the app).
Additionally, note that if you swipe the heads up notification in a upward direction (not sideways), Android starts a cool off time, where no heads up notifications from that app appears for a few seconds (or more). You can try that with Telegram or any other app as well. After the cool-off time, it starts showing up again like a heads up notification. This is a way Android utilises to prevent apps to be annoying to users.
Seems there is no problem in the notification. But your channel is already created with normal notification and you update to IMPORTANCE_HIGH for NotificationChannel.
Once the channel is created with priority it cannot be changed. So you can either change the channel id or uninstall and reinstall and test it.
How can I switch all these settings on programmatically?
I noticed when you install WhatsApp they are all switched on in the beginning(look at the image below).
But I can not find a way to turn them on programmatically.
Here is how I send notifications:
private void sendNotification(Intent intent){
Context context = NotificationService.this;
//open the activity after the notification is clicked
Intent intent1 = new Intent(getApplicationContext(),MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(context, 0, intent1, 0);
Notification.Builder builder = new Notification.Builder(context)
.setTicker("Notification")
.setContentTitle("Important Message")
.setContentText("This is an example of a push notification using a Navigation Manager")
.setSmallIcon(R.drawable.ic_add)
.setContentIntent(pIntent);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
//These are necessary for the notification to pop up
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.O){
builder.setPriority(Notification.PRIORITY_MAX);
builder.setSound(alarmSound);
builder.setLights(Color.BLUE, 500, 500);
}
//after android O we must use notification channels
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
String channelId = "Your_channel_id";
NotificationChannel channel = new NotificationChannel(
channelId,
"Reminder to remind to review your notes",
NotificationManager.IMPORTANCE_HIGH);
if(alarmSound != null){
AudioAttributes att = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
channel.setSound(alarmSound,att);
}
channel.setLightColor(Color.BLUE);
channel.enableVibration(true);
channel.setDescription("Hello Dear friends"); //this is to test what this is
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
channel.setVibrationPattern(new long[]{300, 300, 300});
notificationManager.createNotificationChannel(channel);
builder.setChannelId(channelId);
}
Notification notification = builder.build();
notificationManager.notify(0, notification);
}
I also added this permission to manifest:
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
Update:
Using this code on the emulator, I get the heads-up notification. But on my Xiaomi device, there is no heads-up notification. It just appears on the status bar. If I manually turn on the floating notification (which you can see in the photo) then I will get heads-up notification. But they are switched off by default. When you install Whatsapp they are all switched on.
Is that a kind of privilege for Whatsapp as it is famout? or is there a way to do it?
By default, when you install a app, the system register's default notification channel (on low priority) that doesn't support head up notification by default, it's turned off. You can't control that.
But what you can do it create your own notification channel with highest priority and then register it on app run once.
After that just pass the channel Id with your notification builder so that system shows the head's up notification which you want.
More information can be found here https://developer.android.com/training/notify-user/channels
I have tried for this but unable to set these settings programmatically. Instead of this I have used following method to open notification settings screen to enable notification sounds/vibration.
private void openNotificationSettingsForApp(String channelId) {
// Links to this app's notification settings.
Intent intent = new Intent();
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && channelId!=null){
intent.setAction(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_CHANNEL_ID,channelId);
intent.putExtra("android.provider.extra.APP_PACKAGE", getPackageName());
}
intent.putExtra("app_package", getPackageName());
intent.putExtra("app_uid", getApplicationInfo().uid);
startActivity(intent);
}
I'm sending push notifications in my app and want to be able to show them even if the app is already running, so therefore I'm trying to use the onMessageReceived() function. The function runs whenever I send a notification and I can see that the title and body of the notification is correct, so no problems this far. Then I want the notification to pop up on the users device, but for some reason I just can't get it to work. I have looked at numerous sites and stackoverflow questions and all code basically looks the same, so it's a bit confusing why it doesn't work for me.
#Override
public void onMessageReceived(#NonNull RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
String messageTitle = remoteMessage.getNotification().getTitle();
String messageBody = remoteMessage.getNotification().getBody();
System.out.println("TITLE_IS: " + messageTitle);
System.out.println("MESSAGE_BODY: "+ messageBody);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, getString(R.string.default_notification_channel_id))
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(messageTitle)
.setContentText(messageBody);
//Sets ID for the notification
int mNotificationId = (int) System.currentTimeMillis();
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotifyMgr.notify(mNotificationId, mBuilder.build());
System.out.println("Everything went fine");
}
It never prints the last line ("Everything went fine"), but also don't give an error so it seems it works even though it didn't. What is the problem and how do I fix it?
There seem to have been a recent update which requires you to run some additional code in order for it to work on newer android versions. So the code should looks something like:
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, getString(R.string.default_notification_channel_id))
.setSmallIcon(R.drawable.ic_challenge)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setPriority(Notification.PRIORITY_MAX)
.setContentIntent(pendingIntent);
//to show notification do this
//Sets ID for the notification
int mNotificationId = (int) System.currentTimeMillis();
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
String channelId = "Tic-Tac-Toe";
NotificationChannel channel = new NotificationChannel(
channelId,
"Tic-Tac-Toe",
NotificationManager.IMPORTANCE_HIGH);
mNotifyMgr.createNotificationChannel(channel);
mBuilder.setChannelId(channelId);
}
mNotifyMgr.notify(mNotificationId, mBuilder.build());