We have code similar to the following in our app
val pendingIntent = PendingIntent.getActivity(ctx, id.toInt(), intent, PendingIntent.FLAG_CANCEL_CURRENT)
val builder = NotificationCompat.Builder(ctx, Channel.TEST_CHANNEL.channelId)
builder.setTicker(tickerText)
.setContentTitle(contentTitle)
.setContentText(contentText)
.setVibrate(vibrate)
.setSmallIcon(icon)
.setAutoCancel(true)
.setLights(-0xff0100, 300, 1000)
.setSound(uri)
.setContentIntent(pendingIntent)
.setStyle(NotificationCompat.BigTextStyle().bigText(contentText))
.addAction(R.drawable.ic_notification, ctx.getString(R.string.notification), piAction)
val notification = builder.build()
val nf = ctx.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
nf.notify(NOTIFICATION_TAG, id.toInt(), notification)
}
Starting recently we noticed that notifications on some device running Android 8+ started disappearing briefly after being shown, without user's interaction. Setting auto-cancel to false helps, but the user experience degrades.
The id is a unique item id from the database. This may be important thing to note - technically we can have a notification with such id be shown, removed/canceleld by user, and later some time used again for a similar notification with the same id. Can this be the reason?
We've updated the support libs and tried the following method on builder for luck:
builder.setTicker(tickerText)
...
.setTimeoutAfter(-1)
...
Setting this param to a positive value delayed the notification disappearing by that amount of time (so it did affect). Thus we tried a negative number, the notifications seem to stay there now.
I couldn't find any reasonable documentation explaining this, so this answer is not 100%, but keeping it here for now for others to try and see if it helps them.
Disable your application from auto optimize from battery optimization setting in android OREO. Notification will stay as long as you want
Only thing I found uncertain is NotificationCompat.Builder
Android oreo now uses Notification.Builder instead of NotificationCompat.Builder.
Might be you have to check android version like:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//Use Notification.Builder
} else {
// Use NotificationCompat.Builder.
}
I don't think unique id will be an issue for disappearing notification.
Google has created open source sample for this new changes. Please refer to it for more info.
https://github.com/googlesamples/android-NotificationChannels
.setAutoCancel(false)
May be it will work for you.
Related
The notification it self is working good, but not as I want. It vibrates and shows the icon defined but not as a Watsapp Notification and in the setCategory I put CATEGORY_MESSAGE but still, nothing!
on my App class i put :
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
NotificationChannel channel = new NotificationChannel(CHANNEL_ID,CHANNEL_NAME,NotificationManager.IMPORTANCE_HIGH);
channel.setDescription(CHANNEL_DESC);
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
NotificationManager manager = getSystemService(NotificationManager.class);
assert manager != null;
manager.createNotificationChannel(channel);
}
Fragment :
private void T(String message){
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext(),CHANNEL_ID)
.setContentText(message)
.setContentTitle("Test")
.setColor(0xff123456)
.setSmallIcon(R.drawable.com_facebook_button_icon)
.setCategory(CATEGORY_MESSAGE)
.setPriority(PRIORITY_HIGH);
NotificationManagerCompat compat = NotificationManagerCompat.from(getApplicationContext());
compat.notify(1,mBuilder.build());
}
This is How I want it to notify :
This is how is current notifying
I'm using the SDK 27
After discussing with OP in chat, here's my best explanation about what could have happened:
A notification channel can only be created once, after which it becomes immutable to the app. It can only be tweaked by the user through the Settings. If someone follows the examples in the official docs first, they might create the channel with IMPORTANCE_DEFAULT. After this, even if they change the code later, the channel will remain at level 'High: Make Sound' and not be set to 'Urgent: Make Sound and pop on screen' as desired. Docs on importance level
The code in the question is perfectly fine, and should create a channel with the 'Urgent' level when installed for the first time. In any case, uninstalling the app manually and then installing it again will recreate the channels, setting the level to whatever is mentioned in the latest code.
I am building an android app that replaces the notification drawer and show notifications in its own window. I managed to show notifications on my drawer when they are posted by overriding onNotificationPosted() method. But, same notification is also shown by android. So,I want that notifications should be shown ONLY on my window, there are other apps who have done it,so it's not impossible. Please tell me how to override default behavior of android. Thanks in advance. :)
EDIT
What i want is to disable heads-up notification. Any solutions there?
In Oreo and above OS It is in the Notification channel Where you have to set the Priority any thing lesser than NotificationManager.IMPORTANCE_HIGH or some thing like this below stops the heads up banner.
NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
CHANNEL_NAME,
NotificationManager.IMPORTANCE_DEFAULT)
On Pre-Oreo devices, the notification priority itself helps the system to show/hide the heads up banner.
Also remember when you make this change you have to delete the app and reinstall to see the change!
I used NotificationManager.IMPORTANCE_DEFAULT with setPriority(NotificationCompat.PRIORITY_DEFAULT) and it seems to work (Oneplus 3 and Note 8).
String channelId = "ch01";
String channelName = "Status";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel mChannel = new NotificationChannel(
channelId, channelName, importance);
notificationManager.createNotificationChannel(mChannel);
}
NotificationCompat.Builder nb = new NotificationCompat.Builder(this, channelId);
nb.setSmallIcon(R.drawable.ic_logo);
nb.setContentTitle(notificationText);
nb.setContentText("");
nb.setContentIntent(mainActivityPendingIntent);
nb.setPriority(NotificationCompat.PRIORITY_DEFAULT);
nb.setOnlyAlertOnce(true);
nb.setOngoing(true);
nb.setWhen(System.currentTimeMillis());
Huh! Looks like Android provides no way to disable heads-up notification of other apps via code.
Here is a little hack!
So, what we need is, not show any heads-up notification from any other app. To solve this, we need to understand that at one time there could be only one heads-up notification on screen.
Hack is, send your own notification right after you listen any notification being posted i.e. in onNotificationPosted() of a NotificationListener subclass.
this.mNotificationManager.notify(12321, new Notification.Builder(this)
.setContentTitle("").setContentText("")
.setSmallIcon(R.drawable.transparent)
.setPriority(Notification.PRIORITY_DEFAULT)
.setFullScreenIntent(this.mBlankIntent, true)
.setAutoCancel(true)
.build());
It will replace the notification of the 3rd app with your almost blank notification. Oh wow! Wait!! This looks ugly.
Ofcourse, Now we need to remove this notification before the user could even see this.
Now that you know package name of the android. You can show cancel your notification some thing like this.
if(packageName.equals("com.my.package")){
mNotificationManager.cancel(12321);
return;
}
So, what we are doing is showing our notification, when any other heads up notification shows up, and then remove our own notification. All this happens so quick that user does not sees any heads-up notification, and for doing this, I did not needed to store the notification in memory even.
Set the IMPORTANCE to LOW and PRIORITY to LOW.
It work for me
var notificationChannel = NotificationChannel(channelId, "Call" , NotificationManager.IMPORTANCE_LOW)
var notification = NotificationCompat.Builder(context,channelId)
.setContentTitle("Calling")
.setContentText("Call")
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_LOW)
I an a noob in android, I am trying to show notification of the push notifications I receive. Every time I receive a push notification a new notification is created in the notification bar, even if an exisiting one is present. I want them to be grouped together.
This is what I am currently doing
private void generateNotification(Context context, String ticker, String title, String msg, int icon, Intent intent)
{
int notificationId = 1;
long when = System.currentTimeMillis();
int pendingNotificationsCount = AppName.getPendingNotificationsCount() + 1;
AppName.setPendingNotificationsCount(pendingNotificationsCount);
mNotifyBuilder = new NotificationCompat.Builder(this)
.setWhen(when)
.setContentTitle(title)
.setContentText(msg)
.setAutoCancel(true)
.setContentIntent(PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT))
.setNumber(pendingNotificationsCount);
//This prints the count correctly....
Log.d("Snehan", "Message built with Count "+pendingNotificationsCount);
Notification notif = mNotifyBuilder.build();
notif.defaults = Notification.DEFAULT_ALL;
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notificationId, notif);
}
Am I doing something wrong here or missing something??
Seems Android updated the library since I last used it. But the logic is still the same. You need to save whatever the notification id was or at least give it a name you can track and check if it exists. More info can be found in the Android docs. Below is a snippet from what I mean.
To set up a notification so it can be updated, issue it with a notification ID by calling NotificationManager.notify(ID, notification). To update this notification once you've issued it, update or create a NotificationCompat.Builder object, build a Notification object from it, and issue the Notification with the same ID you used previously. If the previous notification is still visible, the system updates it from the contents of the Notification object. If the previous notification has been dismissed, a new notification is created instead.
The docs have everything you need so no need for me to write the code for you :) Hope that helped.
Edit:
Ok, so I recommend you adda a dummy icon just to see what that does. I also recommend instead of chaining all that stuff only chain the text stuff. This way you can debug a bit easier. Try to follow the doc a bit more closely. I don;t really see anything wrong with your code, but obviously something is causing the issue.
Edit 2
So it seems the icon was the problem. I've had this issue before, which is why I mentioned to add that explicitly. Hopefully when someone encounters issues with notifications please make sure you have an icon!!
I need a program that will add a notification on Android. And when someone clicks on the notification, it should lead them to my second activity.
I have established code. The notification should be working, but for some reason it is not working. The Notification isn't showing at all. I don't know what am I missing.
Code of those files:
Notification n = new Notification.Builder(this)
.setContentTitle("New mail from " + "test#gmail.com")
.setContentText("Subject")
.setContentIntent(pIntent).setAutoCancel(true)
.setStyle(new Notification.BigTextStyle().bigText(longText))
.build();
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Hide the notification after it's selected
notificationManager.notify(0, n);
The code won't work without an icon. So, add the setSmallIcon call to the builder chain like this for it to work:
.setSmallIcon(R.drawable.icon)
Android Oreo (8.0) and above
Android 8 introduced a new requirement of setting the channelId property by using a NotificationChannel.
NotificationManager mNotificationManager;
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(mContext.getApplicationContext(), "notify_001");
Intent ii = new Intent(mContext.getApplicationContext(), RootActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, ii, 0);
NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle();
bigText.bigText(verseurl);
bigText.setBigContentTitle("Today's Bible Verse");
bigText.setSummaryText("Text in detail");
mBuilder.setContentIntent(pendingIntent);
mBuilder.setSmallIcon(R.mipmap.ic_launcher_round);
mBuilder.setContentTitle("Your Title");
mBuilder.setContentText("Your text");
mBuilder.setPriority(Notification.PRIORITY_MAX);
mBuilder.setStyle(bigText);
mNotificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
// === Removed some obsoletes
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);
mNotificationManager.createNotificationChannel(channel);
mBuilder.setChannelId(channelId);
}
mNotificationManager.notify(0, mBuilder.build());
Actually the answer by Ć’ernando Valle doesn't seem to be correct. Then again, your question is overly vague because you fail to mention what is wrong or isn't working.
Looking at your code I am assuming the Notification simply isn't showing.
Your notification is not showing, because you didn't provide an icon. Even though the SDK documentation doesn't mention it being required, it is in fact very much so and your Notification will not show without one.
addAction is only available since 4.1. Prior to that you would use the PendingIntent to launch an Activity. You seem to specify a PendingIntent, so your problem lies elsewhere. Logically, one must conclude it's the missing icon.
You were missing the small icon.
I did the same mistake and the above step resolved it.
As per the official documentation:
A Notification object must contain the following:
A small icon, set by setSmallIcon()
A title, set by setContentTitle()
Detail text, set by setContentText()
On Android 8.0 (API level 26) and higher, a valid notification channel ID, set by setChannelId() or provided in the NotificationCompat.Builder constructor when creating a channel.
See http://developer.android.com/guide/topics/ui/notifiers/notifications.html
This tripped me up today, but I realized it was because on Android 9.0 (Pie), Do Not Disturb by default also hides all notifications, rather than just silencing them like in Android 8.1 (Oreo) and before. This doesn't apply to notifications.
I like having DND on for my development device, so going into the DND settings and changing the setting to simply silence the notifications (but not hide them) fixed it for me.
Creation of notification channels are compulsory for Android versions after Android 8.1 (Oreo) for making notifications visible. If notifications are not visible in your app for Oreo+ Androids, you need to call the following function when your app starts -
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) {
CharSequence name = getString(R.string.channel_name);
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name,
importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviours after this
NotificationManager notificationManager =
getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
You also need to change the build.gradle file, and add the used Android SDK version into it:
implementation 'com.android.support:appcompat-v7:28.0.0'
This worked like a charm in my case.
I think that you forget the
addAction(int icon, CharSequence title, PendingIntent intent)
Look here: Add Action
I had the same issue with my Android app. I was trying out notifications and found that notifications were showing on my Android emulator which ran a Android 7.0 (Nougat) system, whereas it wasn't running on my phone which had Android 8.1 (Oreo).
After reading the documentation, I found that Android had a feature called notification channel, without which notifications won't show up on Oreo devices. Below is the link to official Android documentation on notification channels.
Notifications Overview, Notification anatomy
Create and Manage Notification Channels
For me it was an issue with deviceToken. Please check if the receiver and sender device token is properly updated in your database or wherever you are accessing it to send notifications.
For instance, use the following to update the device token on app launch. Therefore it will be always updated properly.
// Device token for push notifications
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(
new OnSuccessListener<InstanceIdResult>() {
#Override
public void onSuccess(InstanceIdResult instanceIdResult) {
deviceToken = instanceIdResult.getToken();
// Insert device token into Firebase database
fbDbRefRoot.child("user_detail_profile").child(currentUserId).child("device_token")).setValue(deviceToken)
.addOnSuccessListener(
new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
}
});
}
});
I encountered a similar problem to yours and while searching for a solution I found these answers but they weren't as direct as I hoped they would be but it gives an Idea; Your notifications may not be showing because for versions >=8 notifications are done relatively differently there is a NotificationChannel which aids in managing notifications this helped me. Happy coding.
void Note(){
//Creating a notification channel
NotificationChannel channel=new NotificationChannel("channel1",
"hello",
NotificationManager.IMPORTANCE_HIGH);
NotificationManager manager=(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.createNotificationChannel(channel);
//Creating the notification object
NotificationCompat.Builder notification=new NotificationCompat.Builder(this,"channel1");
//notification.setAutoCancel(true);
notification.setContentTitle("Hi this is a notification");
notification.setContentText("Hello you");
notification.setSmallIcon(R.drawable.ic_launcher_foreground);
//make the notification manager to issue a notification on the notification's channel
manager.notify(121,notification.build());
}
Make sure your notificationId is unique. I couldn't figure out why my test pushes weren't showing up, but it's because the notification ids were generated based on the push content, and since I was pushing the same notification over and over again, the notification id remained the same.
Notifications may not be shown if you show the notifications rapidly one after the other or cancel an existing one, then right away show it again (e.g. to trigger a heads-up-notification to notify the user about a change in an ongoing notification). In these cases the system may decide to just block the notification when it feels they might become too overwhelming/spammy for the user.
Please note, that at least on stock Android (tested with 10) from the outside this behavior looks a bit random: it just sometimes happens and sometimes it doesn't. My guess is, there is a very short time threshold during which you are not allowed to send too many notifications. Calling NotificationManager.cancel() and then NotificationManager.notify() might then sometimes cause this behavior.
If you have the option, when updating a notification don't cancel it before, but just call NotificationManager.notify() with the updated notification. This doesn't seem to trigger the aforementioned blocking by the system.
If you are on version >= Android 8.1 (Oreo) while using a Notification channel, set its importance to high:
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
val pendingIntent = PendingIntent.getActivity(applicationContext, 0, Intent(), 0)
var notification = NotificationCompat.Builder(applicationContext, CHANNEL_ID)
.setContentTitle("Title")
.setContentText("Text")
.setSmallIcon(R.drawable.icon)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.build()
val mNotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
mNotificationManager.notify(sameId, notification)
Before Notification.Builder came into existence the way to update a notification that was already in the notification tray was to call setLatestEventInfo() and then send the notification back through the NotificationManager.notify() call with an ID that matches the first notify() call you made.
Now setLatestEventInfo() is deprecated with the message: Use Notification.Builder instead. But I cannot find any documentation about how to properly update a notification using Notification.Builder.
Are you just suppose to recreate a new Notification instance every time you need to update the notification? Then simply pass that to NotificationManager.notify() with the ID you used before?
It seems to work but I wanted to see if anyone had any official verification that this is the new "way to do this"?
There real reason I am asking this is because in Android 4.1.1 Jelly Bean, the notification now flashes everytime notify() is called. When updating a progress bar with setProgress() this looks really bad and makes it hard to tap on the notification. This was not the case in 4.1 or previous versions. So I want to make sure I am doing this correctly before I file a bug.
I resolved this issue by calling setWhen(0) on my Notification.Builder. It seems Android's default value for this argument doesn't suit updating bits of the notification view without the entire notification fading out / in.
Notification.Builder builder = new Notification.Builder(c)
.setContentTitle("Notification Title")
.setSmallIcon(R.drawable.ic_notification_icon)
.setProgress(max_progress,current_progress,false)
.setWhen(0);
notification = builder.getNotification();
mNotificationManager.notify(NOTIFICATION_ID, notification);
Update:
As WolframRittmeyer stated, using when=0 is not an elegant way. I formed a solution like following:
if(mNotif == null) {
//either setting mNotif first time
//or was lost when app went to background/low memory
mNotif = createNewNotification();
}
else {
long oldWhen = mNotif.when;
mNotif = createNewNotification();
mNotif.when = oldWhen;
}
mNotificationManager.notify(NOTIFICATION_ID, mNotif);
What you are doing is correct, you're just missing the flags you can set. I don't know your particular notification implementation but you might consider using:
setOngoing(boolean ongoing)
or
setOnlyAlertOnce(boolean onlyAlertOnce)
I'm guessing (since I had the same trouble just now) that you are using a RemoteView in your notification. I managed to update the notification without it flashing like this:
RemoteViews views;
if( this.mNotification == null) {
views = new RemoteViews(getPackageName(), R.layout.notification);
this.mNotification = new Notification.Builder(this)
.setContent(views)
.setSmallIcon(R.drawable.status_icon)
.setContentIntent(mNotificationAction)
.setOngoing(true)
.setOnlyAlertOnce(true)
.getNotification();
} else {
views = this.mNotification.contentView;
}
Thanks to #seanmonstar for answering Refresh progress bar in notification bar.
The solution described here works well: Updating an ongoing notification quietly
The key is to use to reuse the builder and setOnlyAlertOnce(true):
if (firstTime) {
mBuilder.setSmallIcon(R.drawable.icon)
.setContentTitle("My Notification")
.setOnlyAlertOnce(true);
firstTime = false;
}
mBuilder.setContentText(message)
.setProgress(100, progress, true);
mNotificationManager.notify(mNotificationId, mBuilder.build());