반응형
** 모든 과정은 google play console 과 apple developer 결제 완료 및 project 등록 후 진행한 내용입니다.
개요
기기 정보와 Firebase Cloud Messaging(FCM) 또는 Apple Push Notification Service(APNs)와의 통신에 대한 모든 것이 백그라운드에서 처리된다.
먼저, 내 기기에서 backend 서버로 알림 요청을 보내면 expo push token 이용하여 Expo backend로 푸시알림을 받는다.
android는 Firebase Cloud Messaging(FCM) ios는 Apple Push Notification Service(APNs)이용하여 알림 전송한다.
설정 과정
https://docs.expo.dev/push-notifications/push-notifications-setup/
프론트엔드
- 라이브러리 설치
- 알림을 처리하는 함수를 구현
- Android 및 iOS에 대한 자격 증명을 설정하여 앱을 구성
- expo dev 통해서 테스트
1. 라이브러리 설치
$ npx expo install expo-notifications expo-device expo-constants
- 라이브러리는 사용자의 권한을 요청하고 ExpoPushToken을 가져오는 데 사용. Android 에뮬레이터나 iOS 시뮬레이터에서는 지원되지 않음.
- 앱이 물리적 장치에서 실행되고 있는지 확인하는 데 사용
- projectId앱 구성에서 값을 가져오는 데 사용
2. 함수 구현
import { useState, useEffect, useRef } from 'react';
import { Text, View, Button, Platform } from 'react-native';
import * as Device from 'expo-device';
import * as Notifications from 'expo-notifications';
import Constants from 'expo-constants';
// Notification initialize
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: false,
}),
});
// send 하는 함수
async function sendPushNotification(expoPushToken: string) {
const message = {
to: expoPushToken,
sound: 'default',
title: 'Original Title',
body: 'And here is the body!',
data: { someData: 'goes here' },
};
await fetch('https://exp.host/--/api/v2/push/send', {
method: 'POST',
headers: {
Accept: 'application/json',
'Accept-encoding': 'gzip, deflate',
'Content-Type': 'application/json',
},
body: JSON.stringify(message),
});
}
function handleRegistrationError(errorMessage: string) {
alert(errorMessage);
throw new Error(errorMessage);
}
async function registerForPushNotificationsAsync() {
if (Platform.OS === 'android') {
Notifications.setNotificationChannelAsync('default', {
name: 'default',
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: '#FF231F7C',
});
}
if (Device.isDevice) {
const { status: existingStatus } = await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== 'granted') {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== 'granted') {
handleRegistrationError('Permission not granted to get push token for push notification!');
return;
}
const projectId =
Constants?.expoConfig?.extra?.eas?.projectId ?? Constants?.easConfig?.projectId;
if (!projectId) {
handleRegistrationError('Project ID not found');
}
try {
const pushTokenString = (
await Notifications.getExpoPushTokenAsync({
projectId,
})
).data;
console.log(pushTokenString);
return pushTokenString;
} catch (e: unknown) {
handleRegistrationError(`${e}`);
}
} else {
handleRegistrationError('Must use physical device for push notifications');
}
}
export default function App() {
const [expoPushToken, setExpoPushToken] = useState('');
const [notification, setNotification] = useState<Notifications.Notification | undefined>(
undefined
);
const notificationListener = useRef<Notifications.Subscription>();
const responseListener = useRef<Notifications.Subscription>();
useEffect(() => {
registerForPushNotificationsAsync()
.then(token => setExpoPushToken(token ?? ''))
.catch((error: any) => setExpoPushToken(`${error}`));
notificationListener.current = Notifications.addNotificationReceivedListener(notification => {
setNotification(notification);
});
responseListener.current = Notifications.addNotificationResponseReceivedListener(response => {
console.log(response);
});
return () => {
notificationListener.current &&
Notifications.removeNotificationSubscription(notificationListener.current);
responseListener.current &&
Notifications.removeNotificationSubscription(responseListener.current);
};
}, []);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'space-around' }}>
<Text>Your Expo push token: {expoPushToken}</Text>
<View style={{ alignItems: 'center', justifyContent: 'center' }}>
<Text>Title: {notification && notification.request.content.title} </Text>
<Text>Body: {notification && notification.request.content.body}</Text>
<Text>Data: {notification && JSON.stringify(notification.request.content.data)}</Text>
</View>
<Button
title="Press to Send Notification"
onPress={async () => {
await sendPushNotification(expoPushToken);
}}
/>
</View>
);
}
3. OS 별 자격 증명 설정
Android
https://docs.expo.dev/push-notifications/fcm-credentials/
- Firebase console > Project settings > Service accounts
- firbase admin SDK > new key 생성 > download .json file
- Upload the JSON file to EAS and configure it for sending Android notifications. This can be done using EAS CLI or in Expo dashboard.
- 두가지 방법 중 필자는 cli를 활용하는 방법 채택, 해당 파일을 root directory 에 옮긴 뒤 아래 순서로 실행
- Run eas credentials
- Select Android > production > Google Service Account
- Select Manage your Google Service Account Key for Push Notifications (FCM V1)
- Select Set up a Google Service Account Key for Push Notifications (FCM V1) > Upload a new service account key
- If you've previously stored the JSON file in your project directory, the EAS CLI will automatically detect the file and prompt you to select it. Press to continue. → Y
- google-services.json file in your project. Download it from the Firebase Console and place it at the root of your project directory.
- In app.json, add expo.android.googleServicesFile with its value as the path of the google-services.json.
{
"expo": {
...
"android": {
... "googleServicesFile": "./path/to/google-services.json"
}
}
}
iOS
iOS의 경우, eas build 로 서비스키를 생성할 수 있다.
처음으로 개발 빌드를 만들면 푸시 알림을 활성화하라는 메시지가 표시된다. 그러면 EAS CLI에서 다음 질문에 y 로 선택한다.
- Setup Push Notifications for your project
- Generating a new Apple Push Notifications service key
다음에는 백엔드에서 expo push 이용하여 알림 보내는 방법에 대해 포스팅해보겠다.
반응형
'React Native' 카테고리의 다른 글
[React Native] Upgrade Expo SDK 49→51 (2) | 2024.09.26 |
---|---|
[React Native] Expo Push Notification - API Server (0) | 2024.09.20 |
[React Native] react native 작동 원리 (0) | 2024.04.05 |
[React Native] Expo prebuild (0) | 2023.12.11 |
[React Native] ios, android 폰트 설정 (2) | 2023.12.04 |
댓글