← Назад к вопросам

Что такое Android Permission?

1.0 Junior🔥 131 комментариев
#Нативная интеграция

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Android Permissions — полный гайд

Пермиссии (permissions) в Android — это механизм контроля доступа приложения к чувствительным ресурсам устройства. Это важная часть безопасности и приватности в Android.

Историческая справка

Система пермиссий эволюционировала:

  • API 22 и ниже — install-time permissions (разрешение только при установке)
  • API 23+ — runtime permissions (разрешение во время работы приложения)
  • API 31+ — scoped storage, package visibility

Категории пермиссий

1. Normal Permissions

Низкий риск, автоматически предоставляются при установке:

<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />

Эти пермиссии не требуют запроса пользователя во время выполнения.

2. Dangerous Permissions (Runtime Permissions)

Высокий риск для приватности, требуют явного согласия пользователя:

<!-- Камера -->
<uses-permission android:name="android.permission.CAMERA" />

<!-- Геолокация -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

<!-- Контакты -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />

<!-- Хранилище (до API 30) -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<!-- Микрофон -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />

<!-- Календарь -->
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />

Permission Groups

Далось permissions сгруппированы в permission groups. Если пользователь дал разрешение на одну, остальные в группе получат его автоматически:

  • CALENDAR → READ_CALENDAR, WRITE_CALENDAR
  • CAMERA → CAMERA
  • CONTACTS → READ_CONTACTS, WRITE_CONTACTS, GET_ACCOUNTS
  • LOCATION → ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION
  • MICROPHONE → RECORD_AUDIO
  • PHONE → READ_PHONE_STATE, READ_PHONE_NUMBERS, CALL_PHONE, USE_SIP
  • SENSORS → BODY_SENSORS
  • SMS → SEND_SMS, RECEIVE_SMS, READ_SMS, RECEIVE_WAP_PUSH, RECEIVE_MMS
  • STORAGE → READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE

Flutter: Запрос пермиссий

В Flutter используется пакет permission_handler:

import 'package:permission_handler/permission_handler.dart';

class PermissionService {
  // Запрос одной пермиссии
  Future<bool> requestCameraPermission() async {
    final status = await Permission.camera.request();
    return status.isGranted;
  }

  // Запрос нескольких пермиссий
  Future<Map<Permission, PermissionStatus>> requestMultiple() async {
    final statuses = await [
      Permission.camera,
      Permission.location,
      Permission.microphone,
    ].request();
    return statuses;
  }

  // Проверка текущего статуса
  Future<bool> isCameraPermissionGranted() async {
    final status = await Permission.camera.status;
    return status.isGranted;
  }

  // Запрос с обработкой всех возможных статусов
  Future<void> requestLocationPermission() async {
    final status = await Permission.location.request();

    if (status.isGranted) {
      print('Location permission granted');
    } else if (status.isDenied) {
      print('Location permission denied');
    } else if (status.isPermanentlyDenied) {
      print('Location permission permanently denied, open app settings');
      openAppSettings();
    } else if (status.isRestricted) {
      print('Location permission restricted by system');
    }
  }

  // Проверка нескольких пермиссий
  Future<bool> hasAllRequiredPermissions() async {
    final statuses = await [
      Permission.camera,
      Permission.microphone,
    ].status;

    return statuses.values.every((status) => status.isGranted);
  }
}

Правильный паттерн

class CameraScreen extends StatefulWidget {
  @override
  State<CameraScreen> createState() => _CameraScreenState();
}

class _CameraScreenState extends State<CameraScreen> {
  late PermissionService _permissionService;

  @override
  void initState() {
    super.initState();
    _permissionService = PermissionService();
    _checkAndRequestPermissions();
  }

  Future<void> _checkAndRequestPermissions() async {
    final isGranted = await _permissionService.requestCameraPermission();
    if (isGranted) {
      _initializeCamera();
    } else {
      _showPermissionDeniedDialog();
    }
  }

  void _initializeCamera() {
    // Инициализация камеры
  }

  void _showPermissionDeniedDialog() {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('Camera Permission Required'),
        content: Text('This app needs camera access to function properly'),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: Text('Cancel'),
          ),
          TextButton(
            onPressed: () {
              openAppSettings();
              Navigator.pop(context);
            },
            child: Text('Open Settings'),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Camera')),
      body: Center(child: Text('Camera Screen')),
    );
  }
}

Статусы пермиссий

enum PermissionStatus {
  granted,           // Разрешено
  denied,            // Отказано (может быть запрошено снова)
  permanentlyDenied, // Отказано с опцией "Don't ask again"
  restricted,        // Ограничено системой (родительский контроль)
  limited,           // Ограниченный доступ (только iOS 14+)
}

Best Practices

1. Запрашивай пермиссии в нужный момент

// ❌ Плохо: запрос всех пермиссий при запуске
if (mounted) {
  await requestAllPermissions();
}

// ✅ Хорошо: запрос при использовании функции
FloatingActionButton(
  onPressed: () async {
    if (await Permission.camera.request().isGranted) {
      openCamera();
    }
  },
)

2. Обясни зачем нужна пермиссия Показывай UI (rationale) перед запросом:

if (await Permission.location.shouldShowRequestRationale) {
  showExplanationDialog();
}
final status = await Permission.location.request();

3. Обрабатывай permanentlyDenied Если пользователь выбрал "Don't ask again", отправь в настройки:

if (status.isPermanentlyDenied) {
  openAppSettings();
}

4. Кэшируй результаты

class PermissionCache {
  static final Map<Permission, bool> _cache = {};

  static Future<bool> hasPermission(Permission permission) async {
    if (_cache.containsKey(permission)) {
      return _cache[permission]!;
    }
    final granted = (await permission.status).isGranted;
    _cache[permission] = granted;
    return granted;
  }
}

Заключение

Пермиссии в Android — это фундаментальная часть безопасности. За 10+ лет опыта я вижу, что правильная работа с ними критична для:

  • Безопасности приложения и данных пользователя
  • Доверия пользователей
  • Прохождения App Store/Play Store review
  • Стабильности приложения (краши при отсутствии пермиссий)

Всегда запрашивай пермиссии при необходимости, объясняй зачем они нужны и обрабатывай все возможные статусы.

Что такое Android Permission? | PrepBro