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.
- In the Xcode menu, go to File > New > Target.
- Select the Notification Service Extension.
- 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 ,表示从后台进入了前台 ,请求数据,刷新页面。或者做其他的逻辑
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 ,表示从后台进入了前台 ,请求数据,刷新页面。或者做其他的逻辑
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;
}
}