Deep Link with Push Notification - FCM - Android
I

1

31

What I want: I want to send push notification to users. When user tap on that notification, user should navigate to specific activity.

What I did: I created one deep link in Firebase console. I implemented FirebaseInstanceIdService & FirebaseMessagingService as well. I'm able to catch Firebase message which I sent from Firebase console.

What is the issue: I'm not able to catch the dynamic link what I have created in Firebase console.

My code is like below.

MyFirebaseInstanceIDService.java

    public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {

    private final String TAG = "MyFirebaseInstanceID";

    @Override
    public void onTokenRefresh() {

        String refreshedToken = FirebaseInstanceId.getInstance().getToken();

        Log.e(TAG, "Refreshed token: " + refreshedToken);
    }
}

MyFirebaseMessagingService.java

    public class MyFirebaseMessagingService extends FirebaseMessagingService {

    private final String TAG = "MyFbaseMessagingService";

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {

        String message = remoteMessage.getNotification().getBody();

        Log.e(TAG, "\nmessage: " + message);

        sendNotification(message);
    }

    private void sendNotification(String message) {

        Intent intent = new Intent(this, TestDeepLinkActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setAutoCancel(true)
                .setContentTitle("FCM Test")
                .setContentText(message)
                .setSound(defaultSoundUri)
                .setSmallIcon(R.drawable.common_google_signin_btn_icon_dark)
                .setContentIntent(pendingIntent);

        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        manager.notify(0, builder.build());
    }
}

Firebase Console Image

Firebase Console Image

Imogene answered 3/7, 2018 at 6:40 Comment(0)
I
29

Solution:

  • I have to add intent-filter in an activity in manifest file to which I want to go, on-tapping of push notification. This notification will have some url which is being called deeplink in Android Terminology. You can refer below link for more about deeplink.

https://developer.android.com/training/app-links/deep-linking

  • I was using these two links as a deeplink: "www.somedomain.com/about" & "www.somedomain.com/app".

  • Please do not add http or https in intent-filter, they are not supported. Chekout this conversation for more clarification. I'm putting an image of that chat as well, If in case in future the link gets expire.

enter image description here

  • Please refer below code for how I'm passing deeplink to NotificationManager. intent-filter aumatically intercept and launch that particular activity.

MyFirebaseMessagingService.java

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {

        Map<String, String> data = remoteMessage.getData();

        String title = data.get("title");
        String message = data.get("message");
        String deepLink = data.get("deepLink");

        Notification notification = new Notification();
        notification.setTitle(title);
        notification.setMessage(message);
        notification.setDeepLink(deepLink);

        sendNotification(this, title, message, deepLink);
    }

    public static void sendNotification(Context context, String title, String message, String deepLink) {

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

        if (Build.VERSION.SDK_INT >= 26) {
            NotificationChannel notificationChannel = new NotificationChannel("any_default_id", "any_channel_name",
                    NotificationManager.IMPORTANCE_HIGH);
            notificationChannel.setDescription("Any description can be given!");
            notificationManager.createNotificationChannel(notificationChannel);
        }

        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setPriority(android.app.Notification.PRIORITY_MAX)
                .setDefaults(android.app.Notification.DEFAULT_ALL)
                .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher));

        Intent intent = new Intent();

        intent.setAction(Intent.ACTION_VIEW);
        intent.setData(Uri.parse(deepLink));
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);

        notificationBuilder
                .setContentTitle(title)
                .setContentText(message)
                .setContentIntent(pendingIntent);

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

AndroidManifest.xml

<activity
    android:name=".mvp.view.activity.ActivityName"
    android:label="@string/title_activity_name"
    android:theme="@style/AppTheme.NoActionBar">

    <intent-filter>
        <action android:name="android.intent.action.VIEW" />

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

        <data
            android:host="www.somedomain.com"
            android:path="/about"
            android:scheme="app" />
    </intent-filter>

    <intent-filter>
        <action android:name="android.intent.action.VIEW" />

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

        <data
            android:host="www.somedomain.com"
            android:path="/contact"
            android:scheme="app" />
    </intent-filter>
</activity>

Extra:

  • If you want to receive some more data(i.e userId or loanId) in that activity, you can pass it to while sending push notification from your server(i.e back-end or web based dashboard). You can do like below.

    {
     "data": {
     "userId": "65431214564651251456",
     "deepLink": "www.somedomain.com/app",
     "title": "This is title!",
     "message": "This is message!"
     },
    "to": "FCM token here"
    }
    
  • Important: Below JSON will not work, this is for reference only. This is also nowhere mentioned in documentation. So kindly take care of it. Correct JSON is above.

{
    "to": "FCM Token here",
        "notification": {
            "Body": "This week’s edition is now available.",
            "title": "NewsMagazine.com",
            "icon": "new"
        },
        "data": {
            "title": "This is title!",
            "message": "This is message!"
    }
}
  • You can receive extra data(i.e userId or loanId) in method onMessageReceived of MyFirebaseMessagingService class like below.
String userId = data.get("userId");
intent.putExtra(Intent.EXTRA_TEXT, userId);
  • And in that activity you can write like below in onCreate method.
Intent intent = getIntent();
if (intent != null) {
    String intentStringExtra = intent.getStringExtra(Intent.EXTRA_TEXT);
    if (intentStringExtra != null) {
        userId = intentStringExtra;
    }
}

Imogene answered 9/8, 2018 at 12:46 Comment(6)
Nice explanation : in your answer might make conflict in this<data android:host="www.somedomain.com" android:path="/contact" android:scheme="app" /> we use android:scheme="app" for open specific activity and android:scheme="https" for specific url. refer that link which you have attached.Piles
onMessageReceived() is only executed if the app is opened. So in other situations (I think about 90% of the time!) the push notification will not work for deep linking.Curlpaper
@PayamRoozbahaniFard That's when if you send a 'notification' message or a 'notification + data' message. If 'data message is sent (handled by you), onMessageReceived is triggered (no matter foreground or background)Nims
@Nims You mean if the server sends data then onMessageReceived will get called everytime doesn't matter if your app is in the foreground or in the background?Imogene
@MaulikDodia Yes, if your server ONLY sends 'data' (and NOT 'notification') in the fcm payload, then yes onMessageReceived will be called everytime. Reference hereNims
Could you show the json for the fcm with a deep link?Eyebolt

© 2022 - 2024 — McMap. All rights reserved.