8

I am using the fcm console to send messages to all of devices that have my app installed, the notifications don't have any extra payload only the notification message.

I want to know if there is a simple way to know if an Activity was opened from an FCM notification click.

There is a solution for that by extending the FirebaseMessagingService service and creating a notification by yourself.

I want to know if there is another solution without extending the service or passing extras to the notification.

Is there any extra that is being passed with the Intent that is used for opening the activity from the notification click?

user1940676
  • 4,348
  • 9
  • 44
  • 73
  • what exactly do you want? It's not clear for me you want to know how much of your entry are from the notification??!! – Ashkan Nov 18 '17 at 21:08
  • 4
    @Ashkan: it is written in plain English my friend : "I want to know if there is a simple way to know if an Activity was opened from an FCM notification click." – user1940676 Nov 19 '17 at 17:50
  • If you have **not** subclassed `FirebaseMessagingService`, how a click on notification would launch the activity you need? – azizbekian Nov 20 '17 at 06:50
  • In notification there is a context which holds the activity context so you can get from notification context. – Mohamed Mohaideen AH Nov 20 '17 at 07:31
  • @azizbekian, to send and show notifications firebase don't force you to subclass their service, you can send messages and let users to receive them only by adding the messaging dependency in the build.gradle file. – user1940676 Nov 20 '17 at 12:32
  • *Is there any extra that is being passed with the Intent that is used for opening the activity from the notification click?* - seems like you can easily test that by sending a notification and inspecting the intent extras – Tim Nov 20 '17 at 12:39
  • You can easily check it by passing some boolean like ("from_noti", boolean value(T or F)) in Bundle with the Intent you used to open the Activity and later check the value of boolean in oncreate of the intended activity. – Aman Verma Nov 20 '17 at 13:34
  • don't send `"notification"` in your push notification so you can detect and get your message in `onMessageReceived(RemoteMessage remoteMessage)' it's simple way to get message and get notified that it's from `FCM` – Hanzala Nov 23 '17 at 04:41

3 Answers3

12

I hope you know that FCM based messaging created two types of notification

Firstly, the notification that we create from on onMessageReceived() method, the point to note here is that onMessageReceived() will be triggered if the app is in foreground.

Secondly, FCM creates its own default notification when app is in background, in this case onMessageReceived() is not intercepted and hence we cannot set a pending intent on our own.

Note : the above mentioned types comes to play when you are sending a "notification" push message to your app in the case of a me "data" message onMessageReceived() is triggered irrespective of the app being in foreground or background (the notifications sent from FCM console are "notifications" type push messages)

Coming back to your question, it is not clear if you're sending a push message from FCM console or making a FCM server request, so let's make cases here.

  1. Message being sent by FCM Console :
    send data payload from the advance section in notification panel on FCM which looks like this

enter image description here

when app is in foreground onMessageReceived() will be intercepted use the code below to receive the data payload

public class MyFirebaseMessagingService extends FirebaseMessagingService {

private static final String TAG = "MyFirebaseMsgService";

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    //Displaying data in log
    //It is optional


    //Calling method to generate notification
    sendNotification(remoteMessage.getData());
}

//This method is only generating push notification
//It is same as we did in earlier posts
private void sendNotification(Map<String, String> messageBody) {

    Intent intent = new Intent(this, SplashScreen.class);

    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    PendingIntent pendingIntent = PendingIntent.getActivity(
            this,
            0,
            setNotificationRoute(messageBody),
            PendingIntent.FLAG_UPDATE_CURRENT);
    Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
            .setSmallIcon(android.R.drawable.sym_def_app_icon)
            .setContentTitle(messageBody.get("title"))
            .setContentText(messageBody.get("text"))
            .setAutoCancel(true)
            .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent);

    NotificationManager notificationManager =
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

    notificationManager.notify(0, notificationBuilder.build());


}

private Intent setNotificationRoute(Map<String, String> messageBody) {
    Intent intent = null;
    String type = messageBody.get("type");
    if (type != null) {
        switch (type) {
            case "android":    //intercept your payload here to create swit 
                intent = new Intent(this, MainActivity.class);
                break;
            default:
                break;

        }

    }
    return intent;
}
}

and if app is in background, then on notification click app will be opened on a "default" activity, you can set any activity as a default one by adding the following lines in the app manifest in the activity's intent filter:

<category android:name="android.intent.category.DEFAULT" />

inside this activity you can call to get intent extras and then get the data payload to decide on which activity you need to land on. The code is below

    .
    .
    .

        Bundle bundle = getIntent().getExtras();
            if (bundle != null) {
                setNotificationRoute(getIntent().getExtras());
    .
    .
}
 private void setNotificationRoute(Bundle extras) {
    String type = extras.getString("type");
    Intent intent = null;
    if (type != null) {
        switch (type) {
            case "message":
                String room = extras.getString("room");
                intent = new Intent(this, MainActivity.class);
                startActivity(intent);
                break;
            default:
                break;
        }
      }
    }
  1. Message sent from FCM Server: the message sent from FCM consolse above is same as sending the below json body as post request to FCM server:

    { 
        "notification": {
        "title": "Hi Tester",
        "text": "News for testing",
        "sound": "default",
        "badge": 0
      },
      "data":{
        "type": "credits"
      },
      "priority": "high",
      "to": "{{device_token}}"
    }
    

the process of intercepting the notifications will be same for this case.

ppreetikaa
  • 1,149
  • 2
  • 15
  • 22
Abhishek Tiwari
  • 936
  • 10
  • 25
  • I am using the fcm console to send messages to all of the devices, I have mentioned that, so basically I need to add the extras in the advances section to be able to retrieve them inside the onCreate() of the activity? without extending the messagingservice? (I only want users who don't have the app open to receive the notification) – user1940676 Nov 24 '17 at 09:44
  • "(I only want users who don't have the app open to receive the notification)" so basically you want background notification to work, for that you take the approach for background notification handling that would be getting the intent inside the "default" activity which is mentioned in the manifest and fetching the bundle with the key value that you're passing from advance section of the console. – Abhishek Tiwari Nov 27 '17 at 07:00
  • I am getting null on intent.getExtras. What to do? – Pinkesh Darji Nov 27 '18 at 09:55
  • @PinkeshDarji please elaborate as where are you getting the NPE – Abhishek Tiwari Nov 27 '18 at 10:30
0

if you want to Start any Activity without extending FireBaseMessaging class then you can set this flags with your FCM data payload.

So whenever the user clicked on FCM Notification on System Tray.That defined Activity should open.And if you want to get extra bundle data.you can get it using getIntent().getExtras(); method.

    "message":{
     "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
     "notification":{
       "title":"Match update",
       "body":"Arsenal goal in added time, score is now 3-0"
     },
"android":{
           "ttl":"86400s",
           "notification"{
             "click_action":"MainActivity.class" // define your activity here
           }
         },
 "payload": {
         "aps": {
           "category": "NEW_MESSAGE_CATEGORY"
         }
       }
     }

Please refer to below link:-

"sets the appropriate keys to define the result of a user tap on the notification on Android and iOS — click_action, and category, respectively."

Pankaj Kant Patel
  • 2,050
  • 21
  • 27
-2

No need pass any extra with intent. Just set the flags like

  Intent lIntent = new Intent(getApplicationContext(),YourActivity.class);
        lIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        lIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
        lIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(lIntent);
Kapil Parmar
  • 881
  • 8
  • 19