App Permissions: lifecycle и edge cases которые пропускают
Permissions — самый недотестированный класс мобильных фич. QA обычно проверяет «нажал Allow → камера открылась». Но между этими двумя точками — десяток состояний, и каждый из них может сломаться.
Состояния permission
iOS и Android имеют похожие, но не идентичные ответы:
— notDetermined — ещё не спрашивали.
— denied — юзер отказал. iOS: больше не покажет prompt автоматически.
— authorized / granted — разрешил.
— restricted (iOS) — заблокировано Screen Time / MDM.
— limited (iOS 14+ Photos) — частичный доступ (выбранные фотки).
— provisional (iOS Notifications) — тихое разрешение.
Чек-лист
— Первый запрос: prompt появляется в правильный момент. Apple/Google рекомендуют — после soft-ask экрана с объяснением «зачем».
— Отказ → попытка снова: на iOS повторный prompt не появится. Приложение должно показать кастомное окно с deep-link в Settings.
— Включение через Settings: юзер отказал → пошёл в Settings → включил → вернулся. Permission подхватывается? Часто нет — нужен listener на applicationWillEnterForeground.
— Отзыв permission: юзер вышел в Settings, отключил доступ → приложение разворачивается → не падает, корректно фолбэк-логика.
— Limited Photos (iOS): юзер дал доступ к 5 фоткам из 1000. Приложение работает с этими 5, не пытается читать остальные.
— Permission во время работы: запросили доступ к локации → юзер на середине процесса свернул приложение → отказался → вернулся → не падает.
Permission groups (Android)
Android группирует permissions: например, READ_CONTACTS и WRITE_CONTACTS в одной группе. Если юзер дал доступ на чтение — запись уже разрешена (на Android до 12). Не предполагай разделение.
iOS-специфика
— NSCameraUsageDescription в Info.plist обязателен. Без него приложение крашится при запросе камеры. Проверяйте, что строка локализована.
— Photo Library: NSPhotoLibraryUsageDescription (чтение) и NSPhotoLibraryAddUsageDescription (только запись) — это разные пермишены.
— Bluetooth (iOS 13+): NSBluetoothAlwaysUsageDescription + новый алерт при первом use.
Что проверить под нагрузкой
✅ Многократный запрос пермишена — UI не «дёргается», prompt не показывается дважды.
✅ Отказ от permission не блокирует остальной функционал приложения.
✅ После повторной установки приложения — все permissions сброшены до notDetermined.
✅ В UI есть читаемое объяснение, почему пермишен нужен. Не просто системный prompt.
Тулзы
— iOS: Settings → Privacy & Security → каждая категория показывает кто запрашивал и текущий статус.
— Android: Settings → Apps → [приложение] → Permissions → подробный список с возможностью переключать.
— adb на Android: adb shell pm grant com.example.app android.permission.CAMERA — выдать пермишен программно для тестов.
— adb revoke: adb shell pm revoke com.example.app android.permission.CAMERA — отозвать.
Подробнее: Apple — Requesting access to protected resources, Android — Permissions overview.