2020/12/10 - [React Native] - [React Native] MAC/IOS 알람 구현하기 1(Push notification)-firebase
[React Native] MAC/IOS 알람 구현하기 1(Push notification)-firebase
1. 프로젝트 생성 npx react-native init [파일명] 예를 들어 npx react-native init hyukpush 2. 모듈 다운 # Using npm npm install --save @react-native-firebase/app # Using Yarn yarn add @react-native-fi..
coding-hyeok.tistory.com
1. Install the messaging module
npm install --save @react-native-firebase/messaging
cd ios/ && pod install
2. install the react-native-push-notification module
npm install --save react-native-push-notification
npm install --save @react-native-community/push-notification-ios
3. @react-native-community/push-notification-ios 설정
xcode를 실행시켜서 appDelegate.h파일을 연다.
//제일 위에 추가
#import <UserNotifications/UNUserNotificationCenter.h>
//추가
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, UNUserNotificationCenterDelegate>
appDelegate.m
//제일 위에 추가
#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>
end if 뒤에 추가하면 된다.
// 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];
}
//아래코드도 추가
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
// Define UNUserNotificationCenter
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
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);
}
4. code
hyukpush
src 폴더내에 FCMService, LocalNotificationService.js 두개를 만들었다.
LocalNotificationService의 코드는 다음과 같다.
import PushNotification from 'react-native-push-notification';
import PushNotificationIOS from '@react-native-community/push-notification-ios';
import {Platform} from 'react-native';
class LocalNotificationService {
configure = (onOpenNotification) => {
PushNotification.configure({
onRegister: function (token) {
console.log(
'[LocalNotificationService] onRegister : localtoken',
token,
);
},
onNotification: function (notification) {
console.log('[LocalNotificationService] onNotification ', notification);
if (!notification?.data) {
return;
}
notification.userInteraction = true;
onOpenNotification(
Platform.OS === 'ios' ? notification.data.item : notification.data,
);
//Only call callback if not from foreground
if (Platform.OS === 'ios') {
// (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: true,
});
};
unRegister = () => {
PushNotification.unregister();
};
showNotification = (id, title, message, data = {}, options = {}) => {
PushNotification.localNotification({
// Android only Properties
...this.buildAndroidNotification(id, title, message, data, options),
// IOS and Android properties
...this.buildIOSNotification(id, title, message, data, options),
// IOS and Android properties
title: title || '',
message: message || '',
playSound: options.playSound || false,
soundName: options.soundName || 'default',
userInteraction: false, //BOOLEAN : If the notification was opend by the user from notification area or not
});
};
buildAndroidNotification = (id, title, message, data = {}, options = {}) => {
return {
id: id,
authCancel: true,
largeIcon: options.largeIcon || 'ic_launcher',
smallIcon: options.smallIcon || 'ic_notification',
bigText: message || '',
subText: title || '',
vibrate: options.vibrate || true,
vibration: options.vibration || 300,
priority: options.priority || 'high',
importance: options.importance || 'high', // (optional) set notification importance, default : ??~
data: data,
};
};
buildIOSNotification = (id, title, message, data = {}, options = {}) => {
return {
alertAction: options.alertAction || 'view',
category: options.category || '',
userInfo: {
id: id,
item: data,
},
};
};
cancelAllLocalNotifications = () => {
if (Platform.OS === 'ios') {
PushNotificationIOS.removeAllDeliveredNotifications();
} else {
PushNotification.cancelAllLocalNotifications();
}
};
removeDeliveredNotificationByID = (notification) => {
console.log(
'[LocalNotificationService] removeDeliveredNotificationByID:',
notification,
);
PushNotification.cancelLocalNotifications({id: `${notificationId}`});
};
}
export const localNotificationService = new LocalNotificationService();
FCMService.js
import messaging from '@react-native-firebase/messaging';
import {Platform} from 'react-native';
class FCMService {
register = (onRegister, onNotification, onOpenNotification) => {
this.checkPermission(onRegister);
this.createNotificationListeners(
onRegister,
onNotification,
onOpenNotification,
);
};
registerAppWithFCM = async () => {
if (Platform.OS === 'ios') {
// await messaging().registerDeviceForRemoteMessages();
await messaging().setAutoInitEnabled(true);
}
};
checkPermission = (onRegister) => {
messaging()
.hasPermission()
.then((enabled) => {
if (enabled) {
//User has permission
this.getToken(onRegister);
} else {
//User doesn't have permission
this.requestPermission(onRegister);
}
})
.catch((error) => {
console.log('[FCMService] Permission rejected ', error);
});
};
getToken = (onRegister) => {
messaging()
.getToken()
.then((fcmToken) => {
if (fcmToken) {
onRegister(fcmToken);
} else {
console.log('[FCMService] User does not have a device token');
}
})
.catch((error) => {
console.log('[FCMService] getToken rejected', error);
});
};
requestPermission = (onRegister) => {
messaging()
.requestPermission()
.then(() => {
this.getToken(onRegister);
})
.catch((error) => {
console.log('[FCMService] Request Permission rejected', error);
});
};
deleteToken = () => {
console.log('[FCMService] deleteToken');
messaging()
.deleteToken()
.catch((error) => {
console.log('[FCMService] Delete token error', error);
});
};
createNotificationListeners = (
onRegister,
onNotification,
onOpenNotification,
) => {
//실행중이지만 현재화면은 다른 앱이 실행중이거나 아무것도 실행하지않을때
messaging().onNotificationOpenedApp((remoteMessage) => {
console.log(
'[FCMService] onNotificationOpenApp Notification caused app to open from background',
remoteMessage,
);
if (remoteMessage) {
const notification = remoteMessage.notification;
onOpenNotification(notification);
//this.removeDeliveredNotification(Notification.NotificationId)
} else {
console.log('background notification error', error);
}
alert(remoteMessage.body);
});
//Check whether an initial notification is available
//앱이 실행중이 아닐때
messaging()
.getInitialNotification()
.then((remoteMessage) => {
console.log(
'[FCMService] getInitialNotification casued app to open from quit state : fcmremoteMessage :',
remoteMessage,
);
if (remoteMessage) {
const notification = remoteMessage.notification;
onOpenNotification(notification);
//this.removeDeliveredNotification(notification.notificationId)
} else {
console.log('quit state notification error : ', error);
}
});
//실행중이고 현재 화면일때
this.messageListener = messaging().onMessage(async (remoteMessage) => {
console.log('[FCMService] A new FCM message arrived', remoteMessage);
if (remoteMessage) {
let notification = null;
if (Platform.OS === 'ios') {
notification = remoteMessage.data.notification;
} else {
notification = remoteMessage.notification;
}
onNotification(notification);
}
});
//Triggerd when have new token
messaging().onTokenRefresh((fcmToken) => {
console.log('[FCMService] New token refresh :', fcmToken);
onRegister(fcmToken);
});
};
unRegister = () => {
this.messageListener();
};
}
export const fcmService = new FCMService();
App.js
import React, {useEffect, useState} from 'react';
import {Text, StyleSheet, View, Button} from 'react-native';
import {fcmService} from './src/FCMService';
import {localNotificationService} from './src/LocalNotificationService';
export default function App() {
useEffect(() => {
fcmService.registerAppWithFCM();
fcmService.register(onRegister, onNotification, onOpenNotification);
localNotificationService.configure(onOpenNotification);
function onRegister(token) {
console.log('[App] onRegister : token :', token);
}
function onNotification(notify) {
console.log('[App] onNotification : notify :', notify);
const options = {
soundName: 'default',
playSound: true,
};
localNotificationService.showNotification(
0,
notify.title,
notify.body,
notify,
options,
);
}
function onOpenNotification(notify) {
console.log('[App] onOpenNotification : notify :', notify);
alert('Open Notification : notify.body :' + notify.body);
}
return () => {
console.log('[App] unRegister');
fcmService.unRegister();
localNotificationService.unregister();
};
}, []);
return (
<View style={styles.container}>
<Text>Push Test</Text>
<Button title="Test" onPress={() => alert('remoteMessage')} />
<Button
title="Press"
onPress={() => localNotificationService.cancelAllLocalNotifications()}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
index.js
/**
* @format
*/
import React from 'react';
import {AppRegistry} from 'react-native';
import App from './App';
import {name as hyukpush} from './app.json';
import messaging from '@react-native-firebase/messaging';
messaging().setBackgroundMessageHandler(async (remoteMessage) => {
console.log('Message handled in the background!', remoteMessage);
});
function HeadlessCheck({isHeadless}) {
if (isHeadless) {
// App has been launched in the background by iOS, ignore
return null;
}
return <App />;
}
AppRegistry.registerComponent(hyukpush, () => HeadlessCheck);
hyukpush 부분을 각자의 appname으로 바꿔줘야한다.
android와 다르게 ios는 애뮬레이터로 테스트가 안된다. 테스트를 하려면 apple developer에 가입하고 Device, key, identifier, certificate, profile을 등록해줘야지 테스트를 할 수 있다.
다음에 해보자
모두들 열코!!
참고사이트
github.com/zo0r/react-native-push-notification
zo0r/react-native-push-notification
React Native Local and Remote Notifications. Contribute to zo0r/react-native-push-notification development by creating an account on GitHub.
github.com
github.com/react-native-push-notification-ios/push-notification-ios
react-native-push-notification-ios/push-notification-ios
React Native Push Notification API for iOS. Contribute to react-native-push-notification-ios/push-notification-ios development by creating an account on GitHub.
github.com
Cloud Messaging | React Native Firebase
Installation and getting started with Cloud Messaging.
rnfirebase.io
'React Native' 카테고리의 다른 글
[React Native] 바텀 내비게이션 및 스플래쉬화면 적용하기! (2) | 2020.12.28 |
---|---|
[React Native] MAC/IOS 알람 구현하기 3(Push notification)-firebase (5) | 2020.12.10 |
[React Native] Android 알람 구현하기 2(Push notification)-firebase (0) | 2020.12.10 |
[React Native] MAC/IOS 알람 구현하기 1(Push notification)-firebase (0) | 2020.12.10 |
[React Native] Android 알람 구현하기 1(Push notification)-firebase (0) | 2020.12.10 |