FCM notification payload - determine topic name when app is not running - java

Backend server sends FCM notification like this:
{
"to": "/topics/599_7041",
"priority": "high",
"data": {
"id_message": "45"
}
"click_action": "SHOW"
"notification" : {
"body" : "Lorem ipsum",
"title" : "Sample"
}
}
My application subscribes multiple topics. When application is not running, Firebase displays notification and allows me to run app after tap on notification message, with provided click action and pass data (in this case, message_id) to launched app instance.
Good so far. However, in addition, I need to determine from which subscribed topic notification is received. Can I determine it somehow when launching new app instance from notification, or I need to add topic name to data (next to message_id)?
I know I can determine to filed when my app is running, this way:
#Override
public void onMessageReceived(#NonNull final RemoteMessage remoteMessage)
{
//....
String to = remoteMessage.getTo();
}
But, what if my app is not running, so onMessageReceived won't be called.

you can do this:
exports.pushNotification =
functions.database.ref('/messages/{pushId}').onWrite( event => {
console.log('Push notification event triggered');
var valueObject = event.data.val();
console.log("it is"+ valueObject.title);
//Create a notification
const payload = {
notification: {
title:valueObject.title,
body: valueObject.message,
sound: "default"
},
};
This way you are using the database trigger onWrite, that checks if any messages have been written under the pushid.
Then you retreive the data from the database using: var valueObject = event.data.val();.
And in the notification{..} you can use valueObject.title which will be the topic name, thus when recieving a notification, the topic name will be in the title of the notification and thats how you can know what topic it is.
For more info check https://firebase.google.com/docs/functions/database-events

Related

Kotlin - RxJava Subscribe doesn't trigger whene there is an event

I Initialize Publish Subject Rx Java in my activity like this
private var publisher = PublishSubject.create<Int>()
And I try to create simple publish onNext like this in a button :
binding.btnFab.setOnClickListener {
publisher.onNext(99)
}
I try to listen the changes in function
CompositeDisposable().add(publisher.ofType(Int::class.java).subscribe(
{
"ON NEXT ${it}"
},
{
"ON ERROR"
},
{
"ON COMPLETE"
}
))
But there is no one data that come out from my subscribe? do i make a mistake

Hide push notification if it contains specific elements

I won't show a received push notification from appearing top notifications menu my notification if it has for example key update. For now if I get notification with this key, all notifications are in the notification bar. I want to not present this notifications for user.
I'm using WakefulBroadcastReceiver for handle notifications like below:
public class PusherReceiver extends WakefulBroadcastReceiver {
private boolean isAppOnForeground(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
if (appProcesses == null)
return false;
final String packageName = context.getPackageName();
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
return true;
}
}
return false;
}
public void onReceive(final Context context, Intent intent) {
Log.i("SimpleWakefulReceiver", "Starting service # " + SystemClock.elapsedRealtime());
if (!isAppOnForeground((context))) {
String pushNotificationBody = intent.getStringExtra("alert");
try {
JSONObject notificationData = new JSONObject(pushNotificationBody);
// This is the Intent to deliver to our service.
Intent service = new Intent(context, BackgroundService.class);
// Put here your data from the json as extra in in the intent
service.putExtra("notification", pushNotificationBody);
Log.i("PUSH_NOTIFICATION_JSON", "RECEIVED JSON " + notificationData);
// Start the service, keeping the device awake while it is launching.
if (!notificationData.has("update")) {
startWakefulService(context, service);
} else {
// Do nothing
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
UPDATE:
I changed project a little and with Onesignal and his NotificationExtenderService, I did something like below:
public class NotificationNotDisplayingExtender extends NotificationExtenderService {
#Override
protected boolean onNotificationProcessing(OSNotificationReceivedResult receivedResult) {
String notification = receivedResult.toString();
String notificationBody = receivedResult.payload.body;
JSONObject notificationBodyJSON = null;
try {
notificationBodyJSON = new JSONObject(notificationBody);
} catch (JSONException e) {
e.printStackTrace();
}
JSONObject pushNotificationData = notificationBodyJSON;
boolean hidden = false;
if (pushNotificationData.has("update")) {
Log.i("NOTIFICATION MANAGER", "PREVENT DISPLAY NOTIFICATION");
hidden = true;
}
// Return true to stop the notification from displaying.
return hidden;
}
}
And it prevent displaying notifications with update key, but now I don't receive it in my PusherReceiver to start my service. Is there easy way to send data from my NotificationNotDisplayingExtender receivedResult to my PusherReceiver?
For now it looks like my PusherReceiver don't fire his onReceive method.
Many thanks for help in advance.
There are two types of payload.
1. Data
2. Notification
https://developers.google.com/cloud-messaging/concept-options
Use only data payload. Then you always get the call in FirebaseMessagingService onMessageRececived Method
The thing is basically we have two type of notifications.
One which can be called Notification Type, is that the push has a notification object in sent/received bundle, in which you have to handle it when your app is in foreground and the notification is received. In this case, if your app is in foreground, then you can handle it and do whatever you like which is not showing a notification. But if the app is in background, a notification will automatically create by google and it takes predefined title and message objects within the received push bundle to make the notification.
Second type which can be called Data Type, do not have any notification object in the sent/received bundle. In this scenario, your app is in foreground or background, you should handle everything. So, if you put your data in data object of your push notification message, everything will be in your hands.
So, in short, just put your data in data object of your notification and implement your desired logic.
I do not see the JSON data you are referring to. However, I suppose the update key in your JSON is containing null. In your code you are checking if the JSON data has the key update in it. This function will always return true if the key exists in the JSON body. You might have the field with null value which is indicating that you are not supposed to show the notification in the system tray.
In that case, you might consider using isNull function. It returns true if this object has no mapping for update or if it has a mapping whose value is null.
// Start the service, keeping the device awake while it is launching.
if (!notificationData.isNull("update")) {
startWakefulService(context, service);
} else {
// Do nothing
}
And yes, please use the data payload from the notification that you get.
Every time you notify the NotificationManager to show a notification, you provide an ID to be used for the notification to edit or cancel that notification later on. If you show a notification by manager.notify(notificationId, notification), you can cancel it with manager.cancel(notificationId).
If you want to remove all the notifications, you can use NotificationManager.cancelAll().

Backendless - should i subscribe to a channel from service?

In Backendless, there is a method from which I can subscribe to a channel and listen for incoming messages.
Backendless.Messaging.subscribe(
channelName, //some random name
500, //500 ms interval for polling
new AsyncCallback<List<com.backendless.messaging.Message>>() {
#Override
public void handleResponse(List<com.backendless.messaging.Message> messages) {
System.out.println("message received on your channel");
}
#Override
public void handleFault(BackendlessFault backendlessFault) {
}
},
new AsyncCallback<Subscription>() {
#Override
public void handleResponse(Subscription subscription) {
System.out.println("You subscribed to channel" + subscription.getChannelName() + " succssesfuly");
}
#Override
public void handleFault(BackendlessFault backendlessFault) {
System.out.println("Error: " + backendlessFault.getMessage());
}
}
);
If it subscribes from the MainActivity, and data was sent while the app is in another Activity, how can it grab the data from the response (the List in the first handleResponse method) and use it in other activities?
Should I use a service? Should I bind activities to this service with the listener?
Or is there any less complicated way to accomplish my need?
In the very near future i want this listener to work when the app is in the background and show a notification to a user.
Backendless uses two types of Messaging, see Publish-Subscribe Messaging & Push Notifications. The first one is implemented using the listener you used above. The second one uses a service. please refer to the docs, although they are not very good at all they do provide the necessary information.

Android notification from device 1 to 2

I am developing an app for android using eclipse, what i'm basically trying to do is:
send an notification form my device(1) to another device(2).
I am using user log in with is already configured with a database.
When I press down on user(when i press down on a button that sends the notification).
I want device 1 to send an notification that shows on device 2.
Both devices are logged in with different users, but I can't make the notification part to work.
edit: when I push the button the notification displays on device 1, but iI want it to display on device 2...
This is the code of receiving a notification:
public void NmRecv(String username, String message)
{
FriendInfo friend = FriendController.getFriendInfo(username);
MessageInfo msg = MessageController.checkMessage(username);
if ( msg != null)
{
Intent i = new Intent(TAKE_MESSAGE);
i.putExtra(MessageInfo.USERID, msg.userid);
i.putExtra(MessageInfo.MESSAGETEXT, msg.messagetext);
sendBroadcast(i);
String activeFriend = FriendController.getActiveFriend();
if (activeFriend == null || activeFriend.equals(username) == false)
{
localstoragehandler.insert(username,this.getUsername(), message.toString());
showNotification(username, message);
}
}
}
any ideas?
You can achieve that using Google Cloud Messaging.
Also check this link.
You'll have to register the Android devices' keys in order to be able to send notifications.
In other words. You need to store the devices' keys in the Database when they log in.
And then when device1 wants to send a notification to device 2 you do that using GCM and the device 2 key that's stored in the database.
Here's an example of the code I'm using server side to send a message using GCM:
Sender sender = new Sender (SENDER_API_CODE);
Message message = new Message.Builder ()
.collapseKey ("1")
.timeToLive (2419200)
.delayWhileIdle (false)
.addData ("message", "example message")
.build ();
result = sender.send (message, reGid, sendCount);
Receiving side you have to create a Broadcast Receiver with these actions:
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<action android:name="com.google.android.c2dm.intent.GCM_RECEIVED_ACTION" />
and then when you receive the intent you get the message like this:
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType))
{
//Here you process the intent like you normally would
//String parameter = intent.getStringExtra("name of parameter");
//...
//After that you can create a notification like in the link below.
}
creating notifications

How to suppress new SMS notification?

I'm writing my own SMS messenger and I need to completely suppress new SMS notification raised by default stock messenger. For sure I'm intercepting incoming SMS notification and aborting Broadcast through BroadcastReceiver.abortBroadcast(), like:
public void onReceive(Context context, Intent intent) {
Map<String, String> msgs = retrieveMessages(intent);
for (String address : msgs.keySet()) {
String msg = msgs.get(address);
Log.i(TAG, "New sms received=" + msg);
//saving message in phone
Message message = Message.createIncomingMessage(address, msg);
message.setSeen(1); ////mark message seen, so stock messenger couldn't arose notification
message.setRead(1); //mark message read, so stock messenger couldn't report it as unread
message.setUnread(true); //mark message unread for our messenger
message = Me.getMe().getMessageDAO().save(context, message); //saving message
SmsReceiver.updateNotification(context, message, true, true); //raise notification from "our" messenger
}
//aborting default broadcast, since everything already done and no need to do more
this.abortBroadcast();
}
Everything works as planned. But whenever I'm inserting new SMS into database through Me.getMe().getMessageDAO().save(context, message); within few seconds stock messenger somehow is being notified about new message in database and again raises notification.
Question is: how to suppress this notification?
first you need to set priority of your receiver see docs.
secondly, call abortBroadCast before you do heavy processing task(storing into DB).
or you can try this db storing thing in a thread, Start the thread and call abortBroadcast() immediately.

Categories

Resources