22. Разрешения (Permissions)
iOS и Android требуют явного разрешения для камеры, геолокации, уведомлений и т.д.
Location
Заголовок раздела «Location»npx expo install expo-locationimport * as Location from 'expo-location';
async function getCurrentLocation() { const { status } = await Location.requestForegroundPermissionsAsync(); if (status !== 'granted') { Alert.alert('Нет доступа к геолокации'); return; }
const location = await Location.getCurrentPositionAsync({ accuracy: Location.Accuracy.High, }); console.log(location.coords.latitude, location.coords.longitude);}
// Слежение за местоположениемconst subscription = await Location.watchPositionAsync( { accuracy: Location.Accuracy.High, timeInterval: 5000, distanceInterval: 10 }, (location) => console.log('Новая позиция:', location.coords));subscription.remove(); // Очисткаimport { CameraView, useCameraPermissions } from 'expo-camera';
function CameraScreen() { const [permission, requestPermission] = useCameraPermissions();
if (!permission?.granted) { return <Button title="Разрешить камеру" onPress={requestPermission} />; }
return <CameraView style={{ flex: 1 }} facing="back" />;}QR Scanner
Заголовок раздела «QR Scanner»<CameraView style={{ flex: 1 }} onBarcodeScanned={({ data, type }) => { console.log('Scanned:', data, type); }} barcodeScannerSettings={{ barcodeTypes: ['qr', 'code128'] }}/>Media Library & Image Picker
Заголовок раздела «Media Library & Image Picker»import * as ImagePicker from 'expo-image-picker';
const pickImage = async () => { const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync(); if (status !== 'granted') return;
const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, allowsEditing: true, aspect: [4, 3], quality: 0.8, });
if (!result.canceled) setImage(result.assets[0].uri);};Разрешения в app.json
Заголовок раздела «Разрешения в app.json»{ "expo": { "ios": { "infoPlist": { "NSCameraUsageDescription": "Для сканирования QR-кодов", "NSLocationWhenInUseUsageDescription": "Для отображения карты", "NSPhotoLibraryUsageDescription": "Для загрузки аватара" } }, "android": { "permissions": [ "CAMERA", "ACCESS_FINE_LOCATION", "READ_EXTERNAL_STORAGE" ] } }}При отказе — предложить Настройки
Заголовок раздела «При отказе — предложить Настройки»import { Linking, Alert } from 'react-native';
const handleDenied = () => { Alert.alert( 'Нет доступа', 'Откройте Настройки и разрешите доступ к камере', [ { text: 'Отмена', style: 'cancel' }, { text: 'Настройки', onPress: () => Linking.openSettings() }, ] );};