React native permissions 라이브러리를 통해서 현재 기기에서 권한이 허용되었는지 여부를 체크할 수 있습니다.
안드로이드에서는 React native에 내장된 PermissionsAndroid 를 사용하는 방법도 있습니다.
IOS는 React native 공식문서에 따로 기재되어있지 않아서 공통적으로 권한 관리를 하기 위해서 react native permissions을 사용하도록 하겠습니다.
npm i react-native-permissions
[git] : https://www.npmjs.com/package/react-native-permissions
npx pod install
을 한번 쳐준다.
📄 Podfile
카메라 권한
- Permission-Camera
현재 위치 사용할때만 권한
- LocationWhenInUse
현재 위치 항상 권한
- LocationAlways
현재 위치 정확하게
- LocationAccuracy
푸쉬 알림
- Notifications
사진 라이브러리
- PhotoLibrary
target '나의앱이름' do
# …
permissions_path = '../node_modules/react-native-permissions/ios'
# 🚨 앱에서 사용하는 허용 권한만 추가해줍니다. 🚨
pod 'Permission-AppTrackingTransparency', :path => "#{permissions_path}/AppTrackingTransparency"
pod 'Permission-BluetoothPeripheral', :path => "#{permissions_path}/BluetoothPeripheral"
pod 'Permission-Calendars', :path => "#{permissions_path}/Calendars"
pod 'Permission-Camera', :path => "#{permissions_path}/Camera"
pod 'Permission-Contacts', :path => "#{permissions_path}/Contacts"
pod 'Permission-FaceID', :path => "#{permissions_path}/FaceID"
pod 'Permission-LocationAccuracy', :path => "#{permissions_path}/LocationAccuracy"
pod 'Permission-LocationAlways', :path => "#{permissions_path}/LocationAlways"
pod 'Permission-LocationWhenInUse', :path => "#{permissions_path}/LocationWhenInUse"
pod 'Permission-MediaLibrary', :path => "#{permissions_path}/MediaLibrary"
pod 'Permission-Microphone', :path => "#{permissions_path}/Microphone"
pod 'Permission-Motion', :path => "#{permissions_path}/Motion"
pod 'Permission-Notifications', :path => "#{permissions_path}/Notifications"
pod 'Permission-PhotoLibrary', :path => "#{permissions_path}/PhotoLibrary"
pod 'Permission-PhotoLibraryAddOnly', :path => "#{permissions_path}/PhotoLibraryAddOnly"
pod 'Permission-Reminders', :path => "#{permissions_path}/Reminders"
pod 'Permission-Siri', :path => "#{permissions_path}/Siri"
pod 'Permission-SpeechRecognition', :path => "#{permissions_path}/SpeechRecognition"
pod 'Permission-StoreKit', :path => "#{permissions_path}/StoreKit"
end
📄 Info.plist
사용자에게 그 권한이 왜 필요한지 설명하는 부분이다.
(내용이 없을 경우 출시시 거절 당할수 있다.)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- 🚨 앱에서 사용하는 허용 권한만 추가해줍니다. 🚨 -->
<key>NSAppleMusicUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSCalendarsUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSCameraUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSContactsUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSFaceIDUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSLocationTemporaryUsageDescriptionDictionary</key>
<dict>
<key>YOUR-PURPOSE-KEY</key>
<string>YOUR TEXT</string>
</dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSMicrophoneUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSMotionUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSRemindersUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSSiriUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSUserTrackingUsageDescription</key>
<string>YOUR TEXT</string>
<!-- … -->
</dict>
</plist>
📄 AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myawesomeapp">
<!-- 🚨 앱에서 사용하는 허용 권한만 추가해줍니다. 🚨 -->
<uses-permission android:name="android.permission.ACCEPT_HANDOVER" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BODY_SENSORS" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_MMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECEIVE_WAP_PUSH" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.USE_SIP" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" />
<!-- … -->
</manifest>
📄 iOS flow
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ check(PERMISSIONS.IOS.CAMERA) ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
│
Is the feature available
on this device ?
│ ╔════╗
├───────────║ NO ║──────────────┐
│ ╚════╝ │
╔═════╗ ▼
║ YES ║ ┌─────────────────────┐
╚═════╝ │ RESULTS.UNAVAILABLE │
│ └─────────────────────┘
Is the permission
requestable ?
│ ╔════╗
├───────────║ NO ║──────────────┐
│ ╚════╝ │
╔═════╗ ▼
║ YES ║ ┌───────────────────┐
╚═════╝ │ RESULTS.BLOCKED / │
│ │ RESULTS.LIMITED / │
│ │ RESULTS.GRANTED │
▼ └───────────────────┘
┌────────────────┐
│ RESULTS.DENIED │
└────────────────┘
│
▼
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ request(PERMISSIONS.IOS.CAMERA) ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
│
Does the user accept
the request ?
│ ╔════╗
├───────────║ NO ║──────────────┐
│ ╚════╝ │
╔═════╗ ▼
║ YES ║ ┌─────────────────┐
╚═════╝ │ RESULTS.BLOCKED │
│ └─────────────────┘
▼
┌─────────────────┐
│ RESULTS.GRANTED │
└─────────────────┘
📄 Android flow
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ check(PERMISSIONS.ANDROID.CAMERA) ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
│
Is the feature available
on this device ?
│ ╔════╗
├───────────║ NO ║──────────────┐
│ ╚════╝ │
╔═════╗ ▼
║ YES ║ ┌─────────────────────┐
╚═════╝ │ RESULTS.UNAVAILABLE │
│ └─────────────────────┘
Is the permission
already granted ?
│ ╔═════╗
├───────────║ YES ║─────────────┐
│ ╚═════╝ │
╔════╗ ▼
║ NO ║ ┌───────────────────┐
╚════╝ │ RESULTS.GRANTED │
│ └───────────────────┘
▼
┌────────────────┐
│ RESULTS.DENIED │◀──────────────────────┐
└────────────────┘ │
│ │
▼ │
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ╔═════╗
┃ request(PERMISSIONS.ANDROID.CAMERA) ┃ ║ YES ║
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ╚═════╝
│ │
Does the user accept │
the request ? │
│ ╔════╗ Is the permission
├───────────║ NO ║──── still requestable ?
│ ╚════╝ │
╔═════╗ ╔════╗
║ YES ║ ║ NO ║
╚═════╝ ╚════╝
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ RESULTS.GRANTED │ │ RESULTS.BLOCKED │
└─────────────────┘ └─────────────────┘
✔️ 권한 세팅을 이미 한 경우에 (이미 권한을 차단 했을때 / 이미 권한을 허용한 경우) 아래 값들이 리턴된다.
이 경우에는 사용자가 수동으로 권한 세팅을 할수 있도록 ALERT를 띄워 주도록 한다.
✔️ 권한을 아직 세팅 하지 않은 경우 아래 값이 리턴되며 권한 요청을 보내면 된다.
의 값들이 리턴되며 만약 이 경우에도 RESULTS.BLOCKED일 경우 방금 권한이 차단되었으며 사용자가 수동으로 권한 허용 하도록 ALERT를 띄워준다.
권한 정리
check에서 RESULTS.DENIED가 뜨면 그때 request 권한요청을 하면 된다.
import { Platform } from "react-native";
import { PERMISSIONS, RESULTS, request } from "react-native-permissions";
useEffect(() => {
const permissionCheck = () => {
if (Platform.OS !== "ios" && Platform.OS !== "android") return;
const platformPermissions =
Platform.OS === "ios"
? PERMISSIONS.IOS.CAMERA
: PERMISSIONS.ANDROID.CAMERA;
const requestCameraPermission = async () => {
try {
const result = await request(platformPermissions);
result === RESULTS.GRANTED
? setOpenScanner(true)
: Alert.alert("카메라 권한을 허용해주세요");
} catch (err) {
Alert.alert("Camera permission err");
console.warn(err);
}
};
requestCameraPermission();
};
}, []);
참고
https://flamingotiger.github.io/frontend/ReactNative/react-native-permissions/