Interaction

Handle the users interaction with your notifications.

In their basic form, users can only interact with notifications by clearing them from the notification shade, via the "Clear all" button on the device or by physically swiping them away. Notifee allows the user to interact with notifications, and also hook onto events when the interaction occurs.

Press Action

Notifee does not provide any default interaction behaviour when a user presses a notification. The Android guidelines suggest a notification should always open the application when pressed. In React Native, we have multiple options to exactly how the application opens.

If a notification is pressed with no action, a PRESS event published to any subscribers.

Simple behaviour

The most basic & common behaviour is to open the application which displayed the notification:

  • If the application is already open and in the foreground, nothing happens.
  • If the application is in a minimized state it is moved to the foreground.
  • If the application is in a killed state, launch the application.

To set a simple press action, pass an id to the pressAction property:

notifee.displayNotification({
  title: 'New notification',
  android: {
    channelId,
    pressAction: {
      id: 'default',
    },
  },
});

Notifee will now attempt to launch the application when the user presses the notification. View the App Open Events documentation to learn how to read the notification which caused the app to launch.

(Advanced) Custom Component

If required, you can also launch a custom React component when a notification is pressed. This is an advanced concept which allows fine-grain control over how your application is presented to the user.

First, register a new React component as soon as possible in your project:

function CustomComponent() {
  return (
    <View>
      <Text>A custom component</Text>
    </View>
  );
}

AppRegistry.registerComponent('custom-component', () => CustomComponent);

Next, set the mainComponent property to the registered component name:

notifee.displayNotification({
  title: 'New notification',
  android: {
    channelId,
    pressAction: {
      id: 'default',
      mainComponent: 'custom-component',
    },
  },
});

Inside of your /android/app/src/main/java/.../MainActivity.java, override and update the getMainComponentName method:

package com.invertase.testing;
import com.facebook.react.ReactActivity;

// Import the NotifeeApiModule
import io.invertase.notifee.NotifeeApiModule;

public class MainActivity extends ReactActivity {
  @Override
  protected String getMainComponentName() {
    return NotifeeApiModule.getMainComponent("app");
  }
}

The getMainComponent accepts the default registered main component name, which will be used when no initial notification is available or has no mainComponent set.

Rebuild your project. Now when pressed, the application will open using the registered custom component as the main component.

(Advanced) Android Custom Activity

It is also possible to provide a custom Android Activity to launch. This method is in-place to allow users, with native development experience, full control over notification interaction.

Create the new Activity in your project. It must extend com.facebook.react.ReactActivity:

// com.awesome.app
import com.facebook.react.ReactActivity;

public class CustomActivity extends ReactActivity {
  @Override
  protected String getMainComponentName() {
    return "application";
  }
}

Now set the launchActivity on the pressAction:

notifee.displayNotification({
  title: 'New notification',
  android: {
    channelId,
    pressAction: {
      id: 'default',
      launchActivity: 'com.awesome.app.CustomActivity',
    },
  },
});

Rebuild the project. Now when pressed, CustomActivity will be used to launch the React context.

Dismiss Action

When a notification is displayed to users, they are able to dismiss them via the "Clear all" button or physically swiping them away. This can be prevented by creating an ongoing notification (see Behaviour) or with Foreground Service notifications.

When dismissing you can hook into the DISMISSED event, for example, you could update a remote API indicate the user has not read a notification:

import notifee, { EventType } from '@notifee/react-native';

notifee.onBackgroundEvent(async ({ type, detail, headless }) => {
  if (type === EventType.DISMISSED) {
    // Update remote API
  }
});

View the events documentation for more about handling events.

Quick Actions

Quick Actions enable users to interact with your application directly from the notification body, providing an overall greater user experience.

Loading...
Android Actions Example

Quick Action buttons allow users to perform tasks quickly, and can either trigger your application to open or perform a background task (such as marking a conversation as read). The buttons can also trigger user input, allowing the user to enter free text or choose from predefined options.

Adding actions

A notification can add up to three actions buttons. To ensure a good user experience, we recommend following these guidelines:

  • Action text/icons should not be used more than once.
  • Each action should have a clear and obvious meaning.
  • The interaction of each action should be unique. Don't duplicate the action performed.
  • Pressing the notification body (via pressAction) should not perform the same task as an action button.
  • Action text should be kept as minimal as possible (e.g. Reply, Snooze).
  • Once an action has been completed, the notification should be cancelled or updated.

To create notification actions, pass an array of AndroidAction objects into the actions array of the notification options:

notifee.displayNotification({
  title: '08:00am Alarm',
  body: 'The alarm you set for 08:00am requires attention!',
  android: {
    channelId: 'alarms',
    actions: [
      {
        title: 'Snooze',
        icon: 'https://my-cdn.com/icons/snooze.png',
        pressAction: {
          id: 'snooze',
        },
      },
    ],
  },
});

The following code will create a notification with a single action "Snooze", with a unique identifier of snooze. Depending on the device & Android API version, the title and/or icon will be used to display the action button.

Handling interaction

In the example above, we provided the action an pressAction object with an id property. All notification actions should do something, whether it's opening the application on a specific screen or performing a background task (e.g. snoozing an alarm without opening the alarm application).

At a minimum, each pressAction requires a unique ID, which can be used with events to hook into what action was pressed. When pressed, an action sends the ACTION_PRESS event type to any subscribers:

import notifee, { EventType } from '@notifee/react-native';

notifee.onForegroundEvent(({ type, detail }) => {
  if (type === EventType.ACTION_PRESS && detail.pressAction.id) {
    console.log('User pressed an action with the id: ', detail.pressAction.id);
  }
});

Opening the application

It is also possible to open the application when a notification action is pressed, for example to view a specific chat conversation. To trigger the application to open (if it is not already), the launchActivity property on the pressAction can be used. Notifee will use this activity to launch your application:

notifee.displayNotification({
  title: 'New message',
  body: 'You have a new message from Sarah!',
  data: {
    chatId: '123',
  },
  android: {
    channelId: 'messages',
    actions: [
      {
        title: 'Open',
        icon: 'https://my-cdn.com/icons/open-chat.png',
        pressAction: {
          id: 'open-chat',
          launchActivity: 'default',
        },
      },
    ],
  },
});

View the App Open Events documentation to learn more about finding the notification which caused your application to open.

Action input

Users can reply via notification actions, in the form of free text input and/or pre-defined options.

Free text input

To allow free text input on a notification action, set the input property on the action body to true:

notifee.displayNotification({
  title: 'New message',
  body: 'You have a new message from Sarah!',
  android: {
    channelId: 'messages',
    actions: [
      {
        title: 'Reply',
        icon: 'https://my-cdn.com/icons/reply.png',
        pressAction: {
          id: 'reply',
        },
        input: true, // enable free text input
      },
    ],
  },
});

When set, the device will automatically display an input box when the "Reply" action is pressed:

Input action example
Input action example

You may also notice the example provides a "Send" icon on the right hand side of the input area. When the user has entered their free text and presses this icon, it will change to a "pending" state. A pending state indicates to the user something is happening with their action. It is your responsibility to update the notification once the event has been handled (e.g. removing it or updating the text). When the notification has been updated, the pending state will be removed automatically.

Advanced input

The user may also select predefined choices by providing an object to the property input. Ensure allowFreeFormInput is set to false, and provide an array of choices to the property choices:

notifee.displayNotification({
  title: 'New message',
  body: 'You have a new message from Sarah!',
  android: {
    channelId: 'messages',
    actions: [
      {
        title: 'Reply',
        icon: 'https://my-cdn.com/icons/reply.png',
        pressAction: {
          id: 'reply',
        },
        input: {
          allowFreeFormInput: false, // set to false
          choices: ['Yes', 'No', 'Maybe'],
          placeholder: 'Reply to Sarah...',
        },
      },
    ],
  },
});

When pressed, the notification choices will automatically change to a pending state until the notification is updated or cancelled.

To allow users to edit choices before being sent, the allowFreeFormInput & editableChoices must both be set to true. View the AndroidInput documentation for all advanced input options.

Accessing user input

If the user has provided custom input via free text or choices, we're able to grab the input via the onBackgroundEvent subscriber:

import notifee, { EventType } from '@notifee/react-native';

notifee.onBackgroundEvent(async ({ type, detail }) => {
  if (type === EventType.ACTION_PRESS && detail.pressAction.id === 'reply') {
    await updateChat(detail.notification.data.chatId, detail.input);
    await notifee.cancelNotification(detail.notification.id);
  }
});

Input actions enter a pending state once sent, therefore we must cancel or update the notification once the action has completed. In the example above, we updated a chat conversation with the input provided by the user.


Copyright 2020 - 2021 © Invertase Limited

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 3.0 License and code samples are licensed under the Apache 2.0 License.

All product names, logos, and brands are property of their respective owners. All company, product and service names used in this website are for identification purposes only. Use of these names, logos, and brands does not imply endorsement.