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
Related
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 implemented firebase into my app to use it's notification service a while back and it worked, and today decided to use it's key/value feature, but realized that no matter what I write in my class inherited from FirebaseMessagingService, nothing happens. So I decided to remove the my class for dubugging purposes, and I still got notifications. So I removed the firebase messaging service from the manifest, deleted the app cache and ran the project, but I still get notifications! The only way I can prevent notifications from coming is to remove the firebase dependency in gradle. What's happening here?
Just read the documentation.
...
Ok, let's go: there are three kind of "notification" using Firebase: notification messages, data messages and messages with both notification and data. Each is received and handled differently by the system. Here you can see more information about message types (how there are built).
There are handled like that:
Notification message
App in foreground: onMessageReceived's implementation
App in background: system tray (system dispatch automatically notification) -> with or without service implementation (maybe your case, without code I can't know)
Data message
App in foreground: onMessageReceived's implementation
App in background: onMessageReceived's implementation
Message with both notification and data
App in foreground: onMessageReceived's implementation
App in background: system tray (notification) and in extras of the intent (data)
But without any code or notification information, I can't continue to help you. Until you provide some code example, I only think that you send a notification message, and so system automatically display a notification and there is no call to the service's onMessageReceived, it's normal.
If you want to "control" and decide if notification should be shown or not, just send data messages, and in your onMessageReceived implementation, create a notification with content and intent and notify it to the system (if you want it to be shown).
I am using fcm push notification for my android app. I was able to display push notification on system tray when app is not launched. When I tap on the notification it opens the app launcher by default and I start an activity A from there. But the issue is, if I put the app to background and click on the app icon it again opens the app launcher rather than opening existing Activity A.
If the app process is killed, start the launcher activity. If the app is in the background, you can pass an intent to the notification which starts a DummyActivity that has no code on it, and immediatelly calls finish() on its onCreate() method. This will bring your app to the foreground.
Several things are not clear in your question. For example: How you send messages (from developer console or through rest api post requests to firebase backend)? What is your desired behaviour for app when push messages come? I will try to give you general answer that probably helps you to address issue and understand how to implement desired behaviour.
In any case, there are two types of Firebase push messages:
data messages
notification messages
more details about it check on Notification & data messages page
If you want to send additional details to activity that you are starting (something similar to bundle extras), you should use data messages and handle those in your service that extends FirebaseMessagingService by overriding onMessageReceived(RemoteMessage remoteMessage) method. This method is preferable for me because it is much more flexible. You can define all the details about showing notification based on received firebase message, including if notifications are bundled, what happens in details when user click notification and almost everything related to it.
If you don't need to start certain activity with some parameters, than you can use push messages and just define click_action. This method allows you to add define title, text and sound of notification (beside some other details) but it is not as flexible as if you send data messages
Here you can find detailed overview of possible parameters that you can use for different type of messages
Hope this helps
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.