Deep Link with Push Notification - FCM - Android

Maulik Dodia picture Maulik Dodia · Jul 3, 2018 · Viewed 20.2k times · Source

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

Answer

Maulik Dodia picture Maulik Dodia · Aug 9, 2018

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;
    }
}