How To Handle Notification When App In Background In Firebase
2. How to?
To achieve this, you have to perform a POST
request to the following URL:
Headers
- Key:
Content-Type
, Value:application/json
- Key:
Authorization
, Value:key=<your-server-key>
Body using topics
{"to":"/topics/my_topic","data":{"my_custom_key":"my_custom_value","my_custom_key2":true}}
Or if you want to send it to specific devices
{"data":{"my_custom_key":"my_custom_value","my_custom_key2":true},"registration_ids":["{device-token}","{device2-token}","{device3-token}"]}
NOTE: Be sure you're not adding JSON key
notification
NOTE: To get your server key, you can find it in the firebase console:Your project -> settings -> Project settings -> Cloud messaging -> Server Key
3. How to handle the push notification message?
This is how you handle the received message:
@OverridepublicvoidonMessageReceived(RemoteMessage remoteMessage) {
Map<String, String> data = remoteMessage.getData();
String myCustomKey = data.get("my_custom_key");
// Manage data
}
Solution 2:
To make firebase library to call your onMessageReceived() in the following cases
- App in foreground
- App in background
- App has been killed
you must not put JSON key notification
in your request to Firebase API but instead, use data
, see below.
The following message will not call your onMessageReceived() when your app is in the background or killed, and you can't customize your notification.
{
"to": "/topics/journal",
"notification": {
"title" : "title",
"text": "data!",
"icon": "ic_notification"
}
}
but instead using this will work
{
"to": "/topics/dev_journal",
"data": {
"text":"text",
"title":"",
"line1":"Journal",
"line2":"刊物"
}
}
Basically, the message is sent in the argument RemoteMessage
along with your data object as Map<String, String>
, then you can manage the notification in onMessageReceived
as in the snippet here
@OverridepublicvoidonMessageReceived(RemoteMessage remoteMessage) {
Map<String, String> data = remoteMessage.getData();
//you can get your text message here.String text= data.get("text");
NotificationCompat.Builder notificationBuilder = newNotificationCompat.Builder(this)
// optional, this is to make beautiful icon
.setLargeIcon(BitmapFactory.decodeResource(
getResources(), R.mipmap.ic_launcher))
.setSmallIcon(smallIcon) //mandatory
.......
/*You can read more on notification here:
https://developer.android.com/training/notify-user/build-notification.html
https://www.youtube.com/watch?v=-iog_fmm6mE
*/
}
Solution 3:
I feel like all the responses are incomplete but all of them have something that you need to process a notification that has data when your app is in the background.
Follow these steps and you will be able to process your notifications when your app is in the background.
Add an
intent-filter
like this:<activityandroid:name=".MainActivity"><intent-filter><actionandroid:name=".MainActivity" /><categoryandroid:name="android.intent.category.DEFAULT" /></intent-filter>
to an activity that you want to process the notification data.
Send notifications with the next format:
{ "notification" : { "click_action" : ".MainActivity", "body" : "new Symulti update !", "title" : "new Symulti update !", "icon" : "ic_notif_symulti" }, "data": { ... }, "to" : "c9Vaa3ReGdk:APA91bH-AuXgg3lDN2WMcBrNhJZoFtYF9" }
The key here is add
"click_action":".MainActivity"
where .MainActivity
is the activity with the intent-filter
that you added in step 1.
Get
data
info from notification in the onCreate of.MainActivity
:protectedvoidonCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //get notification data infoBundlebundle= getIntent().getExtras(); if (bundle != null) { //bundle must contain all info sent in "data" field of the notification } }
And that should be all you need to do. I hope this helps somebody :)
Solution 4:
According to the firebase documentation in send downstream using firebase, there is 2 type of payload :
data
This parameter specifies the custom key-value pairs of the message's payload. Client app is responsible for processing data messages. Data messages have only custom key-value pairs.
notification
This parameter specifies the predefined, user-visible key-value pairs of the notification payload. FCM automatically displays the message to end-user devices on behalf of the client app. Notification messages have a predefined set of user-visible keys.
When you are in the foreground you can get the data inside FCM using onMessageReceived(), you can get your data from data payload.
data = remoteMessage.getData();
String customData = (String) data.get("customData");
When you are in background, FCM will showing notification in system tray based on the info from notification payload. Title, message, and icon which used for the notification on system tray are get from the notification payload.
{"notification":{"title":"title","body":"body text","icon":"ic_notification","click_action":"OPEN_ACTIVITY_1"}}
This notification payload are used when you want to automactically showing notification on the system tray when your app is in the background. To get notification data when your app in the background, you should add click_action inside notification payload.
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><actionandroid:name="OPEN_ACTIVITY_1" /><categoryandroid:name="android.intent.category.DEFAULT" /></intent-filter>
Put that intent-filter on your manifest, inside one of your activity tag. When you click the notification, it will open the app and go straight to activity that you define in click_action, in this case "OPEN_ACTIVTY_1". And inside that activity you can get the data by :
Bundleb= getIntent().getExtras();
StringsomeData= b.getString("someData");
I'm using FCM for my android app and use both of the payload. Here is the example JSON i'm using :
{
"to": "FCM registration ID",
"notification": {
"title" : "title",
"body" : "body text",
"icon" : "ic_notification",
"click_action" : "OPEN_ACTIVITY_1"
},
"data": {
"someData" : "This is some data",
"someData2" : "etc"
}
}
Solution 5:
Working as of July 2019
Android compileSdkVersion 28, buildToolsVersion 28.0.3 and firebase-messaging:19.0.1
After many many hours of researching through all of the other StackOverflow questions and answers, and trying innumerable outdated solutions, this solution managed to show notifications in these 3 scenarios:
- App is in foreground: the notification is received by the onMessageReceived method at my MyFirebaseMessagingService class
- App has been killed (it is not running in background): the notification is sent to the notification tray automatically by FCM. When the user touches the notification the app is launched by calling the activity that has android.intent.category.LAUNCHER in the manifest. You can get the data part of the notification by using getIntent().getExtras() at the onCreate() method.
- App is in background: the notification is sent to the notification tray automatically by FCM. When the user touches the notification the app is brought to the foreground by launching the activity that has android.intent.category.LAUNCHER in the manifest. As my app has launchMode="singleTop" in that activity, the onCreate() method is not called because one activity of the same class is already created, instead the onNewIntent() method of that class is called and you get the data part of the notification there by using intent.getExtras().
Steps: 1- If you define your app's main activity like this:
<activityandroid:name=".MainActivity"android:label="@string/app_name"android:largeHeap="true"android:screenOrientation="portrait"android:launchMode="singleTop"><intent-filter><actionandroid:name=".MainActivity" /><actionandroid:name="android.intent.action.MAIN" /><categoryandroid:name="android.intent.category.LAUNCHER" /><categoryandroid:name="android.intent.category.DEFAULT" /></intent-filter></activity>
2- add these lines at the onCreate() method of your MainActivity.class
Intenti= getIntent();
Bundleextras= i.getExtras();
if (extras != null) {
for (String key : extras.keySet()) {
Objectvalue= extras.get(key);
Log.d(Application.APPTAG, "Extras received at onCreate: Key: " + key + " Value: " + value);
}
Stringtitle= extras.getString("title");
Stringmessage= extras.getString("body");
if (message!=null && message.length()>0) {
getIntent().removeExtra("body");
showNotificationInADialog(title, message);
}
}
and these methods to the same MainActivity.class:
@OverridepublicvoidonNewIntent(Intent intent){
//called when a new intent for this class is created.// The main case is when the app was in background, a notification arrives to the tray, and the user touches the notificationsuper.onNewIntent(intent);
Log.d(Application.APPTAG, "onNewIntent - starting");
Bundle extras = intent.getExtras();
if (extras != null) {
for (String key : extras.keySet()) {
Object value = extras.get(key);
Log.d(Application.APPTAG, "Extras received at onNewIntent: Key: " + key + " Value: " + value);
}
String title = extras.getString("title");
String message = extras.getString("body");
if (message!=null && message.length()>0) {
getIntent().removeExtra("body");
showNotificationInADialog(title, message);
}
}
}
privatevoidshowNotificationInADialog(String title, String message) {
// show a dialog with the provided title and messageAlertDialog.Builder builder = newAlertDialog.Builder(this);
builder.setTitle(title);
builder.setMessage(message);
builder.setPositiveButton("OK", newDialogInterface.OnClickListener() {
publicvoidonClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
3- create the class MyFirebase like this:
package com.yourcompany.app;
import android.content.Intent;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
publicclassMyFirebaseMessagingServiceextendsFirebaseMessagingService {
publicMyFirebaseMessagingService() {
super();
}
@OverridepublicvoidonMessageReceived(RemoteMessage remoteMessage) {
Log.d(Application.APPTAG, "myFirebaseMessagingService - onMessageReceived - message: " + remoteMessage);
IntentdialogIntent=newIntent(this, NotificationActivity.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
dialogIntent.putExtra("msg", remoteMessage);
startActivity(dialogIntent);
}
}
4- create a new class NotificationActivity.class like this:
package com.yourcompany.app;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.view.ContextThemeWrapper;
import com.google.firebase.messaging.RemoteMessage;
publicclassNotificationActivityextendsAppCompatActivity {
private Activity context;
@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = this;
Bundleextras= getIntent().getExtras();
Log.d(Application.APPTAG, "NotificationActivity - onCreate - extras: " + extras);
if (extras == null) {
context.finish();
return;
}
RemoteMessagemsg= (RemoteMessage) extras.get("msg");
if (msg == null) {
context.finish();
return;
}
RemoteMessage.Notificationnotification= msg.getNotification();
if (notification == null) {
context.finish();
return;
}
String dialogMessage;
try {
dialogMessage = notification.getBody();
} catch (Exception e){
context.finish();
return;
}
StringdialogTitle= notification.getTitle();
if (dialogTitle == null || dialogTitle.length() == 0) {
dialogTitle = "";
}
AlertDialog.Builderbuilder=newAlertDialog.Builder(newContextThemeWrapper(context, R.style.myDialog));
builder.setTitle(dialogTitle);
builder.setMessage(dialogMessage);
builder.setPositiveButton(getResources().getString(R.string.accept), newDialogInterface.OnClickListener() {
publicvoidonClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
AlertDialogalert= builder.create();
alert.show();
}
}
5- Add these lines to your app Manifest, inside your tags
<serviceandroid:name=".MyFirebaseMessagingService"android:exported="false"><intent-filter><actionandroid:name="com.google.firebase.MESSAGING_EVENT" /></intent-filter></service><meta-dataandroid:name="com.google.firebase.messaging.default_notification_channel_id"android:value="@string/default_notification_channel_id"/><activityandroid:name=".NotificationActivity"android:theme="@style/myDialog"></activity><meta-dataandroid:name="com.google.firebase.messaging.default_notification_icon"android:resource="@drawable/notification_icon"/><meta-dataandroid:name="com.google.firebase.messaging.default_notification_color"android:resource="@color/color_accent" />
6- add these lines in your Application.java onCreate() method, or in MainActivity.class onCreate() method:
// notifications channel creationif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create channel to show notifications.StringchannelId= getResources().getString("default_channel_id");
StringchannelName= getResources().getString("General announcements");
NotificationManagernotificationManager= getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(newNotificationChannel(channelId,
channelName, NotificationManager.IMPORTANCE_LOW));
}
Done.
Now for this to work well in the 3 mentioned scenarios, you have to send the notification from the Firebase web console in the following way:
In the Notification section: Notification Title = Title to display in the notification dialog (optional) Notification text = Message to show to the user (required) Then in the Target section: App = your Android app and in Additional Options section: Android Notification Channel = default_channel_id Custom Data key: title value: (same text here than in the Title field of the Notification section) key: body value: (same text here than in the Message field of the Notification section) key:click_action value: .MainActivity Sound=Disabled Expires=4 weeks
You can debug it in the Emulator with API 28 with Google Play.
Happy coding!
Post a Comment for "How To Handle Notification When App In Background In Firebase"