react-native push-notification fcm firebase

React Native Push Notification with FCM

龔健傑 Jianjack Keng 2021/09/20 09:47:16
3122

1. Introduction

Push Notification is much more common for all app and mobile users. In this article will simply show how to setup Push Notification configurations on React Native and integrate Firebase Cloud Message to receive notifications.

2. Environment Setup

In order to setup push notification on React Native, there are a few things we need to setup before we configure on our application.
i.   Access of  Apple Developer  account (Paid version)
ii.  Create a Firebase project
iii. React Native project
iv  Android & IOS testing devices (Simulator will not work on Remote Notification)

3. Create Key on Apple Developer

To integrate FCM with APNs, create new key to get
*.plist
file to configure in Firebase console.
 
NOTE: This is one-time download link, please keep the file in secure

4. Create Firebase Project

To create firebase project, go to Firebase console and create project for Push Notification
Disable Google Analytics if you don't need  it.
Wait until setup is done.
 

5. Setup Android Platform on Firebase

Go to Android icon to proceed setup in Home Screen.
Make sure the package name is the same in your application, under
android/app/src/main/AndroidManifest.xml
Download
google-services.json
file and move it to
android/app/google-services.json

6. Setup IOS Platform on Firebase

Go to IOS icon to proceed setup.
Make sure bundle identifier name should be the same in your application, can go to Xcode to refer on Bundle Identifier

Download
GoogleService-Info.plist
file and move it to
ios/{projectName}/GoogleService-Info.plist
Drag and drop
GoogleService-Info.plist
file from project folder to Xcode, it's to make sure that Xcode will copied the file from the Project folder when its build
Go to Firebase Project Settings (Cloud Messaging) and configure IOS APNs in order to receive notifications remotely.
Team ID and Key ID may refer on Apple Developer Account.
Setup done as below

7. Application Setup

Install
react-native-push-notification
and
push-notification-ios
in your application
npm install --save react-native-push-notification @react-native-community/push-notification-ios @react-native-firebase/app @react-native-firebase/messaging

7.1 Android Setup

In
android/build.gradle
, make sure you have following settings
ext {
    googlePlayServicesVersion = "<Your play services version>" // default: "+"
    firebaseMessagingVersion = "<Your Firebase version>" // default: "21.1.0"

    // Other settings
    compileSdkVersion = <Your compile SDK version> // default: 23
    buildToolsVersion = "<Your build tools version>" // default: "23.0.1"
    targetSdkVersion = <Your target SDK version> // default: 23
    supportLibVersion = "<Your support lib version>" // default: 23.1.1
}
dependencies {
    ...
    classpath 'com.google.gms:google-services:4.3.8'
    ...
}
In
android/app/build.gradle
, add following command at last line
apply plugin: 'com.google.gms.google-services'
In
android/app/src/main/AndroidManifest.xml
, add following configurations
<manifest ... xmlns:tools="http://schemas.android.com/tools">
    .....
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

    <application ....>
        <!-- Change the value to true to enable pop-up for in foreground on receiving remote notifications (for prevent duplicating while showing local notifications set this to false) -->
        <meta-data  android:name="com.dieam.reactnativepushnotification.notification_foreground"
                    android:value="false"/>
        <!-- Change the resource name to your App's accent color - or any other color you want -->
        <meta-data  android:name="com.dieam.reactnativepushnotification.notification_color"
                    android:resource="@color/white"/> <!-- or @android:color/{name} to use a standard color -->
        <!-- Change the channel id depends on your app created Channel -->
        <meta-data  android:name="com.google.firebase.messaging.default_notification_channel_id"
                    android:value="@string/default_notification_channel_id"
                    tools:replace="android:value" />

        <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationActions" />
        <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationPublisher" />
        <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationBootEventReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.intent.action.QUICKBOOT_POWERON" />
                <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
            </intent-filter>
        </receiver>

        <service
            android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerService"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>
    .....
</manifest>

7.2 IOS Setup

Add below command at the top of
ios/{projectName}/AppDelegate.m
file
#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>
#import <Firebase/Firebase.h>

Add following lines in same file

// Required for the register event.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
 [RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// Required for the notification event. You must call the completion handler after handling the remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
  [RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
 [RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
}
// Required for localNotification event
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void (^)(void))completionHandler
{
  [RNCPushNotificationIOS didReceiveNotificationResponse:response];
}
In
ios/{projectName}/AppDelegate.m
file, add following implementation
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  ...
  // Define UNUserNotificationCenter
  UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
  center.delegate = self;
  [FIRApp configure];

  return YES;
}

//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
  completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
}
Update
ios/{projectName}/AppDelegate.h
file
#import <UserNotifications/UNUserNotificationCenter.h>
Add
 UNUserNotificationCenterDelegate
to protocols
@interface AppDelegate : UIResponder <..., UNUserNotificationCenterDelegate>

7.3 Push Notification Setup

Add Push Notification basic configuration

import PushNotificationIOS from "@react-native-community/push-notification-ios";
import PushNotification from "react-native-push-notification";

// Must be outside of any component LifeCycle (such as `componentDidMount`).
PushNotification.configure({
  // (optional) Called when Token is generated (iOS and Android)
  onRegister: function (token) {
    // Will use Firebase Generated Token
    // console.log("TOKEN:", token);
  },

  // (required) Called when a remote is received or opened, or local notification is opened
  onNotification: function (notification) {
    console.log("NOTIFICATION:", notification);

    // process the notification

    // (required) Called when a remote is received or opened, or local notification is opened
    notification.finish(PushNotificationIOS.FetchResult.NoData);
  },
  // IOS ONLY (optional): default: all - Permissions to register.
  permissions: {
    alert: true,
    badge: true,
    sound: true,
  },

  // Should the initial notification be popped automatically
  // default: true
  popInitialNotification: true,

  /**
   * (optional) default: true
   * - Specified if permissions (ios) and token (android and ios) will requested or not,
   * - if not, you must call PushNotificationsHandler.requestPermissions() later
   * - if you are not using remote notification or do not have Firebase installed, use this:
   *     requestPermissions: Platform.OS === 'ios'
   */
  requestPermissions:  Platform.OS === 'ios',
});

Create New Channel ID (It's required for Android to receive remote notification, only applicable on Android 8 and above). Channel ID must be the same config on android/app/src/main/AndroidManifest.xml

PushNotification.createChannel(
  {
    channelId: CHANNEL_ID, // (required)
    channelName: 'React Native Firebase Cloud Messaging Channel', // (required)
    channelDescription: 'A channel to categorise your notifications', // (optional) default: undefined.
    playSound: true, // (optional) default: true
    soundName: 'default', // (optional) See `soundName` parameter of `localNotification` function
    importance: Importance.HIGH, // (optional) default: Importance.HIGH. Int value of the Android notification importance
    vibrate: true, // (optional) default: true. Creates the default vibration pattern if true.
  },
  created => console.log(`createChannel returned '${created}'`), // (optional) callback returns whether the channel was created, false means it already existed.
);

Get Firebase generated token

messaging()
  .hasPermission()
  .then(() => {
    messaging()
      .getToken()
      .then(token => {
        console.log("TOKEN: ", token)
      })
  });

Add Remote Notification listener

const unsubscribe = messaging().onMessage(async remoteMessage => {
  console.log("MESSAGE: ", remoteMessage)
});
return unsubscribe;

8. Run

Now everything is setup successfully, we can use mobile devices to test on Push Notifications
Use FCM Tester to test on remote notification

Server Key
can be found in Firebase Project Settings,
Device Token
would be the token generated from firebase.

9. Sample Code

10. References

龔健傑 Jianjack Keng