Skip to content

Interactive notifications

Alexander Boldyrev edited this page Oct 30, 2024 · 39 revisions

Interactive notifications are push notifications that provide an option for end user to interact with application through button tap action. This interaction can be accomplished by using our predefined categories or creating your own.

Feature is provided since MM SDK version 1.6.16, Huawei SDK 1.0.0.

Each category has its own ID and actions with their IDs. mm_ prefix is reserved for all predefined IDs and cannot be used for custom actions. Actions may bring app to foreground or leave it in the background.

Starting in Android N, actions are shown without icons in order to accommodate more text. An icon should still be provided because devices with earlier versions of the OS continue to rely on it, as will Android Wear and Android Auto devices.

Configure project to use interactive notifications

  1. Add MM SDK dependency to build.gradle file following quick start guide. Interactive messages require only core module library to be included, all other dependencies will be linked transitively.

  2. Use setNotificationCategories method to subscribe to custom categories

Sending interactive notification

Interactive notifications can be tested through our Single PUSH message and Multiple PUSH messages APIs by using category parameter.

Mobile Originated (MO) messages

With Mobile Messaging SDK you can send messages to arbitrary destinations from mobile device. These messages are also known as Mobile Originated (MO) messages. Actionable notifications are one of use-cases for the MO service, meaning that you can trigger outgoing MO message with any of notification actions. For instance, if user taps the "Vote" button, a specific MO message is sent to your backend service. In order to create a notification action that triggers MO messages, you should use withMoMessage method of NotificationAction.Builder:

val voteAction = NotificationAction.Builder()
        .withId("vote")
        .withTitleResourceId(R.string.vote)
        .withIcon(R.drawable.vote)
        .withMoMessage()
        .build()
expand to see Java code

NotificationAction voteAction = new NotificationAction.Builder()
        .withId("vote")
        .withTitleResourceId(R.string.vote)
        .withIcon(R.drawable.vote)
        .withMoMessage()
        .build();

Predefined categories

Mobile Messaging SDK provides one predefined interactive category for now, but this list will be extended.

Display of interactive notifications with predefined categories in notification center can be tested by including interactive module as described in the first step and sending message through Push API. Action handling needs to be implemented as described in the second step.

A = action

Category ID Action ID A - Title A - Foreground A - mo message
mm_accept_decline mm_accept Accept true true
mm_decline Decline false true

Notice

Mobile Messaging SDK provides localization for action button titles of predefined categories. Titles are localized for the following languages: Arabic, Czech, Danish, German, English, Spanish (Latin America), Spanish, Finnish, French, Hebrew, Croatian, Hungarian, Indonesian, Italian, Japanese, Korean, Malay, Norwegian, Dutch, Polish, Portuguese (Portugal), Portuguese, Romanian, Russian, Slovak, Swedish, Thai, Turkish, Vietnamese, Chinese (Simplified), Chinese (Traditional), Hindi.

Notice

You can exclude unnecessary resources from your application if you don't use predefined notification actions:

implementation ('org.infobip.mobile.messaging.api:infobip-mobile-messaging-android-sdk:2.+@aar') {
   transitive = true;
   exclude group: 'org.infobip.mobile.messaging.api', module: 'infobip-mobile-messaging-android-resources' 
}

All localized strings and additional icons will be excluded from your application and predefined actions won't be available.

Custom categories

Setting up custom categories enables you to configure interactive notification categories along with their actions.

Maximum of three (3) actions are shown in the default notification layout. Actions are displayed in the order they've been set (in current example, "cancel" action will be on the left, "share" action will be on the right).

val cancelAction = NotificationAction.Builder()
        .withId("cancel")
        .withTitleResourceId(R.string.cancel)
        .withIcon(R.drawable.cancel)
        .withMoMessage()
        .build()

val shareAction = NotificationAction.Builder()
        .withId("share")
        .withTitleResourceId(R.string.share)
        .withIcon(R.drawable.share)
        .withBringingAppToForeground(true)
        .withMoMessage()
        .build()

val notificationCategory = NotificationCategory("category_share", cancelAction, shareAction)
MobileInteractive.getInstance(context).setNotificationCategories(notificationCategory)
expand to see Java code

NotificationAction cancelAction = new NotificationAction.Builder()
        .withId("cancel")
        .withTitleResourceId(R.string.cancel)
        .withIcon(R.drawable.cancel)
        .withMoMessage()
        .build();
          
NotificationAction shareAction = new NotificationAction.Builder()
        .withId("share")
        .withTitleResourceId(R.string.share)
        .withIcon(R.drawable.share)
        .withBringingAppToForeground(true)
        .withMoMessage()
        .build();
          
NotificationCategory notificationCategory = new NotificationCategory("category_share", cancelAction, shareAction);
MobileInteractive.getInstance(context).setNotificationCategories(notificationCategory);
The following screenshots demonstrate how our example interactive message is displayed on Android 4.4 and Android 7.1.
Share and Cancel buttons in Notification (Android 4.4) Share and Cancel buttons in Notification (Android 7)
Preview of interactive notifications on Android 4.4 and Android 7.1

Actions with input

It is possible to build notifications with input fields a.k.a. "Reply" action for Android 7+. Such actions are typically used in chat and messaging applications. In order to create such notification, you should use withInput() method in notification action builder. You can also provide resource ID for the text that would be show in input field.

val shareAction: NotificationAction = NotificationAction.Builder()
        .withId("reply")
        .withTitleResourceId(android.R.string.reply)
        .withIcon(android.R.drawable.reply)
        .withInput(android.R.string.reply_hint)
        .build()
expand to see Java code

NotificationAction shareAction = new NotificationAction.Builder()
        .withId("reply")
        .withTitleResourceId(R.string.reply)
        .withIcon(R.drawable.reply)
        .withInput(R.string.reply_hint)
        .build();

Mobile Messaging SDK will trigger NOTIFICATION_ACTION_TAPPED event when user presses send button. You can handle this action in the same way as others (Notification Action custom handling) and read the text using NotificationAction.getInputText() method.

private val actionTappedMessageReceiver = object: BroadcastReceiver() {
    override fun onReceive(context:Context, intent: Intent) {
        val message = Message.createFrom(intent.extras)
        val action = NotificationAction.createFrom(intent.extras)
        val notificationCategory = NotificationCategory.createFrom(intent.extras)
        if (action?.id == "reply") { 
            Log.d("ActionTappedReceiver", "User provided text with reply action: " + action.inputText) }
    }
}
expand to see Java code

private final BroadcastReceiver actionTappedMessageReceiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        Message message = Message.createFrom(intent.getExtras());
        NotificationAction action = NotificationAction.createFrom(intent.getExtras());
        NotificationCategory notificationCategory = NotificationCategory.createFrom(intent.getExtras());

        if (action != null && "reply".equals(action.getId())) {
            Log.d("ActionTappedReceiver", "User provided text with reply action: " + action.getInputText()); 
        }
    }
};

Notice

Please note that "reply"-style actions are only available in Android 7+. However, Mobile Messaging SDK will still display these actions as buttons for Android 6 and below. In this case NOTIFICATION_ACTION_TAPPED event will be triggered right after user presses appropriate action button, no input fields will be shown. NotificationAction.getInputText() will be empty. It is on your behalf to configure appropriate behaviour for Android 6 and below: either do not add such notification action through builder or provide a separate activity or dialog to enter text.

Notification action custom handling

Subscribe to NOTIFICATION_ACTION_TAPPED event and you're all set up to test predefined categories. In the event you've subscribed to, you can check which action has been chosen and act upon it:

// declare action tapped message receiver
private val actionTappedMessageReceiver = object: BroadcastReceiver() {
    override fun onReceive(context:Context, intent:Intent) {
        val message = Message.createFrom(intent.extras)
        val action = NotificationAction.createFrom(intent.extras)
        val notificationCategory = NotificationCategory.createFrom(intent.extras)
        if (action?.id == "mm_accept") {
            // message.getCategory() should be the same as notificationCategory.getId()
            // TODO
        }
    }
}

override fun onResume() {
    super.onResume()
    // subscribe to NOTIFICATION_ACTION_TAPPED event
    val localBroadcastManager = LocalBroadcastManager.getInstance(this)
    localBroadcastManager.registerReceiver(actionTappedMessageReceiver, IntentFilter(InteractiveEvent.NOTIFICATION_ACTION_TAPPED.key))
}
expand to see Java code

// declare action tapped message receiver
private final BroadcastReceiver actionTappedMessageReceiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        Message message = Message.createFrom(intent.getExtras());
        NotificationAction action = NotificationAction.createFrom(intent.getExtras());
        NotificationCategory notificationCategory = NotificationCategory.createFrom(intent.getExtras());

        if (action != null && "mm_accept".equals(action.getId()) {
            // message.getCategory() should be the same as notificationCategory.getId()
            // TODO
        }
    }
};

@Override
protected void onResume() {
    super.onResume();
    // subscribe to NOTIFICATION_ACTION_TAPPED event
    LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);
    localBroadcastManager.registerReceiver(actionTappedMessageReceiver, new IntentFilter(InteractiveEvent.NOTIFICATION_ACTION_TAPPED.getKey()));
}
Clone this wiki locally