[SalesForce] Android Deep linking from ET Push Notification

We currently have push notifications sent to both our Android and iOS apps via Exact Target. We are testing including links to products from our site in those notifications to allow users to deep link directly to the relevant product page in the app when the user taps on a notification. On iOS this is working correctly, but we are having trouble making this work at all on Android devices.

We are using v4.9.2 of the ET Push SDK.

On Android we are using a custom notification builder to create the notification the user sees. Part of constructing the notification in our code is to specify the intent which will be used and transmitted back to the app once the user taps on the notification. What should happen is that the user taps on the notification, and our app is sent the intent we constructed, which in our case would include the deep link we received in the push from ET (note that receiving the link from ET is not a problem – the payload does correctly contain a link field).

What actually happens when the user taps on a notification is that the app just gets a generic intent which opens the app to its default state, rather than the custom intent we constructed in our custom notification builder. We thus do not see the link and cant redirect the app to the product page.

This is the code we use to construct the custom notification:

public class CustomNotificationBuilder {

/**
 * Build an ETNotification that has been customized to our liking.
 *
 * @return
 */
public static ETNotificationBuilder buildETNotification(Context appContext) {
    return (context, payload) -> {
        // Allow the SDK to setup the builder
        NotificationCompat.Builder builder =
                ETNotifications.setupNotificationBuilder(context, payload);

        // Ensure we have the appropriate icons being used
        builder.setSmallIcon(R.drawable.ic_notification_rue)
                //ET sets the large icon as our app icon by default. That is not the desired
                //behavior on android per the android guidelines and style guide.
                .setLargeIcon(null)
                .setColor(context.getResources().getColor(R.color.neutral_9));

        // set sound and vibration based on preferences
        SharedPreferences preferences =
                PreferenceManager.getDefaultSharedPreferences(context);

        if (!preferences.getBoolean(
                DataStoreManager.UserPreferenceKey.PUSH_SOUND.getValue(),
                false)) {
            builder.setSound(null);
        }

        if (!preferences.getBoolean(
                DataStoreManager.UserPreferenceKey.PUSH_VIBRATE.getValue(),
                false)) {
            builder.setVibrate(null);
        }

        // Deep linking from the push notification: provide the link in an intent and post the notification ourselves,
        // since ET refuses to pass us the correct intent we give it
        String link = payload.getString("link");
        if (!TextUtils.isEmpty(link)) {
            Uri linkUri = Uri.parse(link);
            Intent contentIntent = new Intent(Intent.ACTION_VIEW).setData(linkUri);
            PendingIntent pIntent = PendingIntent.getActivity(appContext, 38456, contentIntent, PendingIntent.FLAG_CANCEL_CURRENT);
            builder.setContentIntent(pIntent);
        }

        return builder;
    };
}
}

According to the Android SDK documentation, NotificationBuilder.setContentIntent will set a pending intent to be provided to the app when the notification is clicked. As you can see this is what we're doing in the code, but we do not receive that intent when the user does tap the notification. So it works for an action button, but not for the notification tap itself.

As I side note if I set the intent via an action then the app does receive the correct intent (when the user taps on the action button that is attached to the notification):

builder.addAction(R.drawable.ic_notification_rue, "View", pIntent);

Best Answer

The issue here is that once the SDK receives the Builder from your method it will also call Builder#setContentIntent which will override the Intent you originally set.

A workaround for you would be to register an implementation of ETNotificationLaunchIntent that returns a null Intent.

ETNotifications.setNotificationLaunchIntent(new ETNotificationLaunchIntent() {
  @Override public Intent setupLaunchIntent(Context context, Bundle payload) {
    if (TextUtils.isEmpty(payload.getString("link"))) {
      return null;
    }

    //Allow other notifications to work as expected.
    return ETNotifications.setupLaunchIntent(context, payload);
  }
});

If the SDK finds that the launch intent is null it will not override the Intent set on the Builder.

One additional note: If you want to get analytic data for notification opens you must first add the payload to the Intent you created, then use ETNotifications.createPendingIntentWithOpenAnalytics when creating the PendingIntent for the Builder.

        contentIntent.putExtras(payload);
    builder.setContentIntent(ETNotifications.createPendingIntentWithOpenAnalytics(context, contentIntent, true));
Related Topic