I am trying to implement the Android Bubbles notifications API but it's not working for me, it's displaying as an ordinary notification. I am testing on emulator API 30(Android 11). I got the people-example working on the device, and I am following the Conversation Notifications guidelines.
The notification uses MessagingStyle.
(Only if the app targets Android 11 or higher) The notification is associated with a valid long-lived dynamic or cached sharing shortcut.
The notification can set this association by calling setShortcutId()
or setShortcutInfo(). If the app targets Android 10 or lower, the
notification doesn't have to be associated with a shortcut, as
discussed in the fallback options section.
The user hasn't demoted the conversation from the conversation section via notification channel settings, at the time of posting.
Please tell me what did I missed?
Also, I got a few optional questions about the design of Bubbles.
At what point of the app should I create the shortcuts and when to update it?
How the Person object needs to be cached?
This is what I got so far
Recipient recipient = ...; // Sender data
Message message = ...; // Message data
Intent intent = new Intent(context, ChatActivity.class);
intent.putExtra(ChatActivity.CONVERSATION_ID, message.conversationId);
PendingIntent bubbleIntent =
PendingIntent.getActivity(context, 0, intent, 0);
IconCompat icon = loadIcon(recipient);
Person person = loadPerson(recipient, icon);
NotificationCompat.MessagingStyle style = getMessagingStyle(person);
createOrVerifyChannel();
Notification notification = new NotificationCompat.Builder(context, CHANNEL_ID)
.setContentTitle(getNewMessagesCount(message) + " new messages with " + person.getName())
.setCategory(Notification.CATEGORY_MESSAGE)
.setContentText(message.text)
.setBubbleMetadata(
new NotificationCompat.BubbleMetadata.Builder()
.setDesiredHeight(600)
.setIntent(bubbleIntent)
.setAutoExpandBubble(true)
.setSuppressNotification(true)
.setIcon(icon)
.build()
)
.addPerson(person)
.setSmallIcon(R.mipmap.ic_launcher_round)
.setWhen(message.date)
.setStyle(style)
.setShortcutInfo(
new ShortcutInfoCompat.Builder(context, message.conversationId + "")
.setActivity(new ComponentName(context, ChatActivity.class))
.setCategories(new HashSet<>(Collections.singletonList(Notification.CATEGORY_MESSAGE)))
.setIcon(icon)
.setPerson(person)
.setRank(0)
.setShortLabel(person.getName())
.setIntent(intent)
.build()
)
.build();
NotificationManagerCompat.from(context).notify(message.id + "," + message.type,
message.id, notification);
Manifest
<activity
android:name=".screens.chat.ChatActivity"
android:allowEmbedded="true"
android:resizeableActivity="true"
tools:targetApi="n" />
Gradle
targetSDKVersion 30
implementation 'androidx.appcompat:appcompat:1.3.0-alpha02'
The one thing that I missed was adding .setLongLived(true) for the ShortcutInfoCompat. It solves the problem.
I learned that it best to manage the ShortcutInfo on the app level since you can have at most 5 at a time, so there is no harm caching those in memory, it includes the Person object as well.
Also, you should add LocusId for the NotificationCompat, this id is shared among shortcuts, notifications, and views. To add it to the views you need to put in some extra work, as described in ContentCaptureManager
Related
My Xamarin.Android app's push notification only works on Android 11 (Pixel 3 XL). Currently my app targets Android 11, however it also runs on Android 12 (Pixel 6 Pro). The only thing that is not working is Firebase push notifications. Below is the code that I am using. For the past week I have been researching the issue and saw posts about a specific issue with Android 12 (Pixel 6) not recieving push notifications. I performed changes to the phone configurations that others suggested and another app notification began to work, yet mine still has not. Any ideas would help.Thanks.
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
// Notification channels are new in API 26 (and not a part of the
// support library). There is no need to create a notification
// channel on older versions of Android.
var name = "NameOfChannel";
var description = "Notification Channel";
var channel = new NotificationChannel(CHANNEL_ID, name, NotificationImportance.Max)
{
Description = description
};
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
What I was missed is
PendingIntent.FLAG_IMMUTABLE
If Notification has pendingIntent then set mutable/immutable Flag to it
Found the solution. Which was to add android:exported="false" on the Firebase service tag within the AndroidManifest.
PendingIntent pendingIntent;
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.S)
{
pendingIntent=PendingIntent.getActivity(context,notificationId,notificationIntent,PendingIntent.FLAG_UPDATE_CURRENT|PendingIntent.FLAG_MUTABLE);
}
else
{
pendingIntent=PendingIntent.getActivity(context,notificationId,notificationIntent,PendingIntent.FLAG_UPDATE_CURRENT);
}
builder.setContentIntent(pendingIntent)
Im also facing the similar issue (Android/Kotlin), though i have modified Pending Intent changes and set "exported=false" still , app is not receiving the push notification.
below is firebase version
implementation platform('com.google.firebase:firebase-bom:31.0.3')
implementation 'androidx.work:work-runtime-ktx'
implementation 'com.google.firebase:firebase-messaging'
implementation 'com.google.firebase:firebase-iid'
My app uses the Android N's new quick-reply feature to quickly take notes from a fixed notification, without having the user to open an activity.
However, I would like the notification to be reset to its initial state after the user sends the quick reply message, without having to dismiss the notification.
Here is my code:
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? createChannel() : "").setSmallIcon(android.R.mipmap.sym_def_app_icon).setContentTitle("My Awesome App").setContentText("Doing some work...").setContentIntent(pendingIntent);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
android.support.v4.app.RemoteInput remoteInput = new RemoteInput.Builder(BookmarkCreatorReceiver.TXT_REPLY).setLabel("Reply").build();
Intent replyIntent = new Intent(this, BookmarkCreatorReceiver.class);
PendingIntent replyPendingIntent = PendingIntent.getBroadcast(this, 0, replyIntent, 0);
NotificationCompat.Action action = new NotificationCompat.Action.Builder(android.R.drawable.ic_dialog_email, "Bookmark", replyPendingIntent).addRemoteInput(remoteInput).build();
NotificationCompat.Action actionQuick = new NotificationCompat.Action.Builder(android.R.drawable.ic_dialog_email, "Quick", replyPendingIntent).build();
builder.addAction(action);
builder.addAction(actionQuick);
}
startForeground(NOTIFICATION_ID, builder.build());
The problem is that once the user sends a message and the Broadcast receiver is called, the notification stays in the loading state like this:
How can I remove the loading message, without having to discard the notification?
Per the Notifications in Android N blog post:
After you’ve processed the text, you must update the notification by calling notify() with the same id and tag (if used). This is the trigger which hides the Direct Reply UI and should be used as a technique to confirm to the user that their reply was received and processed correctly.
Also note:
For most templates, this should involve using the new setRemoteInputHistory() method which appends the reply to the bottom of the notification.
This ensures that users see the text they entered was properly handled.
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.
This may be off topic , but I couldn't found anything for it.
Is there any limit on the number of notifications android app can display?I am facing issue after 100 notifications. There is no documentation which states this clearly.
Note: This is not really a good idea to show 100 notifications but It is required for certain reasons.
According to #Nirel's answer.
1) I tried to run the code in 3 different devices.
Surprisingly notifications beyond 50 are not showing in notification area.
It gives following error.
W/NotificationManagerďą• notify: id corrupted: sent 51, got back 0
The same error comes for subsequent calls.
I saw the source of NotificationManager , it gives this error if incoming and out id is not same. See below code.
https://github.com/android/platform_frameworks_base/blob/master/core/java/android/app/NotificationManager.java#L233
2) After I tried to notify on intervals of 100 milliseconds.
It also Gives the same error. What I tried is removed 1 notification when code is executed.
Surprisingly , notification number 153 came in status bar.
So the conclusion is that , at most 50 notifications can be there. This may be default behaviour and may can change by manufacturer as said by #Sharp Edge.
Thnx.
In API23
package com.android.server.notification;
NotificationManagerService.java
static final int MAX_PACKAGE_NOTIFICATIONS = 50;
The limit for notifications and toasts is per app 50
this post has really helped me to do research on this topic. I have written an article on this like how can you modify your logic and keep posting notifications even if you have reached the maximum limit by compromising on the oldest notifications. https://medium.com/mindorks/the-notification-limit-per-app-in-android-94af69a6862c
The notification limit dropped from 50 to 24 per appin the Android 10 notification drawer.
Read more about it here.
run this:
// prepare intent which is triggered if the
// notification is selected
Intent intent = new Intent(this, NotificationReceiver.class);
// use System.currentTimeMillis() to have a unique ID for the pending intent
PendingIntent pIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), intent, 0);
// build notification
// the addAction re-use the same intent to keep the example short
Notification n = new Notification.Builder(this)
.setContentTitle("New mail from " + "test#gmail.com")
.setContentText("Subject")
.setSmallIcon(R.drawable.icon)
.setContentIntent(pIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
for(int i = 0;i<1000;i++)
{
Log.d("Tag", "notification number" + i "just published")
notificationManager.notify(i, n);
}
when the application will crash you will see how much notification you have..
my question for you is the following: I have a web app written in HTML5, wrapped as a native Android app in order to use Google Push Notifications. Because my app is using many notifications for different reasons, I want to be able to say each time a notification is received, which page to be open, like adding a 'href' in the notification intent. Is this possible?
If I wasn't clear enough please let me know.
Thanks
You can define your own notification message content. The Message builder from Google supports key value pairs to be set by the sender of the notification.
See http://developer.android.com/reference/com/google/android/gcm/server/Message.html
Example:
Message message = new Message.Builder()
.addData("link1", "http://mypage1.com")
.addData("link2", "http://mypage2.com")
.build();
When you create the notification, use setContentIntent() to attach an Intent that has been constructed to visit the right webpage:
// assuming <this> is an Activity or other Context
Intent urlIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(yourUrl));
PendingIntent urlPendingIntent = PendingIntent.getActivity(this, 0 urlIntent, 0);
Notification.Builder b = new Notification.Builder(this)
.setSmallIcon(...).setContentTitle(...).setContentText(...) // etc.
.setContentIntent(urlPendingIntent);
NotificationManager noMan
= (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
noMan.notify(ID, b.build());
If you expect to have more than one of these in the notification panel at a time:
Reconsider. It's spammy to post more than one notification.
If you must, you'll need a separate ID (or separate tag) for each.