Implement Push Notifications for React Native App using OneSignal

I recently worked on the implementation of OneSignal and this is a tutorial for anyone who is looking to implement push notifications using the same service or react native app.

Chaudhry Talha 🇵🇸
13 min readSep 21, 2021

Here’s what we’re going to do:

  • Installing OneSignal Package
  • iOS Setup
  • Android Setup
  • Huawei Setup (Optional)
  • React-Native OneSignal Implementation
  • Testing

Installing OneSignal Package

Start by installing the package in your app

npm install --save react-native-onesignal

Head over to https://onesignal.com/ and create a new account.

iOS Setup

Give your app a name and select Apple iOS (APNs) and click on Next: Configure Your Platform.

For iOS 9+ device to test on as you cannot get notifications on the simulator. A mac with XCode +12 and An iOS Push Certificate. We’re going to create this certificate now. You can auto-generate it using OneSignal’s Certificate Wizard but we’re going to follow the manual process.

Open Keychain Access and from the menu select Keychain Access → Certificate Assistance → Request a Certificate From a Certificate Authority…

Give it an email address and a common name and CA email address. Make sure you have selected Saved to disk and it’ll generate a .certSigningRequest which we’ll use later.

Login to your apple developer account and head over to Certificates, IDs & Profile → Identifiers (https://developer.apple.com/account/ios/identifier/bundle)

Select the identifier that has the same identifier as your app.

Scroll down and turn the Push Notifications on.

Don’t click on Configure and Save it. Go to Certificates and click on the blue + button.

Under Services select Apple Push Notification service SSL (Sandbox & Production)

Select your app ID and press Continue

Choose the .certSigningRequest file we created earlier and click continue.

Click on the Download button and it’ll download a .cer file. Open the .cer file and it’ll open in Keychain Access. Select login from the keychain: dropdown and select add.

Right-click on the certificate you just added and select Export “Apple…

Give your file a unique name and it’ll generate .p12

Next, we’ll upload this .p12 file to our OneSignal.

In the next steps, select React Native / Expo. You’ll then see the ID, copy it somewhere secure. Click Done and you’ve successfully configured OnSignal iOS configuration.

Next, we’ll do an iOS app configuration to enable Push Notification capability in our app. I’ve “Automatically manage signing” in Xcode enabled so I won’t be creating an identifier manually.

Click on the + Capability button in the above picture. Search Push Notifications and double-click on it to add it.

Click on +Capability again and this time search for Background Modes and check the Remote notifications option.

Next, we need to add OneSignalNotificationServiceExtension allows your application to receive rich notifications with images and/or buttons, and to report analytics about which notifications users receive.

From the XCode, menu select File → New → Target and select Notification Service Extension

Add product name as OneSignalNotificationServiceExtension and add the rest of the information. In Project select the project and not pods and click on finish.

Click on CANCEL if you are prompted with a popup.

Make sure the iOS version selected is 10.0.

Open your Podfile and add this target:

target 'OneSignalNotificationServiceExtension' do
pod 'OneSignal', '>= 3.0', '< 4.0'
end

Next from the terminal run cd ios && pod install && cd ..

Open your iOS project again and this time you’ll have a folder named as OneSignalNotificationServiceExtension. Expand it and open the NotificationService.swift add the bold code from below in it:

import UserNotificationsimport OneSignalclass NotificationService: UNNotificationServiceExtension {var contentHandler: ((UNNotificationContent) -> Void)?var receivedRequest: UNNotificationRequest!var bestAttemptContent: UNMutableNotificationContent?override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {self.receivedRequest = requestself.contentHandler = contentHandlerbestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)if let bestAttemptContent = bestAttemptContent {OneSignal.didReceiveNotificationExtensionRequest(self.receivedRequest, with: bestAttemptContent, withContentHandler: self.contentHandler)}}override func serviceExtensionTimeWillExpire() {if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {OneSignal.serviceExtensionTimeWillExpireRequest(self.receivedRequest, with: self.bestAttemptContent)contentHandler(bestAttemptContent)}}}

Next, we need to implement App Group. It’ll help us to have confirmed deliveries, increment/decrement badges, and much more.

In your main app target click on + Capability and search and Add Groups. Click on the + button group.YOUR_BUNDLE_IDENTIFIER.onesignal where YOUR_BUNDLE_IDENTIFIER is the same as shown in "Bundle Identifier" then press OK.

Next, repeat the same process for the OneSignalNotificat... target:

That’s all there is to the iOS setup.

Android Setup

Next, we’ll configure it for Android. Select Google Android, from the OneSignal Settings → Platforms.

You’ll need to have an Android 4.0.3+ device or emulator with “Google Play store (Services) installed. It’ll also require a Server Key and a Sender ID which we’ll create next.

Create a Firebase project if you haven’t already and configure it for android. I have already done that so I’m going to go into Project Settings on firebase and select Cloud Messaging from the tab. Here you’ll see Server Key and Sender ID. Copy that and paste it on OneSignal

Select the React Native / Expo again and finish the setup.

Next open app/build.gradle and add the following code at top of that file:

buildscript {repositories {gradlePluginPortal()}dependencies {classpath 'gradle.plugin.com.onesignal:onesignal-gradle-plugin:[0.12.10, 0.99.99]'}}apply plugin: 'com.onesignal.androidsdk.onesignal-gradle-plugin'

That's it for android.

Huawei Setup (Optional)

If you have a version of your app on Huawei AppGallery the firebase is not going to work so it’ll require its certificate and here we’ll see how. You can skip this if you don’t have the app on Huawei AppGallery.

Select Huawei Android from OneSignal Settings → Platforms. It’ll require a package name, App ID, and client secret.

Login to your Huawei Developer Account. In the AppGallery Connect console select My Projects and select Manage APIs next to the General Information tab and search or push kit. Turn the Push Kit button on.

Head back to AppGallery Connect main panel and select My Apps. Select your app and you’ll find the Package name, App ID, and App Secret.

Copy these in your OneSignal HMS configuration and click next. Select React Native / Expo again and finish the setup.

Open android/build.gradle file and add these:

allprojects {
repositories {
google()
jcenter()
maven {url 'https://developer.huawei.com/repo/'}
...
}
}
buildscript {
repositories {
google()
jcenter()
maven {url 'https://developer.huawei.com/repo/'}
...
}
}
buildscript {
dependencies {
...
classpath 'com.huawei.agconnect:agcp:1.3.1.300'
...
}
}

Now open android/app/build.gradle and make the following changes:

apply plugin: "com.huawei.agconnect"...
dependencies {
// Retain other existing dependencies.
implementation 'com.huawei.hms:push:5.3.0.304'
}

The 5.3.0.304 in the above code is the version and I have found it while following this documentation (Search for com.huawei.hms:push and you’ll find the latest version number and I’m sure it’ll implement the latest one for you.)

Open gradle.properties file and add this:

manifestmerger.enabled=true

You can follow this link: https://developer.huawei.com/consumer/en/doc/development/HMS-Guides/Preparations#h2-1584707362385 for more information about configuring for Huawei.

React Native Implementation

We have installed the react-native package at the start and have configured the app for iOS, Android, and Huawei.

In your App.js or index.js (I’m doing it in App.js) we’ll initialize OneSignal and handle the functions of what to do when a notification is received.

// REMOTE NOTIFICATIONS SETUP START //OneSignal.setLogLevel(6, 0);OneSignal.setAppId(YOUR_OneSignal_App_ID);//Prompt for push on iOSOneSignal.promptForPushNotificationsWithUserResponse((response) => {console.log("Prompt response #334: ", response);})//Method for handling notifications recieved while app in foregroundOneSignal.setNotificationWillShowInForegroundHandler((notificationReceivedEvent) => {console.log("One Signal: notiication will show in foreground: ", notificationReceivedEvent);let notification = notificationReceivedEvent.getNotification();console.log("notification: ", notification);const data = notification.additionalDataconsole.log("additionalData: ", data);//Complete with null means don't show a notificationnotificationReceivedEvent.complete(notification);});//Method for handling notifications openedOneSignal.setNotificationOpenedHandler((notification) => {console.log("OneSignal: notification opened: ", notification);})// REMOTE NOTIFICATIONS SETUP END //

This code will handle everything. Make sure you change the setAppID top of our own One signal app ID.

All the settings you have done, from asking permissions to everything else will be handled in this small piece of code. The first method that is promptForPushNotificationsWithUserResponse will only run in the case of iOS. The rest of the methods will be used by all the platforms depending on what is the state of the app. You’ll see how each method works when you test it.

Testing

Now, the moment of truth. Let’s test it on android first and android phones will automatically subscribe users to receive push notifications whereas in iOS it’ll ask for permission first.

Before running let's clean the build folder so do a cd android && ./gradlew clean and finally, do cd .. and then run the following command:

npx react-native run-android

Head over to your OneSignal dashboard and select Audience → All Users and you’ll see one user already registered and it’s because you have run the app on Android.

Now to send a message go to Messages and click on New Push

Fill in only the Title and Message for now (Or not add other things like an image etc). You can learn more about what is required for which platform like Subtitle only works on iOS etc.

Leave all the changes as default and click on Review and Send. In the preview window click on Send Message to send a message.

You’ll see it appearing on the android, iOS, and Huawei apps. You can also see terminal logs as the data is being received.

iOS notifications will work on physical devices only so run your app

nopx react-native run-ios --device "YOUR_DEVICE_NAME"

As soon as the app loads it’ll ask for permissions to show notifications click Allow on that. Then send a notification and you should receive it.

You can test in advance settings and other options provided by OneSignal.

I haven’t performed the tests for Huawei will update this as I do.

Bonus: How to open the notification and navigate to a screen or in-app web view browser

When you have implemented the notification the next thing is to set it up so that when the user opens it they should land on a screen that is related to the notification.

Firstly, when you are creating a new push don’t add the URL in the Launch URL. Just add a Title and Message.

Scroll down a bit and expand Advanced Settings and scroll down to Additional Data and click on Add Field.

Add urlToOpen and then in the second field add any URL.

Don’t press the Review & Send button just yet. I want to show how I have handled the urlToOpen in my code. You can get the idea and implement it accordingly.

I’ve handled this on my Home screen of the app. It’s not the best way but it works just fine. In App.js it’s really hard to get references to navigation. So, in my TabBar.Navigator I have the HomeScreen as Tab.Screen first screen. So, I know it’s the first screen that is going to get initiated so I’ll move the notifications code to this screen as it'll have the navigation initiated. So in my HomeScreen I’ll put this code open without any useEffect:

// REMOTE NOTIFICATIONS SETUP START ////1OneSignal.setLogLevel(6, 0);OneSignal.setAppId(NOTIFICATION_KEYS.OneSignal_App_ID);//2//Prompt for push on iOSOneSignal.promptForPushNotificationsWithUserResponse((response) => {console.log("Prompt response #334: ", response);})
//3
//Method for handling notifications recieved while app in foregroundOneSignal.setNotificationWillShowInForegroundHandler((notificationReceivedEvent) => {let notification = notificationReceivedEvent.getNotification();Alert.alert(notification.title, notification.body, [{text: "OK", onPress: () => {if (notification.additionalData.urlToOpen != null) {navigation.navigate('Web Viewer', { urlToOpen: notification.additionalData.urlToOpen, title: notification.title })}}, style: "default"}]);// const data = notification.additionalData// console.log("additionalData: ", data);//Complete with null means don't show a notificationnotificationReceivedEvent.complete(notification);});// 4//Method for handling notifications openedOneSignal.setNotificationOpenedHandler((openedEvent) => {const { action, notification } = openedEvent;//If action is 0 that means Notification was clicked//If action is 1 that means button in the notification was clickedif (notification.additionalData.urlToOpen != null) {navigation.navigate('Web Viewer', { urlToOpen: notification.additionalData.urlToOpen, title: notification.title })}})// REMOTE NOTIFICATIONS SETUP END //
  1. We have initialized the one signal notifications.
  2. I haven’t configured the app for iOS so I don’t need this method.
  3. If the app is opened and use is using it then this method will be triggered and the user will get an Alert and upon pressing its OK button user will be navigated to 'Web Viewer' a component that I wrote to open URLs inside the app. I pass it the URL I have inside the additionalData in which I have urlToOpen which we set earlier when we were making the push notification.
  4. This method will be called when the user will open the notification and the app will open either from background state to active state or from a closed state to active state. And upon opening, I am navigating it to the same 'Web Viewer' screen with urlToOpen in additionalData.

If you implement iOS/Android Action Button you can also detect what the user has selected and make our app act accordingly.

As I’ll test for iOS later, I’ll update this article. But everything is set up and it should also work fine.

Time to test. Go to OneSignal Dashboard and click Review and Send.

The notification came and the back button will go back to the home screen when pressed.

The same code will work for iOS so you can test that too.

As always if you find this helpful share and press the 👏🏻 button so that others can find it too. If you see a typo feel free to highlight it or if you’re stuck drop a comment and I’ll try my best to help you.

All my tutorials are free but if you feel like supporting you can buymeacoffee.com/chaudhrytalha

Happy Coding 👨🏻‍💻

--

--