As instructed in Firebase dev docs, I've implemented a Service that extends FirebaseMessagingService and overrides the onMessageReceived callback. I have put a Log message in the first line inside the onMessageReceived method.
App running in background
I don't see the log in logcat but I see a Notification posted in the system try.
App in Foreground
I neither see the log nor the notification in system tray
Any idea what's going on?
Manifest
<service
android:name=".fcm.MovieMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
Service Class
public class MovieMessagingService extends FirebaseMessagingService {
private static final String LOG_TAG = MovieMessagingService.class.getSimpleName();
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(LOG_TAG, "From: " + remoteMessage.getFrom());
}
/**
* Create and show a simple notification containing the received FCM message.
*
* #param messageBody FCM message body received.
*/
private void sendNotification(String messageBody) {
Log.d(LOG_TAG, "Presenting Notification with message body: " + messageBody);
//more code
}
}
Actually, app's behavior, while receiving messages including both notification and data payloads, depends on whether the app is in the background or the foreground like:
When in the background, apps receive the notification payload in the notification tray, and only handle the data payload when the user taps on the notification.
When in the foreground, your app receives a message object with both payloads attached.
So, The summary is when app is in background, you can see the notification in system tray and can't see any log until tapping on the notification but you will see only the opening activity log not the service log as it's already executed.
And when the app in foreground you can see the log in logcat but you can't see any notification in the system tray as your app already open state you will receive only data payloads.
Here is a code example of how to receive messages and how to handle the different types. Here is the source of the code.
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
/**
* Called when message is received.
*
* #param remoteMessage Object representing the message received from Firebase Cloud Messaging.
*/
// [START receive_message]
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// [START_EXCLUDE]
// There are two types of messages data messages and notification messages. Data messages are handled
// here in onMessageReceived whether the app is in the foreground or background. Data messages are the type
// traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app
// is in the foreground. When the app is in the background an automatically generated notification is displayed.
// When the user taps on the notification they are returned to the app. Messages containing both notification
// and data payloads are treated as notification messages. The Firebase console always sends notification
// messages. For more see: https://firebase.google.com/docs/cloud-messaging/concept-options
// [END_EXCLUDE]
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
}
Related
I am using FCM in my project and when trying to test the incoming notifications with the firebase "compose notification" feature I am putting a title, a body and an image URL to the message and it shows what it should look like - a rich notification with image. But the notification that is being sent to me is a normal one without any image.
here is the firebase UI and what is suposed to happen -
My issue is that I am getting only the text, without the image.
here is my MyFirebaseMessagingService class -
public class MyFirebaseMessagingService extends FirebaseMessagingService {
public static final String RECEIVED_FCM_ACTION = "com.onemdtalent.app.RECEIVED_FCM_ACTION";
public static final String BD_KEY_BODY = "BD_KEY_BODY";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// [START_EXCLUDE]
// There are two types of messages data messages and notification messages. Data messages are handled
// here in onMessageReceived whether the app is in the foreground or background. Data messages are the type
// traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app
// is in the foreground. When the app is in the background an automatically generated notification is displayed.
// When the user taps on the notification they are returned to the app. Messages containing both notification
// and data payloads are treated as notification messages. The Firebase console always sends notification
// messages. For more see: https://firebase.google.com/docs/cloud-messaging/concept-options
// [END_EXCLUDE]
String image = remoteMessage.getData().get("image");
Timber.d("onMessageReceived: %s", remoteMessage.getFrom());
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
String body = remoteMessage.getNotification().getBody();
Timber.d("Message Notification Body: %s", body);
// broadcast
Intent localIntent = new Intent(RECEIVED_FCM_ACTION);
localIntent.putExtra(BD_KEY_BODY, image);
LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
}
}
}
As I sayed, I am getting only the text without the image. what am I missing?
Solved - I used an old version of firebase messaging dependency and I updated it, including my entire project to androidX and now I can see the images :)
I am integrating firebase FCM push notifications on an android app and all things are working fine except when app goes background/killed, the MyFirebaseMessagingService is not called. It works fine when app is in foreground. The onMessageReceived() is not at all called when app is in background.
I want to send push notifications from Firebase console UI only to all subscribers at once, not trying to do 1-1 messaging or sending through web server.
Not that the service is not running when app is closed from Recent Apps tray, the app is not at all working when simply the app goes to background.
Below are the respective codes:
MyFirebaseMessagingService
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
/**
* Called when message is received.
*
* #param remoteMessage Object representing the message received from Firebase Cloud Messaging.
*/
// [START receive_message]
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// TODO(developer): Handle FCM messages here.
// Not getting messages here? See why this may be:
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
if (/* Check if data needs to be processed by long running job */ true) {
// For long-running tasks (10 seconds or more) use Firebase Job Dispatcher.
scheduleJob();
} else {
// Handle message within 10 seconds
handleNow();
}
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
}
Service Declaration in Manifest
<service android:name=".MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
Application Class Declaration
FirebaseMessaging.getInstance().subscribeToTopic("weather")
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
String msg = "Subscribed";
if (!task.isSuccessful()) {
msg = "Message";
}
Log.d("Token", msg);
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
}
});
I am implementing FCM notifications using cloud functions. In a single app I want to send 2 notifications and whenever the notification is received then the app should open with a different activity.
Suppose A is a sender who sends the notification to B(where B is the receiver).
Here it successfully sends the notification and whenever the user clicks on the notification it goes to desired Intent
Now, Whenever B needs to send the notification to A
*I am receiving the notification in an app but when I click on the notification it is going to the above notification Intent page.But I need to redirect to other Intent with data *
Any suggestions in this regard will be appreciated.
Yes, you should use
"android":{
"notification"{
"click_action":"OPEN_ACTIVITY_1"
}
}
and then in android app
<intent-filter>
<action android:name="OPEN_ACTIVITY_1" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
If you have problem with receiving notification in app you should log every push output:
public class FcmListenerService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.i(TAG, "Message received");
// Not getting messages here? See why this may be: https://firebase.google.com/support/faq/#fcm-android-background
Log.i(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.i(TAG, "Message data payload: " + remoteMessage.getData());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.i(TAG, "Message notification: " + remoteMessage.getNotification());
}
}
}
It will only works if app is in foreground. When your app is in the background, notification messages are displayed in the system tray, and onMessageReceived is not called - https://firebase.google.com/support/faq/#fcm-android-background
Update
onMessageReceived called in API 19 but not on 23 and 24.
Update
I am sending FCM notifications from a server, I can receive notifications but onMessageReceived is not called(foreground, background), even with data messages. This is the code I'm using.
import android.app.PendingIntent;
import android.content.Intent;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import uk.co.socktchat.socketchat.MainActivity;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
/**
* Called when message is received.
*
* #param remoteMessage Object representing the message received from Firebase Cloud Messaging.
*/
// [START receive_message]
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// [START_EXCLUDE]
// There are two types of messages data messages and notification messages. Data messages are handled
// here in onMessageReceived whether the app is in the foreground or background. Data messages are the type
// traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app
// is in the foreground. When the app is in the background an automatically generated notification is displayed.
// When the user taps on the notification they are returned to the app. Messages containing both notification
// and data payloads are treated as notification messages. The Firebase console always sends notification
// messages. For more see: https://firebase.google.com/docs/cloud-messaging/concept-options
// [END_EXCLUDE]
// TODO(developer): Handle FCM messages here.
// Not getting messages here? See why this may be:
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
if (/* Check if data needs to be processed by long running job */ true) {
// For long-running tasks (10 seconds or more) use Firebase Job Dispatcher.
scheduleJob();
} else {
// Handle message within 10 seconds
handleNow();
}
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
}
// [END receive_message]
/**
* Schedule a job using FirebaseJobDispatcher.
*/
private void scheduleJob() {
// [START dispatch_job]
// [END dispatch_job]
}
/**
* Handle time allotted to BroadcastReceivers.
*/
private void handleNow() {
Log.d(TAG, "Short lived task is done.");
}
/**
* Create and show a simple notification containing the received FCM message.
*
* #param messageBody FCM message body received.
*/
private void sendNotification(String messageBody) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
}
}
My Manifest file
<service
android:name=".fcm.MyFirebaseMessagingService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<!-- [END firebase_service] -->
<!-- [START firebase_iid_service] -->
<service
android:name=".fcm.MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
json im posting from server
{
"data": {
"title": "5x1",
"body": "15:10"
},
"to" : "d6IJZlXAUZ4:APA91bF8kB_jBn_N93otIdRFsu89ZDhrFsL--i0I4TmS-LO_h3QQ79lu6VlTQe0poNpuUni7N45_jw2XMli",
"priority" : "high",
"content_available" : true
}
I don't see anything wrong, I tried different versions of Android, thinking android version could be any reason, but didn't seem the find any problem. Any ideas? Thank you.
Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.e(TAG, "Notification Payload: " + remoteMessage.getNotification().getBody());
//handleNotification(remoteMessage.getNotification().getBody());
}
Check if message contains a data payload.
if (remoteMessage.getData().size() > 0){
Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString());
handleNotification(remoteMessage.getData());
}
As per FCM document
Notification messages contain a predefined set of user-visible keys.
Data messages, by contrast, contain only your user-defined custom
key-value pairs. Notification messages can contain an optional data
payload. Maximum payload for both message types is 4KB, except when
sending messages from the Firebase console, which enforces a 1024
character limit.
check that your message size is within limit.
In fact onMessageReceived is being called the whole time, it is just that Logcat didn't show any messages, weird enough it happened only with devices of API 19 above, on a device with API 19 Logcat is showing the messages, I can't explain why this happened but my problem was solved.
I set up the Firebase messaging with my app, but unfortunately the notifications are not coming.
I set up Firebase properly, it is connected to my app, I also sent some test messages, in the Firebase it says completed, however I did not receive them on my phone.
My app is not in the store yet, I am developing and testing it via Android studio.
Here is my MyFirebaseInstanceIDService class
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
private static final String TAG = "MyFirebaseIIDService";
/**
* Called if InstanceID token is updated. This may occur if the security of
* the previous token had been compromised. Note that this is called when the InstanceID token
* is initially generated so this is where you would retrieve the token.
*/
// [START refresh_token]
#Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);
// TODO: Implement this method to send any registration to your app's servers.
sendRegistrationToServer(refreshedToken);
}
// [END refresh_token]
/**
* Persist token to third-party servers.
*
* Modify this method to associate the user's FCM InstanceID token with any server-side account
* maintained by your application.
*
* #param token The new token.
*/
private void sendRegistrationToServer(String token) {
// Add custom implementation, as needed.
}
}
and here comes the MyFirebaseMessagingService class:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
/**
* Called when message is received.
*
* #param remoteMessage Object representing the message received from Firebase Cloud Messaging.
*/
// [START receive_message]
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// [START_EXCLUDE]
// There are two types of messages data messages and notification messages. Data messages are handled
// here in onMessageReceived whether the app is in the foreground or background. Data messages are the type
// traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app
// is in the foreground. When the app is in the background an automatically generated notification is displayed.
// When the user taps on the notification they are returned to the app. Messages containing both notification
// and data payloads are treated as notification messages. The Firebase console always sends notification
// messages. For more see: https://firebase.google.com/docs/cloud-messaging/concept-options
// [END_EXCLUDE]
//"Title","Message","NotyType", "hotelStatus"
String title = "";
if (remoteMessage.getNotification().getTitle() != null){
title = remoteMessage.getNotification().getTitle();
}
String message = "";
if (remoteMessage.getNotification().getBody() != null){
message = remoteMessage.getNotification().getBody();
}
Log.e("notification","recieved");
sendNotification(title, message);
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
}
// [END receive_message]
private void sendNotification(String title, String body) {
Intent i = new Intent(this, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pi = PendingIntent.getActivity(this,
0 /* Request code */,
i,
PendingIntent.FLAG_ONE_SHOT);
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this,
getString(R.string.default_notification_channel_id))
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(body)
.setAutoCancel(true)
.setSound(sound)
.setContentIntent(pi);
NotificationManager manager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.notify(0, builder.build());
} }
I don't see any logs when debugging, also don't receive any notifications on the phone.
Am I doing something wrong here? Can you please advice? Thanks.
onMessageReceived does not get called with a push sent with just notification tag and your app isn't in foreground. If it is indeed in foreground, your onMessageReceived will get called.
If you want your onMessageReceived to get triggered, you will need to send the push with an additional data tag or just the data tag.
However note, if you send both notification and data tags, your onMessageReceived will only get triggered if your app is in foreground, If it's in background, everything inside the data tag will be passed inside an click intent as extras
Only a Data tag will always call onMessageReceived regardless of whether you app is in foreground or not.
Eg: for just a data tag :)
https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA
{ "data": {
"score": "5x1",
"time": "15:10"
},
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
}
OH now I tried something! I updated my MyFirebaseMessagingService class as you see in my question now, and now it WORKS! From Firebase console I sent only message, no data, and all the notifications I received in my device! Even if my app is running, even if I closed it! Every notification I received. When the app was running, the notification has my custom icon, and when the app is closed, the default "bell" icon is there, but in both cases I received the notifications! Not sure how it is possible, but it works.