Edit this page
Learn about notification types and their behavior before you get started.
Notifications have a large surface area and differences across platforms can make implementing notifications intimidating.
Whether you are starting with notifications or have existing knowledge, this document aims to give you a quick start by explaining the different notification types and their behavior that you should understand.
Remember that Expo's notification support builds on top of the native functionality provided by Android and iOS. The same concepts and behaviors from native platforms apply to Expo apps. If you are unsure about a specific notification feature, see each platform's official documentation.
expo-notifications
supports both push and local notifications. You must use a development build to use push notifications since they are not supported in Expo Go.
The rest of this guide focuses on push notifications.
When a push notification arrives to your app, its behavior depends on the app's state and the type of notification. Let's clarify the terminology:
For any kind of notification, when the app is in the foreground, the app is in control of how an incoming notification is handled. The app may present it directly, show some custom in-app UI, or even ignore it (this is controlled by NotificationHandler
). When the app is not in the foreground, the behavior depends on the type of notification.
The table below summarizes what happens when a push notification is delivered to the device:
Notification Type | App in Foreground | App in Background | App Terminated |
---|---|---|---|
Notification Message and Notification Message with data payload | delivery runs NotificationReceivedListener and JS task | OS shows notification | OS shows notification |
Headless Background Notification | delivery runs NotificationReceivedListener and JS task | delivery runs JS task | delivery runs JS task |
For the cases when user interacts with the notification (for example by pressing an action button), the following handlers are made available to you.
App state | Listener(s) triggered |
---|---|
Foreground | NotificationReceivedListener and NotificationResponseReceivedListener |
Background | NotificationResponseReceivedListener |
Terminated | useLastNotificationResponse or getLastNotificationResponseAsync |
In the table above, whenever NotificationResponseReceivedListener
is triggered, the same would apply to the useLastNotificationResponse
hook.
When the app is not running or killed and is restarted by tapping on a notification, theNotificationResponseReceivedListener
may or may not be triggered. To reliably capture the response, we recommend usinguseLastNotificationResponse
orgetLastNotificationResponseAsync
. We plan to improve this behavior in a future release.
A Notification Message is a notification that specifies presentational information, such as a title or body text.
AndroidNotification
aps.alert
dictionary and the apns-push-type
header set to alert
.When you use the Expo Push Service, and specify title
, subtitle
, body
, icon
, or channelId
, the resulting push notification request is a Notification Message.
The typical use case for a Notification Message is to have it presented to the user immediately without any extra processing being done.
This is an Android-only term (see the official docs) where a push notification request contains both data
field and a notification
field.
On iOS, extra data may be part of a regular Notification Message request. Apple doesn't distinguish between Notification Message which does and does not carry data.
Headless Notification is a remote notification that doesn't directly specify presentational information such as the title or body text. With the exception below*, headless notifications are not presented to users. Instead, they carry data (JSON) which is processed by a JavaScript task defined in your app via registerTaskAsync
. The task may perform arbitrary logic. For example, write to AsyncStorage
, make an api request, or present a local notification whose content is taken from the push notification's data.
We use the term "Headless Background Notification" to refer to the Data Message on Android and the background notification on iOS. Their key similarities are that both of these notification types allow sending only JSON data, and background processing by the app.
Headless Background Notifications have the ability to run custom JavaScript in response to a notification even when the app is terminated. This is powerful but comes with a limitation: even when the notification is delivered to the device, the OS does not guarantee its delivery to your app. This may happen due to a variety of reasons, such as when Doze mode is enabled on Android, or when you send too many background notifications — Apple recommends not to send more than two or three per hour.
When you use the Expo Push Service, and specify only data
and _contentAvailable: true
(and other non-interactive fields such as ttl
), the resulting push notification request produces a Headless Background Notification.
To use Headless Background Notifications on iOS, you have to configure them first.
The rule of thumb is to prefer a regular Notification Message if you don't require running JavaScript in the background.
* The exception is when you specify title
or message
inside of data
. In that case, expo-notifications
package automatically presents the headless notification on Android, but not on iOS. We're planning to make this behavior more consistent across platforms in a future release.
Android has a concept of Data Messages. iOS does not have exactly the same concept, but a close equivalent is what we call Headless Background Notifications.
This is a non-exhaustive list of official resources for push notifications on Android and iOS: