diff --git a/README.md b/README.md index 790c027eb8a9d197dc638e4c0261cc46a21c85c3..4a7875ceb3878825e86b4e2756023c1a8bfdedf0 100644 --- a/README.md +++ b/README.md @@ -3,126 +3,158 @@ ## Installation - Run `npm install react-native-fcm --save` -- Run `rnpm link` - -Or you can combine 2 commands -- Run `rnpm install react-native-fcm` +- Run `react-native link react-native-fcm` (RN 0.29.1+, otherwise `rnpm link react-native-fcm`) ## Android Configuration -- In `android/build.gradle` -```gradle -dependencies { -classpath 'com.android.tools.build:gradle:2.0.0' -classpath 'com.google.gms:google-services:3.0.0' // <- Add this line +- Edit `android/build.gradle`: +```diff + dependencies { + classpath 'com.android.tools.build:gradle:2.0.0' ++ classpath 'com.google.gms:google-services:3.0.0' ``` -- In `android/app/build.gradle` -```gradle -apply plugin: "com.android.application" -apply plugin: 'com.google.gms.google-services' // <- Add this line -... +- Edit `android/app/build.gradle`: +```diff + apply plugin: "com.android.application" ++ apply plugin: 'com.google.gms.google-services' ``` -- In `android/app/src/main/AndroidManifest.xml` +- Edit `android/app/src/main/AndroidManifest.xml`: +```diff + + ++ ++ ++ ++ ++ + ++ ++ ++ ++ ++ + + ... ``` - - -... - - - - - - - - - - - -... -``` + ### 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 - - + +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: + +Edit `AndroidManifest.xml`: + +```diff + + - - <--add this line - <--add this line, name should match click_action - <--add this line - <--add this line - + ++ ++ ++ ++ + ``` -and pass intent into package, change MainActivity.java -```java -import android.content.Intent; <--add this line next to the other imports - -// 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); -} + +Notes: +- `launchMode="singleTop"` is to reuse MainActivity +- replace `"fcm.ACTION.HELLO"` by the `click_action` you want to match + + +And pass intent into package, edit `MainActivity.java`: + +- RN 0.28+: + +```diff + import com.facebook.react.ReactActivity; ++ import android.content.Intent; + + public class MainActivity extends ReactActivity { + ++ @Override ++ public void onNewIntent (Intent intent) { ++ super.onNewIntent(intent); ++ setIntent(intent); ++ } +``` + +- RN <= 0.27: + +```diff + import com.facebook.react.ReactActivity; ++ import android.content.Intent; + + public class MainActivity extends ReactActivity { + ++ @Override ++ protected void onNewIntent (Intent intent) { ++ super.onNewIntent(intent); ++ setIntent(intent); ++ } ``` +Notes: +- `@Override` is added to update intent on notification click + ## IOS Configuration ### Pod approach: -install pod 'Firebase/Messaging' -NOTE: make sure cocoapods version > 1.0 +Make sure you have Cocoapods version > 1.0 + +Install the `Firebase/Messaging` pod: ``` cd ios && pod init pod install Firebase/Messaging ``` ### 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) + +1. Download the Firebase SDK framework from [Integrate without CocoaPods](https://firebase.google.com/docs/ios/setup#frameworks) +2. Follow the `README` to link frameworks (Analytics+Messaging) ### Shared steps -in AppDelegate.m add -``` -#import "Firebase.h" <--add if you are using Non Cocoapod approach -#import "RNFIRMessaging.h" <--add this line -... - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ -.... - [FIRApp configure]; <-- add this line -} -//add this method -- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler { - [[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:notification]; - handler(UIBackgroundFetchResultNewData); -} -``` +Edit `AppDelegate.m`: +```diff ++ #import "Firebase.h" // if you are using Non Cocoapod approach ++ #import "RNFIRMessaging.h" + //... + + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions + { + //... ++ [FIRApp configure]; + } ++ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler { ++ [[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:notification]; ++ handler(UIBackgroundFetchResultNewData); ++ } +``` ### 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 `GoogleService-Info.plist` file and place it in `/ios/your-project-name` directory (next to your `Info.plist`) ## Usage ```javascript - import FCM from 'react-native-fcm'; +import FCM from 'react-native-fcm'; - ... - componentWillMount() { - FCM.requestPermissions(); +class App extends Component { + componentDidMount() { + FCM.requestPermissions(); // for iOS FCM.getFCMToken().then(token => { console.log(token) // store fcm token in your server @@ -134,17 +166,17 @@ In [firebase console](https://console.firebase.google.com/), you can get `google console.log(token) // fcm token may not be available on first load, catch it here }); - + FCM.subscribeToTopic('/topics/foo-bar'); FCM.unsubscribeFromTopic('/topics/foo-bar'); } componentWillUnmount() { - // prevent leak + // prevent leaking this.refreshUnsubscribe(); this.notificationUnsubscribe(); } - ... +} ``` ### Behaviour when sending `notification` and `data` payload through GCM @@ -155,12 +187,13 @@ In [firebase console](https://console.firebase.google.com/), you can get `google * 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 - - e.g. fcm payload looks like - ``` + - 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 + + e.g. fcm payload looks like: + + ```json { "to":"some_device_token", "content_available": true, @@ -174,34 +207,51 @@ In [firebase console](https://console.firebase.google.com/), you can get `google } } ``` - and event callback will receive as - ``` - ///Android - { - fcm: {"action": "fcm.ACTION.HELLO"}, - extra: "juice" - } - ///IOS - { - apns: {action_category: "fcm.ACTION.HELLO"}, - extra: "juice" - } - ``` + + and event callback will receive as: + + - Android + ```json + { + "fcm": {"action": "fcm.ACTION.HELLO"}, + "extra": "juice" + } + ``` + + - iOS + ```json + { + "apns": {"action_category": "fcm.ACTION.HELLO"}, + "extra": "juice" + } + ``` - When app is running in foreground - IOS will receive notification and android **won't** (better not to do anything in foreground for hybrid and send a seprate data message.) -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) +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)). ## Q & A -#### My android build is failing + +#### My Android build is failing Try update your SDK and google play service + #### I can't get notification when app is killed -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 +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. + #### App running in background doesn't trigger `FCMNotificationReceived` when receiving hybrid notification [Android] These is [an issue opened for that](https://github.com/google/gcm/issues/63). Behavior is not consistent between 2 platforms + #### 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. -#### It is missing some features -Issues and pull requests are welcomed. Let's make this thing better! +Since Lollipop, the push notification icon is required to be all white, otherwise it will be a white circle. + +#### I am using Proguard +You need to add this to your `android/app/proguard-rules.pro`: +``` +# Google Play Services +-keep class com.google.android.gms.** { *; } +-dontwarn com.google.android.gms.** +``` +#### Some features are missing +Issues and pull requests are welcome. Let's make this thing better!