티스토리 뷰

반응형

 

안녕하세요. 오늘은 리엑트 네이티브에서 앱 디바이스 설정 창을 여는 방법에 대해 소개하겠습니다.

 

해당 기능은 유저가 어플리케이션의 알림 상태를 동의하지 않았을 경우 해당 애플리케이션 설정 창에서 알림을 허용하는 액션이 필요할 때와 같은 경우에 사용할 수 있습니다. 

 

설정 후 다시 앱에 돌아왔을 때 동의 유무에 따른 분기처리 방법도 같이 말씀드리고자 합니다. 

 

 


 

앱 설정 창 열기

 

앱 설정을 여는 것은 기본적으로 Linking에서 openSetting이라는 메서드를 제공합니다. 

import { Linking } from 'react-native';

Linking.openSettings();

 

 

저 같은 경우는 유저가 알림설정을 했는지 안 했는지에 따라서 스크린 분기 처리가 필요했는데요.

설정을 한 후 다시 앱에 돌아갔을 때 유저가 알림설정을 허용했기 때문에 다른 스크린을 보여줘야 하지만 렌더링이 발생하지 않아 앱 알림을 허용하기 전에 보여줘야 할 스크린과 같게 됩니다. 

 

그래서 앱 밖에서 앱 내로 들어왔다는 상태값을 감지할 필요가 있는데요. 이는 React-native에서 제공하는 AppState를 사용하면 됩니다. 

 

 

AppState : AppStateStatic

AppState는 AppStateStatic이라는 인터페이스를 가집니다. 가지고 있는 properties와 method를 응용하여 app 상태를 감지할 수 있습니다.

export type AppStateEvent = 'change' | 'memoryWarning' | 'blur' | 'focus';
export type AppStateStatus = 'active' | 'background' | 'inactive' | 'unknown' | 'extension';

export interface AppStateStatic {
    currentState: AppStateStatus;
    isAvailable: boolean;
    addEventListener(type: AppStateEvent, listener: (state: AppStateStatus) => void): NativeEventSubscription;
    removeEventListener(type: AppStateEvent, listener: (state: AppStateStatus) => void): void;
}

 

 

아래와 같은 코드를 통해 현재 App 상태를 상태 값으로 관리할 수 있게 됩니다. appStateVisible==='active'인 상태가 app에 접속한 상태가 됩니다.

import React, { useRef, useState, useEffect } from "react";
import { AppState } from "react-native";


const Example = () => {
   const appState = useRef(AppState.currentState);
   const [appStateVisible, setAppStateVisible] = useState(appState.current); 
  
   React.useEffect(() => {
    // appState 변화 구독
    const subscription = AppState.addEventListener('change', (nextAppState) => {\
      // 앱 현재 상태에 감지된 state 넣기
      appState.current = nextAppState;
      // 상태값에 현재 상태 넣기
      setAppStateVisible(appState.current);
    });
    // 구독 해지
    return () => {
      subscription.remove();
    };
  }, []);
  
   return (
   ..
   )
}

export default Example;

 

 

저는 유저가 앱 알림설정을 했는지 안 했는지에 대한 유무 사이드 이펙트에서 가져왔는데요. authStatus === ture 라면 유저가 앱 알림 설정을 허용한 상태입니다. 

 

의존성 배열에 appState와 유저의 알림설정 허용 유무에 대한 상태를 넣고 appState가 active인 상태가 아니라면 리턴 시켜 active인 경우에만 해당 값을 setState 해줍니다. 

 

  React.useEffect(() => {
    if (appStateVisible !== 'active') return;
    async function checkPermissionStatus() {
      const authStatus = await getHasPermission();
      setIsAuthorizedNotifications(!!authStatus);
    }
    checkPermissionStatus();
  }, [getHasPermission, appStateVisible]);

 

 

결론적으로 유저가 background에있는지 app안에 있는지 감지가 되어 앱 설정에서 알림을 허용하거나 해제하고 바로 앱으로 돌아왔을 시에 해당 스크린이 리랜더링 되면서 분기 처리에 맞는 스크린이 보여지게 됩니다.

const ExampleScreen = () => {
  const [isAuthorizedNotifications, setIsAuthorizedNotifications] =
    React.useState<boolean | null>(null);

.
.
.
  return (
    <CommonLayout h={'100%'} px={'16px'} bgColor={'#FFFFFF'}>
      {isAuthorizedNotifications ? (
        <AuthorizedNotiScreen />
      ) : (
        <UnAuthorizedNotiScreen />
      )}
    </CommonLayout>
  );
}

export default ExampleScreen;

 

 

 


 

 

전체 코드 

import React from 'react';
import { AppState } from 'react-native';

const ExampleScreen = () => {
  const appState = React.useRef(AppState.currentState);
  const [appStateVisible, setAppStateVisible] = React.useState(
    appState.current,
  );
  const { getHasPermission } = useFCMPermissionService();

  const [isAuthorizedNotifications, setIsAuthorizedNotifications] =
    React.useState<boolean | null>(null);

  React.useEffect(() => {
    const subscription = AppState.addEventListener('change', (nextAppState) => {
      appState.current = nextAppState;
      setAppStateVisible(appState.current);
    });
    return () => {
      subscription.remove();
    };
  }, []);

  React.useEffect(() => {
    if (appStateVisible !== 'active') return;
    async function checkPermissionStatus() {
      const authStatus = await getHasPermission();
      setIsAuthorizedNotifications(!!authStatus);
    }
    checkPermissionStatus();
  }, [getHasPermission, appStateVisible]);

  return (
    <CommonLayout h={'100%'} px={'16px'} bgColor={'#FFFFFF'}>
      {isAuthorizedNotifications ? (
        <AuthorizedNotiScreen />
      ) : (
        <UnAuthorizedNotiScreen />
      )}
    </CommonLayout>
  );
}

export default ExampleScreen;

 

 

 

 


 

Reference

React native Linking

React native AppState

반응형