README.md 7.8 KB
Newer Older
Libin Lu's avatar
Libin Lu committed
1 2
[![Join the chat at https://gitter.im/evollu/react-native-fcm](https://badges.gitter.im/evollu/react-native-fcm.svg)](https://gitter.im/evollu/react-native-fcm?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

Libin Lu's avatar
init  
Libin Lu committed
3 4 5
## Installation

- Run `npm install react-native-fcm --save`
Libin Lu's avatar
Libin Lu committed
6
- Run `rnpm link`
Libin Lu's avatar
Libin Lu committed
7

Libin Lu's avatar
Libin Lu committed
8
Or you can combine 2 commands
Ashwin Preetham Lobo's avatar
Ashwin Preetham Lobo committed
9
- Run `rnpm install react-native-fcm`
Libin Lu's avatar
init  
Libin Lu committed
10

11
## Android Configuration
Libin Lu's avatar
init  
Libin Lu committed
12 13 14 15

- In `android/build.gradle`
```gradle
dependencies {
Libin Lu's avatar
Libin Lu committed
16 17
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
18 19 20 21 22 23 24 25 26
```

- 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
27
- In `android/app/src/main/AndroidManifest.xml`
Libin Lu's avatar
init  
Libin Lu committed
28 29 30

```
<application
Libin Lu's avatar
Libin Lu committed
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
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
46
```
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
### Config for notification and `click_action` in Android
To allow android to respond to `click_action`, you need to define Activities and filter on specific intent. Since all javascript is running in MainActivity, you can have MainActivity to handle actions.
```xml
<activity
  android:name=".MainActivity"
  android:label="@string/app_name"
  android:windowSoftInputMode="adjustResize"
  android:launchMode="singleTop"                                          <--add this line to reuse MainActivity
  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
        <action android:name="fcm.ACTION.HELLO" />                        <--add this line, name should match click_action
        <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
Yann Leflour's avatar
Yann Leflour committed
68 69
import android.content.Intent;                                            <--add this line next to the other imports

70 71 72 73 74 75 76
// Add this line to update intent on notification click
@Override
// in RN <= 0.27 you may need to use `protected void onNewIntent (Intent intent) {`
public void onNewIntent (Intent intent) {
  super.onNewIntent(intent);
    setIntent(intent);
}       
77
```
Libin Lu's avatar
init  
Libin Lu committed
78

79
## IOS Configuration
Libin Lu's avatar
init  
Libin Lu committed
80

Libin Lu's avatar
Libin Lu committed
81 82
### Pod approach:

Libin Lu's avatar
init  
Libin Lu committed
83
install pod 'Firebase/Messaging'
Libin Lu's avatar
Libin Lu committed
84 85 86 87 88
NOTE: make sure cocoapods version > 1.0
```
cd ios && pod init
pod install Firebase/Messaging
```
Libin Lu's avatar
init  
Libin Lu committed
89

Libin Lu's avatar
Libin Lu committed
90 91 92 93 94 95
### Non Cocoapod approach
1. download framework from https://firebase.google.com/docs/ios/setup last section Integrate without CocoaPods
2. Follow the readme to link frameworks (Analytics+Messaging)
3. current zip file is missing `FirebaseAnalytics.framework` file. I put one in the root of this repository

### Shared steps
Libin Lu's avatar
init  
Libin Lu committed
96 97
in AppDelegate.m add
```
Libin Lu's avatar
Libin Lu committed
98
#import "Firebase.h" <--add if you are using Non Cocoapod approach
Libin Lu's avatar
Libin Lu committed
99
#import "RNFIRMessaging.h" <--add this line
Libin Lu's avatar
Libin Lu committed
100
...
Libin Lu's avatar
init  
Libin Lu committed
101

Libin Lu's avatar
Libin Lu committed
102 103 104
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
....
105
  [FIRApp configure]; <-- add this line
Libin Lu's avatar
Libin Lu committed
106
}
Libin Lu's avatar
init  
Libin Lu committed
107

Libin Lu's avatar
Libin Lu committed
108
//add this method
109 110
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler {
  [[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:notification];
Libin Lu's avatar
Libin Lu committed
111
  handler(UIBackgroundFetchResultNewData);
Libin Lu's avatar
init  
Libin Lu committed
112 113 114 115 116
}
```


### FCM config file
117
In [firebase console](https://console.firebase.google.com/), you can get `google-services.json` file and place it in `android/app` directory and get `GoogleService-Info.plist` file and place it in `/ios/your-project-name` directory (next to your `Info.plist`)
Libin Lu's avatar
init  
Libin Lu committed
118

Libin Lu's avatar
Libin Lu committed
119
## Usage
Libin Lu's avatar
init  
Libin Lu committed
120 121

```javascript
Goran Gajic's avatar
Goran Gajic committed
122 123 124 125 126 127 128 129 130 131 132 133
  import FCM from 'react-native-fcm';

  ...
  componentWillMount() {
    FCM.requestPermissions();
    FCM.getFCMToken().then(token => {
      console.log(token)
      // store fcm token in your server
    });
    this.notificationUnsubscribe = FCM.on('notification', (notif) => {
      // there are two parts of notif. notif.notification contains the notification payload, notif.data contains data payload
    });
134 135
    this.refreshUnsubscribe = FCM.on('refreshToken', (token) => {
      console.log(token)
Goran Gajic's avatar
Goran Gajic committed
136 137
      // fcm token may not be available on first load, catch it here
    });
Libin Lu's avatar
Libin Lu committed
138 139 140
    
    FCM.subscribeToTopic('/topics/foo-bar');
    FCM.unsubscribeFromTopic('/topics/foo-bar');
Goran Gajic's avatar
Goran Gajic committed
141 142 143 144 145 146 147 148
  }

  componentWillUnmount() {
    // prevent leak
    this.refreshUnsubscribe();
    this.notificationUnsubscribe();
  }
  ...
Libin Lu's avatar
init  
Libin Lu committed
149 150
```

151
### Behaviour when sending `notification` and `data` payload through GCM
Libin Lu's avatar
Libin Lu committed
152 153 154 155
- 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)

Libin Lu's avatar
Libin Lu committed
156 157 158 159 160 161 162 163 164
- When app is running in background (the tricky one, I strongly suggest you try it out yourself)
 - IOS will receive notificaton from `FCMNotificationReceived` event
    * if you pass `content_available` flag true, you will receive one when app is in background and another one when user resume the app. [more info](http://www.rahuljiresal.com/2015/03/retract-push-notifications-on-ios/)
    * if you just pass `notification`, you will only receive one when user resume the app.
    * you will not see banner if `notification->body` is not defined.
 - Android will receive notificaton from `FCMNotificationReceived` event 
    * if you pass `notification` payload. it will receive data when user click on notification 
    * if you pass `data` payload only, it will receive data when in background 
   
Libin Lu's avatar
Libin Lu committed
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
   e.g. fcm payload looks like
   ```
   {
      "to":"some_device_token",
      "content_available": true,
      "notification": {
          "title": "hello",
          "body": "yo",
          "click_action": "fcm.ACTION.HELLO"
      },
      "data": {
          "extra":"juice"
      }
    }
    ```
    and event callback will receive as
    ```
    ///Android
    {
      fcm: {"action": "fcm.ACTION.HELLO"},
      extra: "juice"
    }
    ///IOS
    {
      apns: {action_category: "fcm.ACTION.HELLO"},
      extra: "juice"
    }
    ```
193

Libin Lu's avatar
Libin Lu committed
194
- When app is running in foreground
195
 - IOS will receive notification and android **won't** (better not to do anything in foreground for hybrid and send a seprate data message.)
196

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

Libin Lu's avatar
init  
Libin Lu committed
199
## Q & A
Libin Lu's avatar
Libin Lu committed
200
#### My android build is failing
Libin Lu's avatar
Libin Lu committed
201
Try update your SDK and google play service
202
#### I can't get notification when app is killed
Libin Lu's avatar
Libin Lu committed
203
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. Use `notification` in the payload instead
Libin Lu's avatar
Libin Lu committed
204
#### App running in background doesn't trigger `FCMNotificationReceived` when receiving hybrid notification [Android]
205
These is [an issue opened for that](https://github.com/google/gcm/issues/63). Behavior is not consistent between 2 platforms
Libin Lu's avatar
Libin Lu committed
206 207
#### Android notification is showing a white icon
Since Lolipop, push notification icon is required to be all white, otherwise it will be a white circle.
208
#### It is missing some features
Libin Lu's avatar
Libin Lu committed
209
Issues and pull requests are welcomed. Let's make this thing better!
Libin Lu's avatar
init  
Libin Lu committed
210