React native - Push Notification (Firebase)

How to add Push Notification in your project? I use firebase to send cloud messages by Push Notification. First of all, you click the website "https://rnfirebase.io/" , and click the menu "Cloud Messaging"

Installation

# Install & set up the app module
yarn add @react-native-firebase/app

# Install the messaging module
yarn add @react-native-firebase/messaging

# If you're developing your app using iOS, run this command
cd ios/ && pod install

iOS Setup

AppDelegate.m

@import Firebase;

@interface AppDelegate () <FIRMessagingDelegate>

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [FIRApp configure];
    [application registerForRemoteNotifications];
    [FIRMessaging messaging].delegate = self;
}

- (void) messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
    NSLog(@"FCM registration token: %@", fcmToken);
    // Notify about received token.
    NSDictionary *dataDict = [NSDictionary dictionaryWithObject:fcmToken forKey:@"token"];
    [[NSNotificationCenter defaultCenter] postNotificationName:
     @"FCMToken" object:nil userInfo:dataDict];
    // TODO: If necessary send token to application server.
    // Note: This callback is fired at each app startup and whenever a new token is generated.
}


- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
  NSLog(@"error: %@", error);
}

Android Setup

/appName/android/app/src/main/AndroidManifest.xml

<service android:name=".MyFirebaseMessagingService" android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

/android/app/src/main/java/com/appName/MyFirebaseMessagingService.java

package com.stylepedia;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import android.util.Log;

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    private final String TAG = "FCMDemo";

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {

        // TODO(developer): Handle FCM messages here.
        Log.d(TAG, "From: " + remoteMessage.getFrom());

        if (remoteMessage.getData().size() > 0) {
            Log.d(TAG, "Message data payload: " + remoteMessage.getData());
        }

        // Check if the message contains a notification payload.
        if (remoteMessage.getNotification() != null) {
            Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
        }

        // Also if you intend on generating your own notifications as a result of a received FCM
        // message, here is where that should be initiated. See sendNotification method below.
    }

    private void sendRegistrationToServer(String token) {
        // TODO: Implement this method to send token to your app server.
    }

    @Override
    public void onNewToken(String token) {
        Log.d(TAG, "From: " + token);
        sendRegistrationToServer(token);
    }
}

React Native

You can get token by this function, if the device didn't open Push Notification, you won't get the token, so you make sure that the user have opened the notifications.

import messaging from '@react-native-firebase/messaging'

if (!messaging().isDeviceRegisteredForRemoteMessages) {
    messaging().registerDeviceForRemoteMessages()
}
messaging().getToken()
.then(fcmToken => {
  if (fcmToken) {
    console.warn(fcmToken)
    if (Platform.OS === 'ios') {
      this.iosTokenNetWork(fcmToken)
    }
    else {
      this.androidTokenNetWork(fcmToken)
    }
  } else {
    console.warn('user doesn t have a device token yet')
    // user doesn't have a device token yet
  }
})

You can use this function to check if the user opens the push notification switch on the user's device.

messaging().requestPermission().then((response: any) => {
  //
}

// if user click allow app push notification on pop-up,I can get token by function: 

messaging().requestPermission().then((response: any) => {
    if (!messaging().isDeviceRegisteredForRemoteMessages) {
        messaging().registerDeviceForRemoteMessages()
      }
      messaging().getToken()
        .then(fcmToken => {
          if (fcmToken) {
            if (Platform.OS === 'ios') {
              this.iosTokenNetWork(fcmToken)
            }
            else {
              this.androidTokenNetWork(fcmToken)
            }
          } else {
            console.warn('user doesn t have a device token yet')
            // user doesn't have a device token yet
          }
        })
})

You can click Push notification and go to another page when the App is in the background.

messaging().setBackgroundMessageHandler(async remoteMessage => {
        if (remoteMessage) {
          appsFlyer.trackEvent("Open_notification")
          analytics().logEvent('Open_notification', {
            value: '',
          });
          if (remoteMessage.data.send_user_history_id) {
            this.pushRequest(remoteMessage.data.send_user_history_id)
          }
          if (remoteMessage.data.url === "MixMatch") {  
              this.props.navigation.push('MyClosetDetailPage', {
                product_id: remoteMessage.data.push_id,
                returnPage: 'Tabs',
              })
  
          }
          if (remoteMessage.data.url === "StreetSnap") {
            this.timer = setTimeout(() => {
              this.props.navigation.navigate('PushlookbookStreetSnapPage', {
                streetId: remoteMessage.data.push_id,
                returnPage: 'Tabs',
              })
            }, 500);
          }
      }
});

You can click Push notification and go to another page when the App is closed

messaging()
      .getInitialNotification()
      .then(remoteMessage => {
        if (remoteMessage) {
          appsFlyer.trackEvent("Open_notification")
          analytics().logEvent('Open_notification', {
            value: '',
          });
          // alert(JSON.stringify(remoteMessage) )

            if (remoteMessage.data.url === "MixMatch") {

              this.timer = setTimeout(() => {
                this.props.navigation.push('MyClosetDetailPage', {
                  product_id: remoteMessage.data.push_id,
                  returnPage: 'Tabs',
                })
              }, 500);
            }
            if (remoteMessage.data.url === "StreetSnap") {
              this.timer = setTimeout(() => {
                this.props.navigation.navigate('PushlookbookStreetSnapPage', {
                  streetId: remoteMessage.data.push_id,
                  returnPage: 'Tabs',
                })
              }, 500);
            }
          }
})

Create Notification Service Extension

If I want to send an iOS Push Notification with picture to my iPhone, I have to add the iOS Push Notification with Notification Service Extension.

  1. In the Xcode menu, go to File > New > Target.
  2. Select the Notification Service Extension.
  3. Gives the name the Extension service and click the finish button.

and enable Push Notification and App Group capabilities in iOS App target.

NotificationService.h

#import <UserNotifications/UserNotifications.h>

@interface NotificationService : UNNotificationServiceExtension

@end

NotificationService.m

#import "NotificationService.h"
@import Firebase;

@interface NotificationService ()

@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;

@end

@implementation NotificationService

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    self.contentHandler = contentHandler;
    self.bestAttemptContent = [request.content mutableCopy];
    
    // Modify the notification content here...
  if (self.bestAttemptContent.title) {
    self.bestAttemptContent.title = [NSString stringWithFormat:@"%@", self.bestAttemptContent.title];
  }
  [[FIRMessaging extensionHelper] populateNotificationContent:self.bestAttemptContent
  withContentHandler:contentHandler];
}

- (void)serviceExtensionTimeWillExpire {
    // Called just before the extension will be terminated by the system.
    // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
    self.contentHandler(self.bestAttemptContent);
}

@end

The format of Push Notification Service be sent by Server

The content of data can be added or deleted with costume way. if your android device click the push notification bar, and then the app is not opened, the problem must be caused by the format of Push Notification Service. iOS as well.

{
  "message": {
    "notification": {
      "title": "title",
      "body": "message content"
    },
    "token": "fi7FrXMCFeQ:APA91bEZ3CCZEu6NJCzPNyOXq3QoGuCgZ_NZ6pSkuvAYM-VKTvfj1FbnBQKimHaOVqWv_4FD_eGZn1CcfNRf2Ve6X4_mYNwmgI99A1ngxcnY6oyjXTcNRsdIh7YD3SizhRHoTbIXcn-8",
    "data": {
      "image_url": "",
      "push_type": "0",
      "type": "0",
      "url": "MixMatch",
      "push_id": "6587588",
      "send_user_history_id": ""
    },
    "apns": {
      "headers": {
        "apns-priority": "10"
      },
      "payload": {
        "aps": {
          "badge": 1,
          "mutable-content": 1
        }
      },
      "fcm_options": {
        "image": ""
      }
    }
  }
}

Detecting that notification is open or closed when app is in foreground or background.

if we need to detect when our app is coming to the foreground or when it comes to background, the AppState will help me to do it so easy:


import NotificationManager from 'react-native-check-notification-enable'

constructor(props) {
    super(props);
    this.state = {
        loginShow: false,
        loginStatus: false,
        isEnabled: false,
    }
    this.flage = false
}

componentDidMount() {
    AppState.addEventListener('change',this._handleAppStateChange)
    this._navListener = this.props.navigation.addListener('didFocus', () => {

      if (Platform.OS === 'ios') {
        messaging().requestPermission().then((response: any) => {
            if (response === 1) {
                this.setState(prevState => ({
                    isEnabled: true
                }))
            }
            else {
                this.setState(prevState => ({
                    isEnabled: false
                }))
            }
        })
      }
      else {
        NotificationManager.areNotificationsEnabled().then((e)=>{
            if (e === true) {
                this.setState(prevState => ({
                    isEnabled: true
                }))
            }
            else {
                this.setState(prevState => ({
                    isEnabled: false
                }))
            }
          }).catch((e)=>{
            this.setState(prevState => ({
                isEnabled: false
            }))
          })
      }

    })
}

_handleAppStateChange = (nextAppState) => {
    if (nextAppState != null && nextAppState === 'active') {
        //如果是true 腋舌,表示從后臺進入了前臺 能颁,請求數(shù)據(jù),刷新頁面”疗欤或者做其他的邏輯
        if (this.flage) {
            if (Platform.OS === 'ios') {
                messaging().requestPermission().then((response: any) => {
                    if (response === 1) {
                        this.setState(prevState => ({
                            isEnabled: true
                        }))
                    }
                    else {
                        this.setState(prevState => ({
                            isEnabled: false
                        }))
                    }
                })
            }
            else {
                NotificationManager.areNotificationsEnabled().then((e) => {
                    if (e === true) {
                        this.setState(prevState => ({
                            isEnabled: true
                        }))
                    }
                    else {
                        this.setState(prevState => ({
                            isEnabled: false
                        }))
                    }
                }).catch((e) => {
                    this.setState(prevState => ({
                        isEnabled: false
                    }))
                })
            }
        }
        this.flage = false;
    } else if (nextAppState != null && nextAppState === 'background') {
        this.flage = true;
    }
}


_handleAppStateChange = (nextAppState) => {
    if (nextAppState != null && nextAppState === 'active') {
        //如果是true 灾部,表示從后臺進入了前臺 ,請求數(shù)據(jù)棒卷,刷新頁面∪秤遥或者做其他的邏輯
        if (this.flage) {
            if (Platform.OS === 'ios') {
                messaging().requestPermission().then((response: any) => {
                    if (response === 1) {
                        this.setState(prevState => ({
                            isEnabled: true
                        }))
                    }
                    else {
                        this.setState(prevState => ({
                            isEnabled: false
                        }))
                    }
                })
            }
            else {
                NotificationManager.areNotificationsEnabled().then((e) => {
                    if (e === true) {
                        this.setState(prevState => ({
                            isEnabled: true
                        }))
                    }
                    else {
                        this.setState(prevState => ({
                            isEnabled: false
                        }))
                    }
                }).catch((e) => {
                    this.setState(prevState => ({
                        isEnabled: false
                    }))
                })
            }
        }
        this.flage = false;
    } else if (nextAppState != null && nextAppState === 'background') {
        this.flage = true;
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末娇跟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子太颤,更是在濱河造成了極大的恐慌苞俘,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件龄章,死亡現(xiàn)場離奇詭異吃谣,居然都是意外死亡乞封,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門岗憋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來肃晚,“玉大人,你說我怎么就攤上這事仔戈」卮” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵监徘,是天一觀的道長晋修。 經(jīng)常有香客問我,道長凰盔,這世上最難降的妖魔是什么墓卦? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮户敬,結(jié)果婚禮上落剪,老公的妹妹穿的比我還像新娘。我一直安慰自己尿庐,他們只是感情好忠怖,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著抄瑟,像睡著了一般脑又。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锐借,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機與錄音往衷,去河邊找鬼钞翔。 笑死,一個胖子當著我的面吹牛席舍,可吹牛的內(nèi)容都是我干的布轿。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼来颤,長吁一口氣:“原來是場噩夢啊……” “哼汰扭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起福铅,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤萝毛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后滑黔,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體笆包,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡环揽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了庵佣。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片歉胶。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖巴粪,靈堂內(nèi)的尸體忽然破棺而出通今,到底是詐尸還是另有隱情,我是刑警寧澤肛根,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布辫塌,位于F島的核電站,受9級特大地震影響晶通,放射性物質(zhì)發(fā)生泄漏璃氢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一狮辽、第九天 我趴在偏房一處隱蔽的房頂上張望一也。 院中可真熱鬧,春花似錦喉脖、人聲如沸椰苟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽舆蝴。三九已至,卻和暖如春题诵,著一層夾襖步出監(jiān)牢的瞬間洁仗,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工性锭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留赠潦,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓草冈,卻偏偏與公主長得像她奥,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子怎棱,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容