diff --git a/app/_layout.tsx b/app/_layout.tsx index 24fbd52..fe27f2f 100644 --- a/app/_layout.tsx +++ b/app/_layout.tsx @@ -1,8 +1,9 @@ import { Stack, useRouter } from 'expo-router'; import { useState, useEffect } from 'react'; +import { AppState } from 'react-native'; import { getForceUpdate, appVersion, versionToNumber } from '../services/forceupdate'; import * as Notifications from 'expo-notifications'; -import { registerForPushNotificationsAsync } from '../services/notifications'; +import { registerForPushNotificationsAsync, shouldRecheckPermission } from '../services/notifications'; import CookieManager from '@react-native-cookies/cookies'; Notifications.setNotificationHandler({ @@ -32,17 +33,33 @@ export default function RootLayout() { }, []); useEffect(() => { - if (!isReady) return; + const handleToken = (token?: string) => { + if (token) { + addTokenToCookie(token); + console.log('Expo Push Token:', token); + } + }; registerForPushNotificationsAsync() - .then((token) => { - if (token) { - addTokenToCookie(token); - console.log('Expo Push Token:', token); - } - }) + .then(handleToken) .catch((error: any) => console.error(error)); + const subscription = AppState.addEventListener('change', (nextAppState) => { + if (nextAppState === 'active' && shouldRecheckPermission()) { + registerForPushNotificationsAsync() + .then(handleToken) + .catch((error: any) => console.error(error)); + } + }); + + return () => { + subscription.remove(); + }; + }, []); + + useEffect(() => { + if (!isReady) return; + const response = Notifications.getLastNotificationResponse(); if (response?.notification) { const data = response.notification.request.content.data.path; diff --git a/services/notifications.ts b/services/notifications.ts index 46bf433..6f38bb8 100644 --- a/services/notifications.ts +++ b/services/notifications.ts @@ -1,7 +1,26 @@ -import { Platform } from 'react-native'; +import { Alert, Linking, Platform } from 'react-native'; import * as Device from 'expo-device'; import * as Notifications from 'expo-notifications'; import Constants from 'expo-constants'; +import { exitApp } from '@logicwind/react-native-exit-app'; + +let wentToSettings = false; + +const notificationPermissionAlert = () => + Alert.alert('알림 권한이 필요해요', '설정으로 이동해서 알림 권한을 허용해주세요.', [ + { + text: '앱 종료', + onPress: () => exitApp(), + style: 'cancel', + }, + { + text: '확인', + onPress: () => { + wentToSettings = true; + Linking.openSettings(); + }, + }, + ]); function handleRegistrationError(errorMessage: string) { console.error(errorMessage); @@ -24,7 +43,7 @@ export async function registerForPushNotificationsAsync() { finalStatus = status; } if (finalStatus !== 'granted') { - handleRegistrationError('Permission not granted to get push token for push notification!'); + notificationPermissionAlert(); return; } const projectId = @@ -47,3 +66,11 @@ export async function registerForPushNotificationsAsync() { handleRegistrationError('Must use physical device for push notifications'); } } + +export function shouldRecheckPermission() { + if (wentToSettings) { + wentToSettings = false; + return true; + } + return false; +}