Customize Baidu Push JSON Payload - android

I am using a rest API to send Baidu Push notifications. I don't have access to Android's notification builder classes, so I can't, for example, use notificationBuilder.setPriority(2);. Really the main thing that I need to know is how to set the priority of a Baidu Push notification to MAX, using JSON only.
According to this website, here are all of the keys and values for a Baidu JSON payload:
{
//android必选,ios可选
"title": "hello" ,
"description": "hello world"
//android特有字段,可选
"notification_builder_id": 0,
"notification_basic_style": 7,
"open_type":0,
"net_support" : 1,
"user_confirm": 0,
"url": "http://developer.baidu.com",
"pkg_content":"",
"pkg_name" : "com.baidu.bccsclient",
"pkg_version":"0.1",
//android自定义字段
"custom_content": {
"key1":"value1",
"key2":"value2"
},
//ios特有字段,可选
"aps": {
"alert":"Message From Baidu Push",
"sound":"",
"badge":0
},
//ios的自定义字段
"key1":"value1",
"key2":"value2"
}
I assume I need to set the values of notification_builder_id, but as it simply takes an integer as a the value, I am not sure how to create the notification to correspond with the id.

I was able to find out how to set the priority to high, in order to make the notification appear as a banner, as opposed to just an icon in the status bar.
In the client app, you need to set the notification builder, and give it an id, like so (note that I'm using Xamarin Forms, but the logic is the same if you are using native Android. Also, this code should be placed directly after the PushManager.StartWork() method call, most likely in your activity's onCreate() method):
BasicPushNotificationBuilder builder = new BasicPushNotificationBuilder();
builder.SetNotificationFlags(
(int)NotificationFlags.AutoCancel |
(int)NotificationFlags.HighPriority |
(int)NotificationFlags.ShowLights);
builder.SetNotificationDefaults(
(int)NotificationDefaults.Lights |
(int)NotificationDefaults.Vibrate);
builder.SetStatusbarIcon(Resource.Drawable.icon);
// the second parameter is the id. This is the id that you need to set
// in the JSON payload in order for the incoming notification to appear
// in this way.
PushManager.SetNotificationBuilder(Xamarin.Forms.Forms.Context, 1, builder);
And then for the payload, its simply like this:
{"title":"My Title","description":"my description","notification_builder_id":1}
Again, note that the value of notification_builder_id has to correspond with the second parameter in the SetNotificationBuilder() method.

Related

How to collapse multiple notifications into a single one using Firebase?

I have function in Firebase Cloud Functions which is used to send notifications to specific users within my app and has as the notificationContent the following code:
const notificationContent = {
notification: {
title: "My Notification Title",
body: "My Notification Body",
icon: "default",
sound : "default"
}
};
I have tried to use collapse_key: "unique_key" but it has no effect. I read the has an effect only when the device is offline. I also have used a tag: "unique" but every time a new notification arrives, it will override the oldest one.
I there any way in which I can achieve this with Firebase? If I receive more then one notification, to be grouped in a single one?
Thanks in advance!
If you want to use more customizable and advanced notification features.
You should only send FCM with data payload, and create notification at android client side.
Remember that if you send FCM with notification payload or notification + data payload, the notification will be created by android core system and BroadcastReceiver's onReceive method won't being called if your app is on background.
If you send FCM with data payload, it will call onReceive all the time, so you can produce custom notification manually at android client side. (most app uses latter method.)
I hope this link would be helpful.
I had this same confusion and realized I misunderstood what collapseKey and tag are for.
collapseKey will limit the number of notifications a client receives while they're offline, tag is what will stack notifications together in the drawer.
So for a typical cloud function, it should look like this:
const notification = {
notification: {
'title': 'Interesting title',
'body': 'Hello, world'
},
'data': {
'whatever': whatever,
},
'android':{
'collapseKey': collapseKey,
'priority': 'high',
'notification': {
'tag': tag,
}
},
'token': fcmToken
};
admin.messaging().send(notification)
Note that the "tag" parameter sits inside of the android notification, not the top-level notification.
The easiest and most flexible solution is to extend the FirebaseMessagingService and handle the notification yourself. But first instead of using notification on your notificationContent in your cloud function, you have to change that to data so that you send a data message instead of a notification message. The difference is that the notification message will have an implicit collapse key (the package name of the app), while the data message won't have one. But the data message needs to be handled on the client or else it won't be displayed.
Here's a sample of what you'll need for your FirebaseMessagingService:
public class MyFCMService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (remoteMessage.getNotification() != null) {
//this notification was sent from the Firebase console, because in our cloud function, we are using the DATA tag, not the notification tag
//so here we have to handle the notification that was sent from the console
...
} else if (remoteMessage.getData().get(KEY) != null) {
//this data message was sent from our cloud function
//KEY is one of the keys that you are using on the cloud function
//in your example, you are using the keys: title, body, icon, sound
//display the notification to the user
...
notificationManager.notify(TAG, ID, notificationBuilder.build());
//you have to use the same TAG and the same ID on each notification if you want your 2nd notification to simply update the text of the first one, instead of showing as a new notification
}
}
}
PS. When you send a notification from your cloud function (well if you use the data tag, it's actually a data message, not a notification message), then this method will be called, regardless if the app is in the background or in the foreground. HOWEVER, when you send a notification from the firebase console, this method will be called ONLY if the app is in the foreground. If the app is in the background, the Firebase SDK will handle the notification and show it to the user. In some cases, it makes sense to show a notification only when the user is not running the app, for example if you want to advertise some new features of the app. In that case, what you can do is use a unique tag on the notification console (e.g. "display_in_foreground") and check that tag on the client. If you have set that to true, you can show the notification even to users that are currently running the app, or if it's false you can choose not to show the notification. This check will happen only if the app is in the foreground. If it's in the background, this won't be called at all and the SDK will handle to show the notification.

Creating a local notification in response to a push notification (from firebase) in cordova/ionic

I'm building an application using Ionic Framework that implements a chat function similar to good-old facebook messenger, in that i want to notify users of a chat message, but if they view it elsewhere, i want to remove the notification from their home screen.
I'm using firebase as a back-end for push notifications (though that could be changed i suppose).
I know that you can't expire a remote notification, but i've been told you can expire + remove a local notification, so my question is - can i reliably receive a remote notification, create a local one, and display that, and then in response to a notification with a scope of 'expire' or 'remove', delete a local notification so that my users don't see a duplication of information?
Most plugins tend to detect the status of the app and add a remote notification to the homescreen with the info you've pushed by default, is there a way to avoid this?
Thanks guys.
EDIT:
- Local notifications: http://ionicframework.com/docs/native/local-notifications/
- Firebase cloud messaging: https://github.com/fechanique/cordova-plugin-fcm
As far as I can tell there're no plugins which accomplish all what you need. However..
can i reliably receive a remote notification, create a local one, and display that, and then in response to a notification with a scope of 'expire' or 'remove', delete a local notification so that my users don't see a duplication of information?
Most plugins tend to detect the status of the app and add a remote notification to the homescreen with the info you've pushed by default, is there a way to avoid this?
Yes, by using silent notifications and building the local notification by yourself.
For a project I'm working in, I modified the plugin cordova-plugin-fcm to add support for (local on demand) notifications dismiss/display, send multiple notifications to the cordova app, and some PRs that are not included yet. Also I build the notification by myself, to have full control of what is displayed. You can take a look at the code to get some ideas.
In brief it works like this:
Firstly, I send a "silent" push to the app, which is not displayed by Android:
{
"content_available": true, // IMPORTANT: For Apple -> content-available: 1, for firebase -> content_available: true
"priority": "high",
"to": "/topics/all", // or to a fcm token
"data"{
"title": "My title", // this implies that you display the notification by yourself
"body": "My body", // this implies that you display the notification by yourself
"type": "NEW_USER_MESSAGE", // only relevant to this project
"userId": "1", // only relevant to this project
"timestamp", "150000000"
}
}
Note: If the payload have the "notification": {} item, Android will display it on the system tray (if the app is in background).
https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages
Secondly, when the push arrives to the app (in onMessageReceived()), I build the local notification, assigning it a TAG and an ID. This is the way you can use to dismiss it later.
For example, you could create a local notification with the TAG "NEW_USER_MESSAGE" and ID 1 (a constant indicating a state of the message, or the user ID for example). Also, Android will replace notifications with the same TAG and ID, so this is another way to automatically replace notifications (for example if you send a generic message, like "New update available").
public static String TYPE_NEW_USER_MESSAGE = "NEW_USER_MESSAGE";
public static String TYPE_USER_LEFT_ROOM = "USER_LEFT_ROOM";
NotificationManager notificationManager =
(NotificationManager) _ctx.getSystemService(Context.NOTIFICATION_SERVICE);
// based in the type of the message you've received, you can stylize the notification
if (type.equals( TYPE_USER_LEFT_ROOM )){
notificationBuilder.setColor(Color.RED);
notificationBuilder.setLights(Color.RED, 1000, 500);
}
else if (type.equals( TYPE_NEW_USER_MESSAGE )){
notificationBuilder.setColor(Color.BLUE);
notificationBuilder.setLights(Color.BLUE, 1000, 1000);
}
Notification n = notificationBuilder.build();
notificationManager.notify(type, userId, n);
One advantage of doing it in this way, is that you have full control of the notification to be displayed, so you can stylize it like you want.
If you want to discard expired messages, you can check out the elapsed time between the sent timestamp and the current timestamp:
java.util.Date now = new java.util.Date();
java.util.Date sent_timestamp = new java.util.Date( Long.valueOf(timestamp.toString()) );
final Long elapsed_time = ((now.getTime() - sent_timestamp.getTime()) / 1000);
Log.d(TAG, "New message. sent " + elapsed_time + "s ago");
Thirdly, when the user clicks on a notification Android will launch your app, and the plugin will send the payload of the push message to the cordova view (onNotificationReceived()).
Once your app is opened and you have received the push message, you can dismiss it adding a new action to the plugin:
onNotificationReceived(data){
if (data.wasTapped === true){
if (data.type === 'NEW_USER_MESSAGE'){
FCMPlugin.dismissNotification(NEW_USER_MESSAGE, 1);
}
}
}
The Android action:
else if (action.equals( ACTION_DISMISS_NOTIFICATION )) {
cordova.getThreadPool().execute(new Runnable() {
public void run() {
try{
Log.d(TAG, "FCMPlugin dismissNotificaton: " + args.getString(0)); //tag
NotificationManager nManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
nManager.cancel(args.getString(0)/*NEW_USER_MESSAGE*/, args.getInt(1) /*1*/);
Log.d(TAG, "FCMPlugin dismissNotificaton() to remove: " + id); //tag
callbackContext.success();
}catch(Exception e){
callbackContext.error(e.getMessage());
}
}
});
https://github.com/TrustedCircles/cordova-plugin-fcm/blob/master/src/android/FCMPlugin.java#L286
And the method exposed to the cordova app:
// dismisses a notification by tag+id
FCMPlugin.prototype.dismissNotification = function( tag, userId, success, error ){
exec(success, error, "FCMPlugin", 'dismissNotification', [tag, userId]);
}
https://github.com/TrustedCircles/cordova-plugin-fcm/blob/master/www/FCMPlugin.js#L65
The only tricky bit with notifications in cordova/ionic is the JS part receiving the notification and triggering the Android code.
I used https://github.com/phonegap/phonegap-plugin-push library and its pretty straight forward.
There is a callback when notifications are received in JS(Cordova/Ionic), use this to render you notifications locally in Android.
P.S: Basel's answer tells you how to clear your notifications, so I decided to leave that bit out.

FCM Push notifications does not show heads display on notification on top of screen

We are using firebase push notification in Android and in iOS. The push is sent using FCM REST API call. Push type is notification with extra data node.
Here is a sample payload:
{
"notification" : {
"title": "title text",
"body": "message body text",
"sound": "default"
},
"data": {
"messageType": "xxx"
},
"to": "yyy",
"priority": "high",
"time_to_live": 0
}
This type of push notification does not show a heads up display when the app is in background and phone is on. -- Notification just are added to notifications bar but are not sneak peaked to user at the top of the screen. -- no matter if the current app is full screen app or not.
One solution that I have tried and is working is to shift to pure data message where we will not send any notification node, but just the data node and write the code to show notification ourselves and set notification priority to Max (ie .setPriority(Notification.PRIORITY_MAX)) on notification builder object.
But this seems to have issues on iOS where data only pushes are not received/shown to user if the app killed by user.
So is there any workaround to this? any solution that works on Android, but also does not break iOS.
You should set the NotificationPriority to PRIORITY_HIGH or PRIORITY_MAX for Android to show the notification. See Android Notification and Notification Priority for more details.
You should set these values using the constants, not using the strings. E.g.
{
token,
android: {
notification:
{
title,
body,
// See https://developer.android.com/reference/android/app/Notification#PRIORITY_MAX.
// This is deprecated in Android API level 26, but works for older versions.
notification_priority: 2,
// Always allow Android users to see the message in its entirety.
// See https://developer.android.com/reference/android/app/Notification#VISIBILITY_PUBLIC
visibility: 1
}
}
}

Firebase merge similar notifications in Android

We are using Firebase in a SIP app to send us missed call notifications and chat notifications whenever the app was offline.
While sending and receiving works fine, we have the effect on the Android client, that 5 missed calls obv produce 5 missed-call-notifications, filling up the notification bar on the client device.
How can we merge those notifications together, to just show a single "5 missed calls" notification?
Is there any additional flag (like grouping) we can put in the data or notification part of the message?
Here is an example of our current missed call notification:
{
"to":"<<FCMToken>>",
"priority":"high",
"notification":{
"title":"<<Displayname-of-Caller>>",
"text":"<<Date-and-time-of-call>>",
"icon":"icon_notification_missed",
"click_action":"MISSED_CALL"
},
"data":{
"type":"sip-call-missed"
}
}
So what's the trick in combining them together as one?
We found the correct solution.
There are more existing keywords for the notification content.
The one we needed was "tag".
We can even localize the client-side text of the notification by supplying a resource name in loc keys.
Here is a correct message that can be bundled together:
{
"to":"<<FCMToken>>",
"priority":"high",
"notification":{
"title_loc_key":"notification_missed_call",
"tag":"MISSED_CALL",
"body_loc_key":"notification_missed_call_multiple",
"body_loc_args":["<<missed_call_count>>"],
"icon":"icon_nav_main_chat",
"click_action":"MISSED_CALL"
},
"data":{
"type":"sip-call-missed"
}
}
The tag will be merged by the client ... say: they will replace each other. Whenever a notification with a tag arrives, it replaces all other existing notifications with the same tag.
So the trick here is, to supply a running count <<missed_call_count>> (which the server has to count), so the client can show an increasing number, like "5 missed calls".
The string "%d missed calls" is stored in the client side string resource named "notification_missed_call_multiple".

How to customize baidu push notification?

I am using baidu push notification in my app. The issues i am facing are i am not able to customize its notification UI and not able to clear it from status bar unless i tap on that. I could see below code in theirs demo project to customize the UI. But it does not make any difference. please help me.
CustomPushNotificationBuilder cBuilder = new CustomPushNotificationBuilder(
getApplicationContext(), R.layout.notification_custom_builder,
R.id.notification_icon, R.id.notification_title,
R.id.notification_text);
cBuilder.setNotificationFlags(Notification.FLAG_AUTO_CANCEL);
cBuilder.setNotificationDefaults(Notification.DEFAULT_SOUND
| Notification.DEFAULT_VIBRATE);
cBuilder.setStatusbarIcon(getApplicationContext().getApplicationInfo().icon);
cBuilder.setNotificationTitle("push");
cBuilder.setNotificationText("baidu");
PushManager.setNotificationBuilder(getApplicationContext(), 1, cBuilder);
I got answer for this question. Actually the second parameter i pass in PushManager.setNotificationBuilder(getApplicationContext(), 1, cBuilder); is notification ID. Means if u want to display a custom UI from server this id should be passed with notification. Then client will take corresponding builder with that ID. In my case i was not getting this parameter from server
you can pass setNotificationTitle("notification_title"); and setNotificationText("notification_content"); this two parameter is fixed from baidu push notification server

Categories

Resources