리액트 네이티브 권한
리액트 네이티브에서 권한을 받는 코드는 보통 react-native-permissions 라는 의존성을 통해 구현한다.
그 이유는 안드로이드와 IOS 의 권한 체계가 다른데 그것을 각자 코딩하려면 너무 공수가 많이 들기 때문이다.
그럼에도 네이티브에서 수정해야되는 내용들이 꽤 있다.
IOS 네이티브 권한 설정
어떤 권한을 쓸지 명시해주기
ios/Podfile
내부에 아래와 같은 내용을 추가해주면 된다.
target 'FoodDeliveryApp' do
config = use_native_modules!
# Flags change depending on the env values.
flags = get_default_flags()
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"
권한을 얻을 때 메세지 설정하기
<key>NSCameraUsageDescription</key>
<string>배송완료 사진 촬영을 위해 카메라 권한이 필요합니다.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>배송중 위치 확인을 위해서 위치 권한이 필요합니다.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>배송중 위치 확인을 위해서 위치 권한이 필요합니다.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>배송중 위치 확인을 위해서 위치 권한이 필요합니다.</string>
<key>NSMotionUsageDescription</key>
<string>배송중 위치 확인을 위해서 위치 권한이 필요합니다.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>배송완료 사진 선택을 위해 라이브러리 접근 권한이 필요합니다.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>배송완료 사진 선택을 위해 라이브러리 접근 권한이 필요합니다.</string>
<key>CFBundleDevelopmentRegion</key>
안드로이드 네이티브 권한 설정
어떤 권한을 줄지 명시해주기
android/app/src/main/AndroidManifest.xml
에 작성해주면 된다.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.n00nietzsche.fooddeliveryapp">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.VIBRATE"/>
</manifest>
권한 받기 관련 Hooks 작성
import { useEffect } from "react";
import { Alert, Linking, Platform } from "react-native";
import { check, PERMISSIONS, request, RESULTS } from "react-native-permissions";
function usePermissions() {
// 권한 관련
// 파일명을 usePermissions.android.ts, usePermissions.ios.ts 와 같은 형식으로 디바이스별로 나누어도 되긴 한다.
useEffect(() => {
if (Platform.OS === "android") {
check(PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION)
.then((result) => {
console.log("check location", result);
if (result === RESULTS.BLOCKED || result === RESULTS.DENIED) {
Alert.alert(
"이 앱은 위치 권한 허용이 필요합니다.",
"앱 설정 화면을 열어서 항상 허용으로 바꿔주세요.",
[
{
text: "네",
// 여기서는 설정을 이용하지만, url 의 스킴을 이용해서 다른 앱으로 이동하는 것도 가능하다.
// ex) tel://01000000000 혹은 sms://01000000000
onPress: () => Linking.openSettings(),
},
{
text: "아니오",
onPress: () => console.log("No Pressed"),
style: "cancel",
},
]
);
}
})
.catch(console.error);
} else if (Platform.OS === "ios") {
check(PERMISSIONS.IOS.LOCATION_ALWAYS)
.then((result) => {
if (result === RESULTS.BLOCKED || result === RESULTS.DENIED) {
Alert.alert(
"이 앱은 백그라운드 위치 권한 허용이 필요합니다.",
"앱 설정 화면을 열어서 항상 허용으로 바꿔주세요.",
[
{
text: "네",
onPress: () => Linking.openSettings(),
},
{
text: "아니오",
onPress: () => console.log("No Pressed"),
style: "cancel",
},
]
);
}
})
.catch(console.error);
}
if (Platform.OS === "android") {
check(PERMISSIONS.ANDROID.CAMERA)
.then((result) => {
// GRANTED 를 넣은 이유는 ELSE 문으로 가지 않게 하기 위해서 넣었음.
// TODO: 사실 깔끔하게 만들기 위해서는 분리할 필요가 있음 if (alreadyGranted) return 과 같이...
if (result === RESULTS.DENIED || result === RESULTS.GRANTED) {
return request(PERMISSIONS.ANDROID.CAMERA);
} else {
console.log(result);
throw new Error("카메라 지원 안 함");
}
})
.catch(console.error);
} else {
check(PERMISSIONS.IOS.CAMERA)
.then((result) => {
if (
result === RESULTS.DENIED ||
result === RESULTS.LIMITED ||
result === RESULTS.GRANTED
) {
return request(PERMISSIONS.IOS.CAMERA);
} else {
console.log(result);
throw new Error("카메라 지원 안 함");
}
})
.catch(console.error);
}
}, []);
}
export default usePermissions;
앱 메인에서 사이드이펙트로 작동하도록 두면 된다.
기존 코드 출처
반응형
'리액트 네이티브 (React Native)' 카테고리의 다른 글
리액트 네이티브에서 티맵 사용하는 방법 (0) | 2022.10.22 |
---|---|
리액트 네이티브 이미지 첨부하기 (카메라, 갤러리) (0) | 2022.10.21 |
리액트 네이티브에 네이버 맵 넣기 (0) | 2022.10.19 |
React-Native 리덕스 리액트 실무 사용 패턴 (0) | 2022.10.19 |
리액트 네이티브(React Native) 에서 사용하는 스토리지 저장소 알아보기 (0) | 2022.10.12 |