Push notifications in Expo for React Native
Expo Push API provides a simple and easy-to-use service abstraction layer for push notifications on top of Apple and Android services.
What is a Push Notification?
A push notification is a block of targeted message sent from a backend service to a specific app on a mobile device. The message block contains a “data” payload and some other helper information. The backend sending the message block can, in essence, be any system in the internet; however, in common discussions, the 2 most common ones that come up are Firebase Cloud Messaging for Android devices and Apple’s Apple Push Notification Service for Apple devices. The size of the message block is limited in size and content by the individual providers.
Why Push Notifications ?
Push Notifications or PSNs were originally developed to help apps bring certain information to the user’s knowledge at times when the user was not actively interacting with the app. Soon they evolved to serve some secondary purposes like, for backend servers to also alert certain variations of app versions to sync or pull data from the backend systems.
These days PSNs are used in various use cases likes alerting users of an upcoming sales, reengagement triggers, price alerts in trading, bank transactions, etc.
Expo’s Push Notifications
In an effort to create a simple suite of application development services on top of React Native, Expo has created a ridiculously simple method of sending out PSNs to app built with Expo on React native irrespective of the type of device it is. More so, it does not require any pre-registration of accounts, etc to get going.
They achieve this, by creating a wrapping service layer on top of both (Android) FCM and (Apple) APNS services. Using a single identifiable token irrespective of the device type, your app’s backend can send a targeted message to your app on any mobile device irrespective of whether it is an Apple or Android device. On top, you as a developer do not need to pay any service fee for usage of PSN service to Google or Apple(actually Apple does not charge for PSNs).
How does it work ?
A pretty documentation is available here: https://docs.expo.dev/push-notifications/overview/
In my own words, it all starts with adding the ‘expo-notifications’ library. Using it, get the device’s ExponentPushToken, which uniquely identifies the device to Expo’s backend services. Now you can store this token string in your backend system, and when you need to send a PSN to a device, send a POST API call to Expo’s open API url. It’s advisable to bundle together PSNs for multiple devices into a single API call. You get back a status response message for every device you wanted to send the PSNs to, and thereon, deal with retries, failure, etc as per the SLOs documented in the link above.
Even though the API it is a simple, single API call for sending and status checks of PSN delivery, there are SDKs now available for backends written in all common languages like Go, .NET, Python, Rust, Node, etc.
Go Native ?
If you would still want to use FCM or APNS services, on your Expo-based React Native app, you can very well do so. To get the device’s underlying token, Expo exposes a single native module call that returns the respective DeviceToken for Android and iOS devices. You can continue to use this device token as you would on FCM-based and APNS-based PSN implementations.
Foreground and Background PSN
A Foreground PSN is interpreted as one that is received on the device while the user is actively interacting with the device. In Expo’s PSN implementation, a foreground PSN does not automatically show up in the Controls Center in iOS or Notifications Tray in Android.
Instead they are delivered to the app, and the app is expected to consume the message and act on it.
A Background PSN is one that is received on the device when the user is not actively interacting with the app. If other necessary configurations are done right then, a background PSN will show up in the Notification Tray in Android or Control Center in iOS. Based on the priority configured on the PSN, it might even show as a pop-up on the top of the screen.
Configurations
The programming needed for implementation can be found in the docs here: https://docs.expo.dev/push-notifications/overview/
Beyond this, there are a few subtle configurations needed to ensure it fully works:
For iOS (for push notifications in general):
- Enable Push Notifications under Signing & Capability tab of your target in XCode.
- In the Signing & Capability tab, choose an Apple Developer profile that has an identifier containing a certificate for Apple Push Services.
For iOS (for background notifications specifically):
- Add in the key for remote-notifications in info.plist of iOS:
"ios": { "infoPlist": { "UIBackgroundModes": [ "remote-notification" ], }}
After the above configurations are done, then run a
# npx expo start
or
# expo start — dev-client
to get running.
Although, Expo docs says that adding ‘content-available: 1’ in the PSN payload should deliver the PSN to the app when the PSN is received as background PSN enabling the app to handle the PSN through a receiver of some sort, this does not seem to work as of the date of this writing (end 2022). Issue report: https://github.com/expo/expo/issues/13767
Thoughts
With the Expo Push API service, the Expo team definitely takes a great leap in the direction of abstracting away the devices to develop apps on, enabling app developers to write completely hardware-agnostic apps. Sending Notifications has historically been the holy grain over which each provider has been trying to compete over, and Expo’s move simply takes the fight and the hassles away. A simple few lines of code in the app and a single open API with tokenized calls make the whole experience drastically simple for app developers.
I have not yet completed Expo’s Push API implementation and testing on Android devices yet. Once done, I will include that in this article.
I regularly write about different topics in tech including career guidance, the latest news, upcoming technologies, and much more. This blog was originally posted in my blogs at anirban-mukherjee.com