Updated October 27, 2016

React Native Push Notifications with OneSignal

Originally publish on medium.com.

0

Last updated April 18, 2018.

I had initially planned to make a comprehensive multi-part video series on setting up remote push notifications but, unfortunately, I underestimated the time it would take for me to recover from getting my wisdom teeth removed.

But that’s no excuse. Here’s a tutorial on how to set up push notifications in React Native (both iOS and Android) with OneSignal, a service that provides free push notification delivery for multiple platforms. This is a pretty long tutorial but it’s worth it. Even if you don’t use OneSignal, much of this will apply to you (general configuration). Let’s get to it.

Create React Native App

First thing you’ll need is a React Native app. Maybe that’s your existing app or maybe it’s a new one. We’ll start with a new one. From the command line:

react-native init OneSignalExample

Something to note going forward: push notifications only work on a real device, they won’t work on a simulator. I use an unlocked refurbished Nexus 5 and an iPhone 6 for testing.

You can access instructions for running on your device at the following links.

Create OneSignal Account & Create App

Next you’ll want to head over to OneSignal and sign up for an account. At that point you’ll be prompted to set up your app.

1

Now we’ll be asked to configure a platform. This is going to be the most complex part. I’m going to start off with iOS and configure Android later — details on how to do that outlined below.

2

Generate iOS Push Certificate

So you’re probably sitting at a screen that looks a lot like this…

3

You may be wanting to jump right into creating your .p12 file (we’ll cover that in a moment) but we’ve got to actually create our app within the Apple Developer portal.

Now if you’ve never done this before it’s important to note that you’ll need to set an Explicit App ID for push notifications to work.

4

You’re also going to want to enable push notifications for this app.

5

Now that we’re done with that we can move over to actually creating the provisioning profile. OneSignal has a tool called The Provisionator that will help with this process.

If you’re uncomfortable using giving this tool access to your Apple account you can create the profile manually.

Protip: If you’ve got two-factor authentication turned on for your account you’ll need to turn it off in order to use The Provisionator. Feel free to change your password before/after using it — that’s what I did to aid in keeping my account secure.

Okay, now that we’re past those notes let’s actually use this tool and get our profile.

You’ll want to sign into your account and make sure you choose the proper team.

6

Upon pressing “Next”, and waiting a few seconds, you’ll see something like this

7

Go ahead and download those files and remember the password for the p12 file. Then we can head back to OneSignal and upload our file…

8

And that’s it, for now! We’ll just close out this modal and come back to the React Native side of things in a moment. Now let’s configure Android (it’s easier, I promise).

Generate Google Server API Key

To set up OneSignal with Google we need to go to our App Settings (within OneSignal) and click “Configure” for Android.

9

We then see that we’ll need a Google Server API Key and a Google Project Number. Let’s get both of those…

10

You’ll need to go to the Google Services Wizard to do this — the names aren’t important. Just choose things that make sense OR if you’re setting this up with an existing app, make sure you choose the right app.

11

I like to keep things consistent between iOS and Android

Then enable Cloud Messaging

12

Once enabled you’ll have access to your API key and your project ID (called Sender ID). Bring these over to OneSignal.

13

Woohoo! Platforms are set up. Now we can actually work on integrating this with our app.

Quick break: If, as you’re working to set up push notifications, you’re wondering how you’re actually going to use them then I want to share a quick 9 minute video describing some must-follow practices when using push notifications in your React Native app. It’ll really help you (and your users) out!

Install react-native-onesignal

OneSignal has a package on npm, react-native-onesignal, that makes integrating with your platform super easy. It’s not the easiest to install but once it’s done you don’t have to do it again :) I’m hoping in the future that they integrate with rnpm/react-native link so that we can minimize diving into native code but until then we must. For now, from your project root, run the following to install the package.

npm install react-native-onesignal --save

Thanks to react-native link configuring this package is a breeze.

Once installed all you have to run is react-native link react-native-onesignal and the package will be installed!

Configure iOS

I’m basically just rehashing the official docs. If you want to ensure you’ve got the most up to date information, check out the docs.

Now let’s configure our capabilities within Xcode

14

Next, jump over to the Build Settings tab and search for “Header Search Paths”, double click the value, then click the “+” sign. Then add $(SRCROOT)/../node_modules/react-native-onesignal/ios and set it to “recursive” (this step may be done already).

15

Then onto AppDelegate.m.

Synthesize oneSignal after @implementation AppDelegate.

AppDelegate.m

#import "AppDelegate.h"

#import "RCTBundleURLProvider.h"
#import "RCTRootView.h"

@implementation AppDelegate
@synthesize oneSignal = _oneSignal;

// ...

Still in your AppDelegate.m you need to setup OneSignal, that’s the first section of code I added below. Make sure to swap “YOUR_ONESIGNAL_APP_ID” with the right ID. The last part is so that you can receive notifications.

AppDelegate.m

// ...

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  NSURL *jsCodeLocation;

  self.oneSignal = [[RCTOneSignal alloc] initWithLaunchOptions:launchOptions
                                                       appId:@"YOUR_ONESIGNAL_APP_ID"];

  // ...
}

You can find your OneSignal App ID via App Settings > Keys & IDs

16

Jump over to AppDelegate.h and add #import <RCTOneSignal.h> and @property (strong, nonatomic) RCTOneSignal* oneSignal;

AppDelegate.h

/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

#import <UIKit/UIKit.h>
#import <RCTOneSignal.h> /* <--- Add this */

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (nonatomic, strong) UIWindow *window;
@property (strong, nonatomic) RCTOneSignal* oneSignal; /* <--- Add this */

@end

Now we’ll want to try and get this to run. You might have to do a few more things here.

Make sure to set your Bundle Identifier to the one you set up when you made the app.

17

Then we need to make sure we create a provisioning profile that will work with the push certificate we set up earlier. You’ll likely need to create an AdHoc one if you’ve been following these instructions exactly.

18

Then choose the correct app.

19

Then choose your certificate and the devices that should be included for the AdHoc distribution. If you need to add devices you can do so on the Apple dev portal. Need to find out your UDID? Use this resource.

Then create your profile and download it. Once it’s downloaded. Double click it so that it’s installed.

20

Then in Xcode you’ll want to choose that profile in the Provisioning Profile section.

21

Okay… now… try to compile it. Cross your fingers. If it worked, congrats!

If not make sure you followed all the steps above. Now for Android.

Configure Android

I’m basically just rehashing the official docs. If you want to ensure you’ve got the most up to date information, check out the docs.

First we need to add some necessary permissions to AndroidManifest.xml, which can be found at android/app/src/main/AndroidManifest.xml.

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.onesignalexample"
    android:versionCode="1"
    android:versionName="1.0">

    ...
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <!-- ADD THIS -->

    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="22" />

    <application
      ...
    >
        <activity
          ...
          android:launchMode="singleTop" <!-- ADD THIS -->
        >
          ...
        </activity>
      ...
    </application>

</manifest>

Access the full file.

We need to tell OneSignal about our app information. Make sure to use your own values for this. In android/app/build.gradle add our keys (see code snippet), and add the package as a dependency of our Android app.

build.gradle

android {
    ...
    defaultConfig {
        ...
       manifestPlaceholders = [onesignal_app_id: "YOUR_ONESIGNAL_ID",
                                onesignal_google_project_number: "REMOTE"]
    }
}

Remember, you want to change YOUR_ONESIGNAL_ID (same one used for iOS).

Go ahead and make sure your app compiles, I’ll wait.

Good? Good. Great! Let’s use these fancy remote notifications now.

Android Usage & iOS Usage

First thing we want to do is create a new App.js file in the root of our project — this way we can write the same code for both iOS and Android. Go ahead and copy and paste the following.

App.js

import React, { Component } from 'react';
import { StyleSheet, Text, View, Platform } from 'react-native';

class App extends Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>Welcome to the OneSignal Example!</Text>
        <Text style={styles.instructions}>Using {Platform.OS}? Cool.</Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

export default App;

And then change both index.ios.js and index.android.js to the following (so we use the App file we just made).

index.*.js

import { AppRegistry } from 'react-native';
import App from './App';

AppRegistry.registerComponent('OneSignalExample', () => App);

We can then go ahead and refresh or start our app on both iOS and Android. If everything worked as expected you should see something like this on your OneSignal dashboard.

24

Remember, you need a real device to test this.

Go ahead and lock the device and jump over to OneSignal’s dashboard and send a message.

25

I won’t go over all the options available to you through OneSignal (right now) but there is quite a lot you can do through the dashboard. You can also interact with the service via their REST API so you can programmatically send notifications. Anyways, if everything worked out correctly you should have gotten notifications on your device!

26

Now that’s pretty basic and you can do a lot more with OneSignal and push notifications in general, some of which I’ll cover below.

[iOS] Request notification permission only when needed

One pattern that is encouraged by Apple (I can’t find the docs stating this but they do exist) is to request permission to send push notifications when it’s needed. So, rather than requesting permission as soon as the app boots (the default) you wait until the user takes some action so that they would understand why you’re requesting permission. This builds confidence with your user so let’s set that up.

First thing we have to do is disable auto registration, which we’ll do in the AppDelegate.m file. Remember that self.oneSignal from earlier? We’ll be touching that again.

AppDelegate.m

self.oneSignal = [[RCTOneSignal alloc] initWithLaunchOptions:launchOptions
                                        appId:@"YOUR_ONESIGNAL_APP_ID"
                                        settings:@{kOSSettingsKeyAutoPrompt: @false}]; // added this

So once we do that it won’t ask permission — we have to do that manually. OneSignal makes that easy for us. Over in the App.js file we’ll add a button (only on iOS) to request permission. We’re going to use the registerForPushNotifications function to do so. After requesting permission it will do everything necessary to register the device with OneSignal.

App.js

render() {
    return (
      <View style={styles.container}>
        ...
        {Platform.OS === 'ios' ?
          <TouchableOpacity
            onPress={() => OneSignal.registerForPushNotifications()}
            style={{ padding: 20, backgroundColor: '#3B5998' }}
          >
            <Text style={{ color: '#fff' }}>Request Push Notification Permission</Text>
          </TouchableOpacity>
        : null}
      </View>
    );
  }

Full file.

If you previously ran the app on your phone you may have to delete it and reinstall so that you’re prompted to enable notifications again.


Want to see more on Push Notifications via OneSignal? Let me know by responding to and recommending this article. I would really appreciate it! Feel free to ask questions below — this can be tricky.

Full source is on GitHub.

Some of the links in the post are affiliate links and I may earn a small commission if you buy something from them.

React Native School Logo

React Native School

Want to further level up as a React Native developer? Join React Native School! You'll get access to all of our courses and our private Slack community.

Learn More