Push message via react-native-firebase(V5)

2020-08-18 hit count image

Let's see how to use FCM(Firebase Cloud Messaging) via react-native-firebase(V5) to implement Push message on React Native.

Outline

The app developed by React Native is also a normal app, so it can receive a Push message. In this blog post, I will show you how to use FCM(Firebase Cloud Messaging) via react-native-firebase(V5) library to revceive a Push message on React Native.

Install library

Execute the command below to install react-native-firebase library.

npm install --save react-native-firebase

We need to link react-native-firebase library to use it.

Over 0.60 version

Execute the command below to link react-native-firebase library to React Native project.

cd ios
pod install
cd ..

Under 0.59 version

Execute the command below to link react-native-firebase library to React Native project.

react-native link react-native-firebase

Create Firebase project

Next, we need to create a project on Google Firebase. Click the link below to go to Google Firebase.

Click the SIGN IN button on the right top to login.

google firebase after login

After login, click the GO TO CONSOLE button on the right tope to go to Google Firebase Console.

google firebase console

On Google Firebase Console, click + Add project to add a new project.

google firebase console add project

After inserting the project information, click the Create project button to create the project.

iOS settings

Let’s see how to configure react-native-firebase for iOS.

Configure iOS project on Firebase

When you click the project on Google Firebase Console, you can see the screen like below.

google firebase console project

click the iOS button on the center to go to iOS configuration.

google firebase console project ios

Insert Bundle ID of the app, and click Register app button

GoogleService-Info.plist download

Download GoogleService-Info.plist file which is created by Google Firebase, and move it to the same location of info.plist file. after adding GoogleService-Info.plist file, click Next button.

add Firebase SDK

We need to add Google Firebase SDK to React Native poject like above.

If you use React Native under 0.59 version, execute the command below.

pod init

To add Google Firebase SDK, modify ./ios/Podfile file like below.

target 'blaboo' do
  ...
  pod 'Firebase/Core'
  pod 'Firebase/Analytics' // if you use Analytics
  pod 'Firebase/Messaging'
  ...
end

Install Google Firebase SDK.

pod install
# pod update

edit appdelegate.m for firebase

Open AppDelegate.m file on React Native porject, and modify it like below,

...
@import Firebase;
#import "RNFirebaseNotifications.h"
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [FIRApp configure];
  [RNFirebaseNotifications configure];
  ...
  return YES;
}
...

To initialize Google Firebase SDK.

connect firebase to app

At this part, I clicked Skip this step to skip this section.

Configure Permissions

To configure the permissions, open ios/[project name].xcworkspace file to execute Xcode.

After executing the Xcode, click the proejct on the left menu, and click the Signing & Capabilities tab.

react native firebase analytics

click +Capabilty on the top. Search and add the permissions below.

  • Push Notifications
  • Background modes

When you add Background modes, you can see the checkbox list unlike Push Notifications permmision. Select Remote notifications in the list.

APNS setting

We need to configure APNS(Apple Push Notification Service) to use Push message on iOS.

open Keychain Access on macOS. And the, click Keychain Access > Certificate Assistant > Request a Certificate From a Certificate Authority... menu.

APNS(Apple Push Notification Service) - request a certificate from a certicate authority

If the screen blow is shown up, insert User Email Address and Common Name, and select Saved to disk. After it, click Continue button to go to the next.

APNS(Apple Push Notification Service) - request a certificate from a certicate authority insert information

When you see the screen like below, select the folder which you want to save the file, and click Save button to save it.

APNS(Apple Push Notification Service) - request a certificate from a certicate authority save certification

Next, go to https://developer.apple.com/ site.

APNS(Apple Push Notification Service) - apple developer site

click the Account menu on the right top, and login. If you see the screen like below, click Certificates, Identifiers & Profiles menu.

APNS(Apple Push Notification Service) - apple developer site Certificates, Identifiers & Profiles

When you see the screen like below, click Certificates menu and click + button on the top.

APNS(Apple Push Notification Service) - Certificates, Identifiers & Profiles Add Certificates

Next, when Create a New Certificate is shown up, scroll it to go down. When you scroll down, you can find Apple Push Notification service SSL (Sandbox & Production) on Service section. Select it, and click Continue button on the right top to go to the next.

APNS(Apple Push Notification Service) - Certificates, Identifiers & Profiles Apple push notification service

When you see the screen like below, select the app which you want to implement FCM feature, and click Continue button to go to the next.

APNS(Apple Push Notification Service) - Certificates, Identifiers & Profiles Apple push notification service

When you see the screen like below, click Choose File and select the file which you’ve made via Keychain. After selecting, click Continue button.

APNS(Apple Push Notification Service) - Certificates, Identifiers & Profiles Apple push notification service

If you see the screen like below, you made a certification well. Click Download button on the right top to download the certification.

APNS(Apple Push Notification Service) - Certificates, Identifiers & Profiles Apple push notification service

We need to transform this certification to .p12 format. Double-click the certification to register it to Keychain.

APNS(Apple Push Notification Service) - generate .p12

Right-click the registered certification, select Export "Apple Push Services: package name"... menu.

APNS(Apple Push Notification Service) - generate .p12 export

When the screen above is shown up, select Personal Information Exchange (.p12) on File Format and click Save button to save the file.

APNS(Apple Push Notification Service) - generate .p12 insert password

We need to insert a password to save p12 file like above. Insert the password to save .p12 file.

Next, go to Firebase Console, and click the project which we’ve made above. After it, you can see the iOS project on the right side.

APNS(Apple Push Notification Service) - Firebase Console select ios

Click the iOS project, and click the configuration icon to go to the iOS project setting screen. Click Cloud Messaging menu on the iOS setting screen.

APNS(Apple Push Notification Service) - Firebase Console cloud messaging

You can see the APNs certificates on iOS app configuration section on the bottom. Click Upload button on No development APNs certificate and No production APNs certificate.

APNS(Apple Push Notification Service) - Firebase Console upload p12 file

When this screen is shown up, upload .p12 file, and insert the password which you made .p12 file.

APNS(Apple Push Notification Service) - Firebase Console finish settings

We’ve done all configurations for APNS(Apple Push Notification Service).

Android settings

Next, let’s see how to configure Anddroid to use react-native-firebase.

Modify Android package name

  • Modify android/app/BUCK file on React Native project like below.

    ...
    android_build_config(
        ...
        package = "package_name",
    )
    ...
    android_resource(
        ...
        package = "package_name",
        ...
    )
    ...
    
  • Modify android/app/src/main/AndroidManifest.xml file on React Native project like below.

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="package_name">
    ...
    
  • Modify android/app/src/main/java/com/ProjectName/MainActivity.java file on React Native project like below.

    package package_name;
    ...
    
  • Modify android/app/src/main/java/com/ProjectName/MainApplication.java file on React Native project like below.

    package package_name;
    ...
    
  • Modify android/app/build.gradle file on React Native project like below.

    ...
    defaultConfig {
        applicationId package_name
        ...
    }
    ...
    

Configure Android proejt on Firbase

Click Project Overview on left top of the Google Firebase Console.

Google Firebase Console Project Overview

Click + Add app > Android icon to go to the Android project setting.

Google Firebase Android app register

Insert Android Package Name, and click REgister app button.

Google Firebase google-services.json setting

Copy google-services.json file which Google Firebase generates to android/app folder on React Native project. And then, click Next button to go to the next.

Google Firebase setting on android

Open android/build.gradle file on React Native project and modify it like below.

buildscript {
  repositories {
    google()
    jcenter()
  }
  dependencies {
    classpath("com.android.tools.build:gradle:3.4.2")
    classpath 'com.google.gms:google-services:4.3.3'
  }
}
...
allprojects {
  repositories {
    mavenLocal()
    google()
    jcenter()
    ...
  }
}

As you see above, google() should be in repositories and be defined above jcenter().

Open android/app/build.gradle file and modify it like below.

dependencies {
    // under 59 version
    // implementation project(':react-native-firebase')
    ...
    implementation 'com.google.android.gms:play-services-base:17.2.1'
    implementation 'com.google.firebase:firebase-core:17.0.0'
    implementation "com.google.firebase:firebase-messaging:20.0.0"
    implementation 'me.leolin:ShortcutBadger:1.1.21@aar'
}

And the, add the code below to the bottom of the same file.

...
apply plugin: 'com.google.gms.google-services'

Next, Open ./android/build.gradle file and modify it like below.

buildscript {
    ext {
        ...
    }
    repositories {
        ...
    }
    dependencies {
        classpath("com.android.tools.build:gradle:3.4.2")
        classpath 'com.google.gms:google-services:4.3.3'
    }
}
  • Over 0.60 version

To use react-native-firebase, open android/app/src/main/java/com/[app name]/MainApplication.java file and modify it like below.

import io.invertase.firebase.RNFirebasePackage;
import io.invertase.firebase.analytics.RNFirebaseAnalyticsPackage;
import io.invertase.firebase.messaging.RNFirebaseMessagingPackage;
import io.invertase.firebase.notifications.RNFirebaseNotificationsPackage;
...
@Override
protected List<ReactPackage> getPackages() {
  @SuppressWarnings("UnnecessaryLocalVariable")
  List<ReactPackage> packages = new PackageList(this).getPackages();
  // Packages that cannot be autolinked yet can be added manually here, for example:
  // packages.add(new MyReactNativePackage());
  packages.add(new RNFirebaseAnalyticsPackage());
  packages.add(new RNFirebaseMessagingPackage());
  packages.add(new RNFirebaseNotificationsPackage());
  return packages;
}
...
  • Under 0.59 version

To use react-native-firebase, open android/app/src/main/java/com/[app name]/MainApplication.java file and modify it like below.

import io.invertase.firebase.RNFirebasePackage;
import io.invertase.firebase.analytics.RNFirebaseAnalyticsPackage;
import io.invertase.firebase.messaging.RNFirebaseMessagingPackage;
...

@Override
protected List<ReactPackage> getPackages() {
  return Arrays.<ReactPackage>asList(
    ...
    new RNFirebasePackage(),
    new RNFirebaseAnalyticsPackage(),
    new RNFirebaseMessagingPackage()
    ...
  );
}

To receive the Push message, open android/app/src/main/AndroidManifest.xml file and modify it like below.

<application ...>
...
<service android:name="io.invertase.firebase.messaging.RNFirebaseMessagingService">
  <intent-filter>
    <action android:name="com.google.firebase.MESSAGING_EVENT" />
  </intent-filter>
</service>
<service android:name="io.invertase.firebase.messaging.RNFirebaseBackgroundMessagingService" />
...
</application>

Open the Android proejct via Android Studio and click Gradle Sync.

Test

Let’s test FCM to check the configuration well.

Add Javascript source code

To test, we need FCM Token. To get this token, we need to use Javascript. You can use this source code to the production projecton.

Create ./src/Components/FCMContainer/index.tsx file and modify it like below to use FCM.

import React, { useEffect } from 'react';
import { Platform, Alert } from 'react-native';
import firebase from 'react-native-firebase';
import DeviceInfo from 'react-native-device-info';
import AsyncStorage from '@react-native-community/async-storage';
import Axios from 'axios';

import Config from '~/Config';

interface Props {
  children: JSX.Element;
  onNotificationOpened?: (data: { [key: string]: string }) => any;
}

const FCMContainer = ({ children, onNotificationOpened }: Props): JSX.Element => {
  const CHANNEL_ID = 'io.github.dev.yakuza.poma';
  const APP_NAME = 'POMA';
  const DESCRIPTION = 'POMA channel';

  let _onTokenRefreshListener: any = undefined;
  let _notificationDisplayedListener: any = undefined;
  let _notificationListener: any = undefined;
  let _notificationOpenedListener: any = undefined;

  const _registerMessageListener = (): void => {
    firebase
      .notifications()
      .getInitialNotification()
      .then((notificationOpen) => {
        if (
          onNotificationOpened &&
          typeof onNotificationOpened === 'function' &&
          notificationOpen &&
          notificationOpen.notification &&
          notificationOpen.notification.data &&
          notificationOpen.notification.data.notifications_id
        ) {
          onNotificationOpened(notificationOpen.notification.data);
        }
      });

    const channel = new firebase.notifications.Android.Channel(
      CHANNEL_ID,
      APP_NAME,
      firebase.notifications.Android.Importance.Max,
    ).setDescription(DESCRIPTION);
    firebase.notifications().android.createChannel(channel);

    _notificationListener = firebase.notifications().onNotification((notification) => {
      // Process your notification as required
      notification.android.setPriority(firebase.notifications.Android.Priority.Max);
      notification.android.setChannelId(CHANNEL_ID);

      firebase.notifications().displayNotification(notification);
    });
    _notificationDisplayedListener = firebase.notifications().onNotificationDisplayed(() => {});
    _notificationOpenedListener = firebase
      .notifications()
      .onNotificationOpened((notificationOpen) => {
        if (onNotificationOpened && typeof onNotificationOpened === 'function') {
          onNotificationOpened(notificationOpen.notification.data);
        }
      });
  };

  const _registerToken = async (fcmToken: string): Promise<void> => {
    console.log(fcmToken);
    // try {
    //   const deviceUniqueId = DeviceInfo.getUniqueId();
    //   const token = await AsyncStorage.getItem('token');
    //   await Axios.post(
    //     `URL`,
    //     {
    //       token: fcmToken,
    //       device_unique_id,
    //     },
    //     {
    //       headers: { Authorization: 'Bearer ' + token },
    //     },
    //   );
    // } catch (error) {
    //   console.log('ERROR: _registerToken');
    //   console.log(error.response.data);
    // }
  };

  const _registerTokenRefreshListener = (): void => {
    if (_onTokenRefreshListener) {
      _onTokenRefreshListener();
      _onTokenRefreshListener = undefined;
    }

    _onTokenRefreshListener = firebase.messaging().onTokenRefresh((fcmToken) => {
      // Process your token as required
      _registerToken(fcmToken);
    });
  };
  const _updateTokenToServer = async (): Promise<void> => {
    try {
      const fcmToken = await firebase.messaging().getToken();
      _registerMessageListener();
      _registerToken(fcmToken);
    } catch (error) {
      console.log('ERROR: _updateTokenToServer');
      console.log(error);
    }
  };

  const _requestPermission = async (): Promise<void> => {
    try {
      // User has authorised
      await firebase.messaging().requestPermission();
      await _updateTokenToServer();
    } catch (error) {
      // User has rejected permissions
      Alert.alert("you can't handle push notification");
    }
  };

  const _checkPermission = async (): Promise<void> => {
    try {
      const enabled = await firebase.messaging().hasPermission();
      if (enabled) {
        // user has permissions
        _updateTokenToServer();
        _registerTokenRefreshListener();
      } else {
        // user doesn't have permission
        _requestPermission();
      }
    } catch (error) {
      console.log('ERROR: _checkPermission', error);
      console.log(error);
    }
  };

  useEffect(() => {
    _checkPermission();
    return (): void => {
      if (_onTokenRefreshListener) {
        _onTokenRefreshListener();
        _onTokenRefreshListener = undefined;
      }
      if (_notificationDisplayedListener) {
        _notificationDisplayedListener();
        _notificationDisplayedListener = undefined;
      }
      if (_notificationListener) {
        _notificationListener();
        _notificationListener = undefined;
      }
      if (_notificationOpenedListener) {
        _notificationOpenedListener();
        _notificationOpenedListener = undefined;
      }
    };
  }, []);

  if (Platform.OS === 'ios') {
    firebase.notifications().setBadge(0);
  }

  return children;
};

export default FCMContainer;

You should change Channel ID, App Name and Description to fit yours.

const CHANNEL_ID = 'io.github.dev.yakuza.poma';
const APP_NAME = 'POMA';
const DESCRIPTION = 'POMA channel';

Alos, For testing, just disply FCM token on the log,

const _registerToken = async (fcmToken: string): Promise<void> => {
  console.log(fcmToken);
  // try {
  //   const deviceUniqueId = DeviceInfo.getUniqueId();
  //   const token = await AsyncStorage.getItem('token');
  //   await Axios.post(
  //     `URL`,
  //     {
  //       token: fcmToken,
  //       device_unique_id,
  //     },
  //     {
  //       headers: { Authorization: 'Bearer ' + token },
  //     },
  //   );
  // } catch (error) {
  //   console.log('ERROR: _registerToken');
  //   console.log(error.response.data);
  // }
};

For production, You should make this part to send FCM Token to the server via API.

To use the source code above, open App.tsx file and modify it like below.

import React from 'react';
import FCMContainer from '~/Component/FCMContainer';

const App = (): JSX.Element => {
  return (
    <FCMContainer>
      ...
    </FCMContainer>
  );
};

export default App;

iOS test

To test FCM on iOS, we need a device. Connect the device to the PC, and open Xcode.

iOS FCM test - select device

Select the device on the left tope menu, and clic > button to execute the project.

iOS FCM test - permission

After executing the app on the device, you can see the screen like above. Click Allow button.

iOS FCM test - get token

After allowing, you can see the FCM token on the console. copy the Token key.

Next, go to Firebase Console, click Cloud Messaging on the left menu, and Send your first message button.

ios FCM test - Firebase console

When the next screen is shown up, insert a test message to Notification title and Notification text. After inserting, click Send test message.

ios FCM test - insert message

When the screen below is shown up, paste the FCM Token which you copied above on the console to Add an FCM registration token, and click + button.

ios FCM test - insert token

Next, click Test button to send the message.

ios FCM test - send message

And then, you can see the screen like below that the app received the message well.

ios FCM test - receive message

Android test

Execute the command below to test FCM on Android.

npm run android

After executing, you can see the FCM Token on the console. copy the key.

Android FCM test - FCM token

Next, go to Firebase Console, and click Cloud Messaging menu on the left, and click Send your first message button.

Android FCM test - Firebase console

When the next screen is show up, insert a test message to Notification title and Notification text. After it, click Send test message button on the right side.

Android FCM test - insert message

When the screen blow is shown up, paste FCM token which you copied above to Add an FCM registration token, and click + button.

Android FCM test - insert token

And then, click Test button to send the test message.

Android FCM test - send message

And then, you can see the screen like below that the app received the message well.

Android FCM test - receive message

Completed

We’ve seen how to receive FCM message on React Native project by react-native-firebase library. You can implement the Push notification by saving the FCM token on the server, and send a message with the Token!

Posts