README.md 5.88 KB
Newer Older
Libin Lu's avatar
init  
Libin Lu committed
1 2 3 4 5
## Installation

- Run `npm install react-native-fcm --save`
- Run rnpm link

Libin Lu's avatar
Libin Lu committed
6
### Android Configuration
Libin Lu's avatar
init  
Libin Lu committed
7 8 9 10

- In `android/build.gradle`
```gradle
dependencies {
Libin Lu's avatar
Libin Lu committed
11 12
classpath 'com.android.tools.build:gradle:2.0.0'
classpath 'com.google.gms:google-services:3.0.0' // <- Add this line
Libin Lu's avatar
init  
Libin Lu committed
13 14 15 16 17 18 19 20 21
```

- In `android/app/build.gradle`
```gradle
apply plugin: "com.android.application"
apply plugin: 'com.google.gms.google-services' // <- Add this line
...
```

Libin Lu's avatar
Libin Lu committed
22
- In `android/app/src/main/AndroidManifest.xml`
Libin Lu's avatar
init  
Libin Lu committed
23 24 25

```
<application
Libin Lu's avatar
Libin Lu committed
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
android:theme="@style/AppTheme">

...
<service android:name="com.evollu.react.fcm.MessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>

<service android:name="com.evollu.react.fcm.InstanceIdService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
...
Libin Lu's avatar
init  
Libin Lu committed
41 42 43 44 45 46 47 48
```

### IOS Configuration

install pod 'Firebase/Messaging'

in AppDelegate.m add
```
Libin Lu's avatar
Libin Lu committed
49
#import "RNFIRMessaging.h"
Libin Lu's avatar
Libin Lu committed
50
...
Libin Lu's avatar
init  
Libin Lu committed
51

Libin Lu's avatar
Libin Lu committed
52 53 54 55 56
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
....
[FIRApp configure]; <-- add this line
}
Libin Lu's avatar
init  
Libin Lu committed
57

Libin Lu's avatar
Libin Lu committed
58
//add this
Libin Lu's avatar
init  
Libin Lu committed
59
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification {
Libin Lu's avatar
Libin Lu committed
60 61 62
[[NSNotificationCenter defaultCenter] postNotificationName: FCMNotificationReceived
object:self
userInfo:notification];
Libin Lu's avatar
init  
Libin Lu committed
63 64 65

}

Libin Lu's avatar
Libin Lu committed
66
//add this
Libin Lu's avatar
init  
Libin Lu committed
67
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler {
Libin Lu's avatar
Libin Lu committed
68 69 70 71
[[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived
object:self
userInfo:notification];
handler(UIBackgroundFetchResultNoData);
Libin Lu's avatar
init  
Libin Lu committed
72 73 74 75 76 77 78
}
```


### FCM config file
In [firebase console](https://console.firebase.google.com/), you can get `google-services.json` file and place it in `android/app` directory and get `googleServices-info.plist` file and place it in `/ios` directory

Libin Lu's avatar
Libin Lu committed
79
## Usage
Libin Lu's avatar
init  
Libin Lu committed
80 81 82 83 84 85

```javascript

var FCM = require('react-native-fcm');

componentWillMount() {
Libin Lu's avatar
Libin Lu committed
86 87 88 89 90 91 92 93 94 95
FCM.requestPermissions();
FCM.getFCMToken().then(token => {
//store fcm token in your server
});
this.fcmNotifLsnr = DeviceEventEmitter.addListener('FCMNotificationReceived', (notif) => {
//there are two parts of notif. notif.notification contains the notification payload, notif.data contains data payload
});
this.fcmTokenLsnr = DeviceEventEmitter.addListener('FCMTokenRefreshed', (token) => {
//fcm token may not be available on first load, catch it here
});
Libin Lu's avatar
init  
Libin Lu committed
96 97 98
}

componentWillUnmount() {
Libin Lu's avatar
Libin Lu committed
99 100 101
//prevent leak
this.fcmNotifLsnr.remove();
this.fcmTokenLsnr.remove();
Libin Lu's avatar
init  
Libin Lu committed
102 103 104 105 106
}

}
```

Libin Lu's avatar
Libin Lu committed
107
### Response to `click_action` in Android
Libin Lu's avatar
Libin Lu committed
108
To allow android to respond to `click_action`, you need to define Activities and filter on specific intent. Since everything is running in MainActivity, you can have MainActivity to handle actions.
Libin Lu's avatar
Libin Lu committed
109 110 111 112 113 114 115 116 117 118 119
```xml
<activity
  android:name=".MainActivity"
  android:label="@string/app_name"
  android:windowSoftInputMode="adjustResize"
  android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
  <intent-filter>
      <action android:name="android.intent.action.MAIN" />
      <category android:name="android.intent.category.LAUNCHER" />
  </intent-filter>
    <intent-filter>                                                       <--add this line
Libin Lu's avatar
Libin Lu committed
120
        <action android:name="fcm.ACTION.HELLO" />                        <--add this line, name should match click_action
Libin Lu's avatar
Libin Lu committed
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
        <category android:name="android.intent.category.DEFAULT" />       <--add this line
    </intent-filter>                                                      <--add this line
</activity>
```
and pass intent into package, change MainActivity.java
```java
new FIRMessagingPackage(getIntent()),                                     <--add getIntent()
```

### Behaviour when sending `click_action` and `data` in notification
- When app is not running when user clicks notification, notification data will be passed into 
 - `FCM.initialAction`(contains `click_action` in notification payload
 - `FCM.initialData` (contains `data` payload if you send together with notification)

- When app is running in background
 - IOS will receive notificaton from `FCMNotificationReceived` event
 - Android will reload the whole react app
138

Libin Lu's avatar
Libin Lu committed
139 140
- When app is running in foreground
 - Both will receive notificaton from `FCMNotificationReceived` event
141

Libin Lu's avatar
Libin Lu committed
142
NOTE: it is recommend not to reply on extra data for click_action as it can be overwritten. check [this](http://stackoverflow.com/questions/33738848/handle-multiple-notifications-with-gcm)
143

Libin Lu's avatar
init  
Libin Lu committed
144
## Q & A
Libin Lu's avatar
Libin Lu committed
145
#### My android build is failing
Libin Lu's avatar
Libin Lu committed
146
Try update your SDK and google play service
Libin Lu's avatar
Libin Lu committed
147
#### I can't get notification data when app is killed?
Libin Lu's avatar
Libin Lu committed
148
If you send notification with `data` only, you can only get the data message when app is in foreground or background. Killed app doesn't trigger FCMNotificationReceived. Seems that is how FCM works today
Libin Lu's avatar
Libin Lu committed
149
#### App running in background doesn't trigger `FCMNotificationReceived` when receiving hybrid notification [Android]
Libin Lu's avatar
Libin Lu committed
150
These is [an issue opened for that](https://github.com/google/gcm/issues/63). You will received data payload in FCM.initialData if you click on the notification. But if you just open the app, the data is lost.
Libin Lu's avatar
Libin Lu committed
151
#### I can't get `notification` payload when my android app is in foreground
Libin Lu's avatar
Libin Lu committed
152
It is better to use data payload if you need to pass data into application. I haven't implemented notification payload bridging in android module and am not planning to (the SDK should post notification for you)
Libin Lu's avatar
Libin Lu committed
153
#### Notification payload and data payload are mixed in iOS app.
Libin Lu's avatar
Libin Lu committed
154
I'm not doing any filtering. Try to add some `type` attributes to differentiate data payload from APN notification
Libin Lu's avatar
Libin Lu committed
155
#### App reloads when notification is clicked [Android]
Libin Lu's avatar
Libin Lu committed
156
Preserve app status with asyncStorage should get around this. Still looking for solution
Libin Lu's avatar
Libin Lu committed
157 158
### It is missing some features
Issues and pull requests are welcomed. Let's make this thing better!
Libin Lu's avatar
init  
Libin Lu committed
159