Урок 01

Разрешения и приватность

Мобильные приложения запрашивают разрешения: камера, геолокация, контакты, уведомления. Правильная работа с ними — обязательна.

Зачем разрешения

Операционная система защищает пользователя. Приложение не может получить доступ к камере или геолокации без явного согласия. Это требование Apple и Google — без него приложение не пропустят в сторах.

Запрос разрешения

Expo предоставляет универсальный API:

import * as ImagePicker from 'expo-image-picker';

async function pickImage() {
    const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();

    if (status !== 'granted') {
        Alert.alert('Нет доступа', 'Разрешите доступ к галерее в настройках');
        return;
    }

    const result = await ImagePicker.launchImageLibraryAsync();
    if (!result.canceled) {
        setImage(result.assets[0].uri);
    }
}

Проверка без запроса

const { status } = await ImagePicker.getMediaLibraryPermissionsAsync();

if (status === 'undetermined') {
    // ещё не спрашивали
} else if (status === 'granted') {
    // разрешено
} else if (status === 'denied') {
    // отказано
}

Открыть настройки

Если пользователь отказал:

import * as Linking from 'expo-linking';

Linking.openSettings();

Описание в app.json

iOS требует описание, зачем нужно разрешение:

{
    "expo": {
        "ios": {
            "infoPlist": {
                "NSCameraUsageDescription": "Приложение использует камеру для фото профиля",
                "NSPhotoLibraryUsageDescription": "Приложение открывает галерею для выбора фото",
                "NSLocationWhenInUseUsageDescription": "Приложение показывает ближайшие точки на карте"
            }
        },
        "android": {
            "permissions": ["CAMERA", "READ_MEDIA_IMAGES", "ACCESS_FINE_LOCATION"]
        }
    }
}

Без описания iOS-приложение крашится при запросе.

Основные разрешения

  • Камера — expo-camera
  • Галерея — expo-image-picker
  • Геолокация — expo-location
  • Контакты — expo-contacts
  • Уведомления — expo-notifications
  • Микрофон — expo-av
  • Календарь — expo-calendar

Хук usePermission

function usePermission(requestFn: () => Promise<{ status: string }>) {
    const [status, setStatus] = useState<'undetermined' | 'granted' | 'denied'>('undetermined');

    async function request() {
        const { status } = await requestFn();
        setStatus(status as 'granted' | 'denied');
        return status;
    }

    return { status, request };
}

Приватность

  • Не запрашивай разрешения заранее — только когда нужно
  • Объясняй, зачем нужно разрешение
  • Не используй данные без согласия
  • Храни персональные данные безопасно

App Tracking Transparency (iOS)

Для рекламы и трекинга:

import { requestTrackingPermissionsAsync } from 'expo-tracking-transparency';

const { status } = await requestTrackingPermissionsAsync();

Без разрешения нельзя трекать пользователя.

Итоги

  • Разрешения обязательны
  • Запрашивай только при необходимости
  • Описание в app.json для iOS
  • Linking.openSettings для отказа
  • ATT для трекинга
  • Приватность — закон