There are 3 states that an app can be in :
1. Foreground.
2. Background(minimized)
3. Completely closed( removed from list of active applications)
This is the way I've done it :
1. Forground/Background ->
onMessageReceived(RemoteMessage remoteMessage) is where I get all the messages which I further parse.
Completely closed ->
Intent processInputIntent = getIntent();
int id = processInputIntent.get("id"); // I fetch all the parameters this way.
This method works if I don't do the following changes in the manifest.
The issue is my app is a complete webview and I need to save the state of the app and so I used
android:alwaysRetainTaskState="true"
android:launchMode="singleTask">
Is this the right way of handling things? Any help would be highly appreciated.
So going by the comments. I deduce that the reason you are not getting intent data in activity after adding android:alwaysRetainTaskState="true" is because the task is being retained by the system and system is not creating a new task so now new Root Activity. But according to FCM Docs
When your app is in the background, Android directs notification
messages to the system tray. A user tap on the notification opens the
app launcher by default.
This includes messages that contain both notification and data payload
(and all messages sent from the Notifications console). In these
cases, the notification is delivered to the device's system tray, and
the data payload is delivered in the extras of the intent of your
launcher Activity.
So, I think the solution to this issue is getting DATA PAYLOAD ONLY in onMessageReceived(). And Here is very important info regarding this method.
onMessageReceived() method will not be called if the app is in background or killed and if the message sent contains DATA and NOTIFICATION payload both.
When app is not running you will anyway receive notification. But if you want to intercept data via onMessageReceived() then you will have to create a custom app server which will send only DATA payload to fcm endpoint.
something like this:
{
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data" : {
"Title" : "Title for Notification",
"body" : "Notification body can go here",
"Room" : "Something extra"
},
}
Let me know if it changes anything for you.
Related
I am seeing how Huawei Push Kit works in Android. For this I am using postman to send the notifications, I am sending a notification message and a data message. Notification messages are seen in the notification area, but I can't get the data that I sent in the data message. I would like to know how to get them both when the app is in foreground and background.
You have to include "foreground_show": false to get the message "data" payload to get delivered to "onMessageReceived".. otherwise it will only be displayed in the notification area .. and you wont be able to read the payload..
https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides-V5/android-basic-receivemsg-0000001087370610-V5
Read "Receiving a Notification Message" Title in the above doc
There's a difference between HMS Core Push Kit and FCM. Notification messages will be delivered to the system tray, and data messages will be delivered to the onMessageReceived method by default when using HMS Core Push Kit. So notification message title and body cannot be obtained.
If you want to pass data to your app when sending notification message, you can tap the notification message to trigger the corresponding action such as opening the app, a web page, or a specific page in the app. To obtain data with customized actions, see docs.
For the data message parameters, see this:
{
"validate_only": false,
"message": {
"data": "{'param1':'value1','param2':'value2'}",
"token": [
"pushtoken1",
"pushtoken2"
]
}
}
and get the data with the onMessageReceived() method.
When you send a push notification without explicitly setting the value of the *message.android.notification.foreground_show = **false***, the data content won't be read because the NC (Notification Center of Huawei phones) takes care of the notification (when your app run in the foreground).
The NC doesn't implement the method of reading the data content as stated here by Huawei.
Therefore, you have to instruct your app, so that is your app handling the push-notification rather than the NC.
To do so you have to:
message.android.notification.foreground_show = false in the payload (See here)
You need to declare the implementation class of HmsMessageService in the AndroidManifest.xml file of the app (See here).
Here you can find all the details about the payload of a Downlink Messages
I'm with a problem here.
I have a logic with deep links in my push notification.
This is the FCM's json now:
{
"to": token_here",
"data": {
"DEEP_LINK_PATH": "STRING_HERE",
},
"notification": {
"title": "Teste",
"body": "Push de teste"
}
}
As you can see, all the logic for deep links is inside DATA, as usual.
When my app is open, everything looks fine.
But when its close, or in background, not working because its not passing inside my FirebaseMessagingService. Its seens like the notification is creating automatic by Android with base in NOTIFICATION body and title.
Is there a way to continue using this model of json and receive FirebaseMessagingService be call in background too?
Firebase Cloud Messaging has two basic types of messages:
Notifications messages
These messages are delivered to your application code when the app is active, and are handled by the system (Android in your case) when your app is not active. The system displays them as a notification in the system tray in that case.
Data messages
These messages are always delivered to your application code, no matter if the app is active or not. Your application code can either display a message when it receives a data message, or process it in any other way you see fit.
So it sounds like you're looking for a data message.
Also see:
the documentation on message types
the documentation on sending messages
I am developing an e-mail app in which I want that the user will get a push notification as soon as they receive new email. And for that purpose I am using FCM. I have just tried push notifications using FCM by following this link: https://www.youtube.com/watch?v=XijS62iP1Xo&t=6s in order to test what features FCM provides. But the problem I face is that the device receives push notifications when app is either in foreground or background but it won't receive any push notifications when the app is closed (swipe or clear from the task manager). I don't know how to achieve this via FCM? I want to receive push notifications just like the WhatsApp and Facebook apps.
Every kind of help is appreciated. Thanks in advance.
There are 2 types of push notifications: Data messages and Notification messages.
If you are using the Data messages you will be in charge of handling the received message and present a notification to the user (if needed of course). But in this case you might miss notifications when your app is closed.
If you are using Notification Messages, FCM is handling the message for you and directly displays a notification if the app is in background/closed.
Please see more here.
It is not possible to receive a push notification in an app that has been killed/stopped by "Force stop" in application settings:
Let me quote the response I got from Firebase Support when I posed them that question:
The Android framework advises that apps that have been stopped (i.e.
killed/force-stopped from Settings) should not be started without
explicit user interaction. FCM follows this recommendation, and thus
does not deliver messages to stopped apps. Here are some documentation
that discuss this topic:
Life of a message from FCM to the device Using Firebase Cloud
Messaging with Android O
This confirms what I observed when I tested it using a simple app.
But you should be able to get push messages from FCM when the app is in background, even if it was swiped off from Recents screen, or after system reboot. That is, unless the manufacturer made the swipe gesture to work the way "Force stop" does on your device. How you receive it in the background depends on whether the push notification contains the "notification" payload:
If it does, you will receive the "data" only if user taps on the notification and it will be delivered in the Intent extras to the activity launched by the notification action.
If it doesn't, you will receive the notification in onMessageReceived just like you do when the app is in foreground.
Some other cases when your app is not killed, but still may not receive push notifications:
there can be delays because of Doze mode if you don't use high priority for the push message
message might not be delivered if your app is background restricted
Yes only if you consider sending data payloads not notifications and handle it in onMessage()
get more info here
How to handle firebase notification on background as well as foreground?
If your App is Killed or in background,check for the Payload in your Launching Screen
in My case it is MainActivity so in onCreate() Check for Extras:
if (getIntent().getExtras() != null) {
for (String key : getIntent().getExtras().keySet()) {
Object value = getIntent().getExtras().get(key);
Log.d("MainActivity: ", "Key: " + key + " Value: " + value);
}
}
I'm working with Firebase Cloud Messaging. I have a couple of question I was not able to understand from the documentation:
Android: Lets suppose the app is closed (not backgrounded: closed). If I send a notification with also the data payload, this data payload is passed to the activity through the Intent Extra
Messages with both notification and data payload, both background and
foreground. In this case, the notification is delivered to the
device’s system tray, and the data payload is delivered in the extras
of the intent of your launcher Activity.
What if the user does not tap on the notification? Is the data payload lost? Is there a way to retrieve it?
iOS/Android. Lets suppose the user disabled the notification and I sent a notification to the client: is there a way to retrieve (pull) the notification at the application start?
Thanks very much
If the app is closed (not in background) the onMessageReceived method is called when the notification is received and there you can retrieve the data payload with remoteMessage.getData().get("key_for_parameter"); where key_for_parameter is the name of the parameter that you send in the notification. This method is called even if the application is closed. However, take into account that the "onMessageReceived" is called only if you omit the "notification" param in the notification (look this post)
So once you have the params in the onMessageReceived you can look for an strategy to use them in your application like storing in the DB and you are not going to lose the data if the user does not click on the notification.
if your app in background, Firebase will not trigger onMessageReceived(). Why.....? I have no idea. In this situation, I do not see any point in implementing FirebaseMessagingService.
According to docs, if you want to process background message arrival, you have to send 'click_action' with your message. But it is not possible if you send message from Firebase console, only via Firebase API. It means you will have to build your own "console" in order to enable marketing people to use it. So, this makes Firebase console also quite useless!
There is really good, promising, idea behind this new tool, but executed badly.
I suppose we will have to wait for new versions and improvements/fixes
I want to open application automatically when notification is received, is this possible with Firebase and new FCM notifications?
I know I can set click_action but that's only for customizing which activity will start on notification click, I need something that will start automatically when notification is received.
I tried the quick start messaging firebase sample and there is a onMessageReceived() method but it only works if the app is in foreground. Is there something that will execute while app is in background as well?
GCM could do something like what I want here by directly starting activity intent from broadcast receiver which is called when notification is received.
Quick answer:
To automatically open an application via FCM you need to use a data-message, which guarantees to always invoke the FirebaseMessagingService.onMessageReceived() method.
Then you can add your logic in the .onMessageReceived() method to start the preferred activity.
WARNING: launching a UI without any user interaction is a very very bad practice for most of the applications! Please read the MarkG answer here:
How to start an Activity from a Service?
[...] Interrupting what the user is currently doing is considered bad design form, especially from something that is supposed to be operating in the background.
Therefore, you should consider using a Notification [...] to launch the desired Activity when the user decides it is time to investigate. [...]
Full explaination:
FCM works similarly to GCM and can receive two types of messages:
display-messages: payload
{"notification" : { "body" : "hello world"}}
These messages are automatically displayed when the app is in background and they call FirebaseMessagingService.onMessageReceived() if the app is already in foreground.
data-messages: payload {"data" : { "key1" : "value1"}}
These messages always invoke FirebaseMessagingService.onMessageReceived(),
even if the app is closed or in background.
click_action is a parameter of the notification payload, thus it applies to the display-messages.
Indicates the action associated with a user click on the notification.
If this is set an activity with a matching intent filter
is launched when user clicks the notification.
https://firebase.google.com/docs/cloud-messaging/http-server-ref#notification-payload-support
It looks like this section of the guide is the key to the puzzle of backgrounded apps:
To receive messages Use a service that extends
FirebaseMessagingService. Your service should override
the onMessageReceived callback, which is provided for most message
types, with the following exceptions:
Notifications delivered when your app is in the background.
In this
case, the notification is delivered to the device’s system tray. A
user tap on a notification opens the app launcher by default.
Messages with both notification and data payload.
In this case, the
notification is delivered to the device’s system tray, and the data
payload is delivered in the extras of the intent of your launcher
Activity.
Essentially, when the app is backgrounded, it's not truly responsive or running at this point. So instead, the message is delivered to the system tray. However, just below, the solution is explained.
If you want to open your app and perform a specific action [while backgrounded], set
click_action in the notification payload and map it to an intent
filter in the Activity you want to launch. For example, set
click_action to OPEN_ACTIVITY_1 to trigger an intent filter like the
following:
<intent-filter>
<action android:name="OPEN_ACTIVITY_1" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
I summarize the steps here, hopefully it helpful
STEP 1
Following FCM user guide. Make sure everything work properly by pushing a message from Firebase console.
STEP 2
Change your custom FirebaseMessagingService class as following:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
startActivity(new Intent(this, SplashActivity.class));
}
}
Now using Firebase console push messages again, you will found that onMessageReceived only fires when your app is in the foreground. Because Firebase console is able to send Notification message only. In order to send Data message, we need step 3.
STEP 3
Install Google Advanced REST client
Input below params:
url: https://fcm.googleapis.com/fcm/send
method: POST
Raw header:
Content-Type: application/json
Authorization:key=YOUR_SERVER_KEY
Raw payload:
{
"to" : "YOUR_DEVICE_FCM_TOKEN",
"data" : {
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark"
},
}
YOUR_SERVER_KEY is available in the Firebase console > Settings pane > the Cloud Messaging tab
YOUR_DEVICE_FCM_TOKEN is FirebaseInstanceId.getInstance().getToken() on onTokenRefresh()
NOTE
Starting UI without user interaction is bad UX, you might need to replace start activity with start service or something in the background. I just use activity for testing purpose, so it will be more visual than service.
Thanks #2ndgab for introducing to the Google Advanced REST client tool.
[Android]
If you are using Firebase Notifications (not Firebase Cloud Messaging) all you have to do is include Firebase Messaging in your build.gradle, and then link your app to a project on Firebase Console.
If your app is in the background, any message sent from the console will give you a system notifiction, which, if touched, will activate your app.
Take a look here: https://youtu.be/KpTSpVh9SfY?t=10m22s