React Native OneSignal
React Native Push Notifications support with OneSignal integration.
Installation
npm install react-native-onesignal
Android Installation
In your AndroidManifest.xml
.....
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<application ....>
<activity
android:launchMode="singleTop">
.....
In android/gradle/wrapper/gradle-wrapper.properties
...
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https:
```
In `android/settings.gradle`
```gradle
...
include ':react-native-onesignal'
project(':react-native-onesignal').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-onesignal/android')
```
In `android/build.gradle`
```gradle
...
dependencies {
classpath 'com.android.tools.build:gradle:2.1.0'
}
```
In `android/app/build.gradle`
```gradle
...
android {
...
buildToolsVersion "23.0.2"
...
defaultConfig {
...
manifestPlaceholders = [manifestApplicationId: "${applicationId}",
onesignal_app_id: "YOUR_ONESIGNAL_ID",
onesignal_google_project_number: "YOUR_GOOGLE_PROJECT_NUMBER"]
}
}
dependencies {
...
compile project(':react-native-onesignal')
}
```
### RN < 0.29
Register module (in `MainActivity.java`)
```java
import com.geektime.reactnativeonesignal.ReactNativeOneSignalPackage;
public class MainActivity extends ReactActivity {
......
@Override
protected List<ReactPackage> getPackages() {
...
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new ReactNativeOneSignalPackage()
);
}
......
}
```
### RN >= 0.29
In RN 0.29 FB changed the way RN libraries should be included in Android, and listen to application life cycle.
Register module (in `MainApplication.java`)
```java
import com.geektime.reactnativeonesignal.ReactNativeOneSignalPackage;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
......
@Override
protected List<ReactPackage> getPackages() {
...
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new ReactNativeOneSignalPackage()
);
}
};
......
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
};
```
## iOS Installation
* Follow the steps according to the official OneSignal SDK Installation here: https://documentation.onesignal.com/docs/installing-the-onesignal-ios-sdk
* Make sure you installed the OneSignal Pod.
* Once you've finished, Open your project in Xcode.
### Importing The Library
* Drag the file `RCTOneSignal.xcodeproj` from `/node_modules/react-native-onesignal/ios` into the `Libraries` group in the Project navigator. Ensure that `Copy items if needed` is UNCHECKED!
![Add Files To...](http://i.imgur.com/puxHiIg.png)
![Library Imported Successfuly](http://i.imgur.com/YJPQLPD.png)
* Ensure that `libRTCOneSignal.a` is linked through `Link Binary With Libraries` on `Build Phases`:
![Add Files To...](http://i.imgur.com/IxIQ4s8.png)
* Ensure that `Header Search Paths` on `Build Settings` has the path `$(SRCROOT)/../node_modules/react-native-onesignal` set to `recursive`:
### Adding the Code
* When you reach `AppDelegate.m` instructions on the OneSignal documentation, stop and enter this following code snippets instead:
* Import `RCTOneSignal.h`:
```objc
#import "RCTOneSignal.h"
```
* Synthesize `oneSignal` after `@implementation AppDelegate`
```objc
@synthesize oneSignal = _oneSignal;
```
* On the `application didFinishLaunchingWithOptions` method, insert the following code (replace YOUR_ONESIGNAL_APP_ID with your OneSignal app ID):
```objc
self.oneSignal = [[RCTOneSignal alloc] initWithLaunchOptions:launchOptions
appId:@"YOUR_ONESIGNAL_APP_ID"];
```
* After `application ` insert the code for the notification event:
```objc
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification {
[RCTOneSignal didReceiveRemoteNotification:notification];
}
```
* on `AppDelegate.h`:
* Import `RCTOneSignal.h`:
```objc
#import <RCTOneSignal.h>
```
* Declare the `RCTOneSignal` property:
```objc
@property (strong, nonatomic) RCTOneSignal* oneSignal;
```
* You're All Set!
## Android Usage
In your `index.android.js`:
```javascript
import OneSignal from 'react-native-onesignal';
OneSignal.configure({
onIdsAvailable: function(device) {
console.log('UserId = ', device.userId);
console.log('PushToken = ', device.pushToken);
},
onNotificationOpened: function(message, data, isActive) {
console.log('MESSAGE: ', message);
console.log('DATA: ', data);
console.log('ISACTIVE: ', isActive);
}
});
```
## iOS Usage
In iOS, we have to wait a little bit before fetching the notification. The reason is that notification is coming too fast, before the main view of the app is being rendered.
Therefore, the notification could get lost. We solve it in an ugly way, but working one.
In your `index.ios.js`:
```javascript
import OneSignal from 'react-native-onesignal';
var pendingNotifications = [];
OneSignal.configure({
onIdsAvailable: function(device) {
console.log('UserId = ', device.userId);
console.log('PushToken = ', device.pushToken);
},
onNotificationOpened: function(message, data, isActive) {
var notification = {message: message, data: data, isActive: isActive};
console.log('NOTIFICATION OPENED: ', notification);
pendingNotifications.push(notification);
handleNotification(notification);
}
});
```
## API
### Handling Notifications
When any notification is opened or received the callback `onNotification` is called passing an object with the notification data.
Notification object example:
```javascript
{
isActive: false,
message: 'My Notification Message',
data: {},
}
```
### Sending and Getting OneSignal Tags
We exposed the tags API of OneSignal (currently on Android) in order to segment people in a better way.
````javascript
// Sending the tags for the device
OneSignal.sendTags(missingTags);
//Getting the tags from the server and use the received object
OneSignal.getTags((receivedTags) => {
console.log(receivedTags);
});
//Delete a tag
OneSignal.deleteTag(tag);
Getting Player ID and Push Token
We exposed the idsAvailable API of OneSignal (both Android & iOS) as an event.
Just define a onIdsAvailable callback in the configure options.
OneSignal.configure({
onIdsAvailable: function(device) {
console.log('UserId = ', device.userId);
console.log('PushToken = ', device.pushToken);
}
});
Enable Vibration
We exposed the enableVibrate API of OneSignal (Android only).
You can call this from your UI from a button press for example to give your user's options for your notifications. By default OneSignal always vibrates the device when a notification is displayed unless the device is in a total silent mode. Passing false means that the device will only vibrate lightly when the device is in it's vibrate only mode.
OneSignal.enableVibrate(true);
Enable Sound
We exposed the enableSound API of OneSignal (Android only).
You can call this from your UI from a button press for example to give your user's options for your notifications. By default OneSignal plays the system's default notification sound when the device's notification system volume is turned on. Passing false means that the device will only vibrate unless the device is set to a total silent mode.
OneSignal.enableSound(true);
Enable Notification When App Active
We exposed the enableNotificationsWhenActive API of OneSignal (Android only).
By default this is false and notifications will not be shown when the user is in your app, instead the NotificationOpenedHandler is fired. If set to true notifications will always show in the notification area and NotificationOpenedHandler will not fire until the user taps on the notification.
OneSignal.enableNotificationsWhenActive(true);
Enable In-App Alert Notification
We exposed the enableInAppAlertNotification API of OneSignal (both Android & iOS).
By default this is false and notifications will not be shown when the user is in your app, instead the OneSignalHandleNotificationBlock is fired. If set to true notifications will be shown as native alert boxes if a notification is received when the user is in your app. The OneSignalHandleNotificationBlock is then fired after the alert box is closed.
OneSignal.enableInAppAlertNotification(true);
Change User Subscription Status
We exposed the setSubscription API of OneSignal (both Android & iOS).
You can call this method with false to opt users out of receiving all notifications through OneSignal. You can pass true later to opt users back into notifications
OneSignal.setSubscription(true);
Post Notification (Peer-to-Peer Notifications)
We exposed the postNotification API of OneSignal, currently supports one Player ID to send a notification to.
We call it internally P2P Notification, and therefore there is a special attribute to listen to while receiving the notification.
Allows you to send notifications from user to user or schedule ones in the future to be delivered to the current device.
OneSignal.postNotification(contents, data, player_id);
onNotificationOpened: function(message, data, isActive) {
if (data.p2p_notification) {
for (var num in data.p2p_notification) {
}
}
}
Prompt Location (Android Only)
We exposed the promptLocation API of OneSignal (currently supported only on Android).
Prompts the user for location permissions. This allows for geotagging so you can send notifications to users based on location.
Note: Make sure you also have the required location permission in your AndroidManifest.xml.
OneSignal.promptLocation();
Clear Notifications (Android Only)
We exposed the clearOneSignalNotifications API of OneSignal (currently supported only on Android).
Removes all OneSignal notifications from the Notification Shade.
OneSignal.clearOneSignalNotifications();
Cancel Notifications (Android Only)
We exposed the cancelNotification API of OneSignal (currently supported only on Android).
Cancels a single OneSignal notification based on its Android notification integer id. You can get the notification Id when invoking OneSignal.onNotificationOpened while receiving a notification.
OneSignal.cancelNotification(id);
Check Push Notification Permissions (iOS Only)
See what push permissions are currently enabled. callback will be invoked with a permissions object (currently supported only on iOS).
OneSignal.checkPermissions((permissions) => {
console.log(permissions);
});
Request Push Notification Permissions (iOS Only)
We exposed the requestPermissions method (currently supported only on iOS).
permissions = {
alert: true,
badge: true,
sound: true
};
OneSignal.requestPermissions(permissions);
Register For Push Notifications (iOS Only)
We exposed the registerForPushNotifications API of OneSignal (currently supported only on iOS).
Call when you want to prompt the user to accept push notifications. Only call once and only if you passed false to initWithLaunchOptions autoRegister:.
OneSignal.registerForPushNotifications();
The following example is from our own App and needs to be customized in order to work.
Example:
_syncOneSignal = () => {
var allTags = {};
var missingTags = {};
OneSignal.getTags((receivedTags) => {
for (var i = this.categories.length * 1; i >= 0; i--) {
var category = this.categories[i];
if (!(category.slug in receivedTags)) {
missingTags[category.slug] = category.is_push_default;
}
allTags[category.slug] = category.is_push_default;
};
if (Object.keys(missingTags).length > 0) {
OneSignal.sendTags(missingTags);
}
Object.keys(receivedTags).forEach(function(key,index) {
if (!(key in allTags)) {
OneSignal.deleteTag(key);
}
});
});
};
FAQ / Repeating Issues
The following issues has been marked as repeating, therefore we decided to devote them a separate section.
Issue 1 - Multiple dex files define:
> com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.dex.DexException: Multiple dex files define Lcom/google/android/gms/internal/zzr;
Solution: Update all your Google Play Services dependencies to the latest version rather than to a specific version.
From the Google Play Services documentation:
Be sure you update this version number each time Google Play services is updated https://developers.google.com/android/guides/setup#add_google_play_services_to_your_project
In android/app/build.gradle
...
dependencies {
...
compile "com.google.android.gms:play-services-base:+"
compile "com.google.android.gms:play-services-location:+"
complie "com.google.android.gms:play-services-ads:+"
}
Issue 2 - Multiple dex files define (Again):
:app:dexRelease
Unknown source file : UNEXPECTED TOP-LEVEL EXCEPTION:
Unknown source file : com.android.dex.DexException: Multiple dex files define Landroid/support/v7/appcompat/R$anim;````
Solution: Upgrade your gradle to properly handle the dex tasks:
In android/build.gradle
...
dependencies {
classpath 'com.android.tools.build:gradle:2.1.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
In android/gradle/wrapper/gradle-wrapper.properties
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https:
Issue 3 - symbol(s) not found for architecture x86_64 and/or OneSignal/OneSignal.h file not found
Solution: Go to your Podfile file, located within the ios folder on the root of your project.
Add the line pod 'OneSignal' as follows:
target 'YourApp' do
...
pod 'OneSignal'
end
target 'YourAppTests' do
end
Then head to the terminal, ls to the ios folder on the root of your project, then type pod install
to install the pods. After that, make sure to drag OneSignal.framework
from your Pods project on Xcode to the Frameworks folder on your Xcode workspace. Make sure that your Link Binary With Libraries
on the Build Phases
section of your target contains the Onesignal.framework
file as follows.
CREDITS
Thanks for all the awesome fellows that contributed to this repository!
@danpe, @lunchieapp, @gaykov, @williamrijksen, @adrienbrault, @kennym, @dunghuynh, @holmesal, @joshuapinter
TODO