Android chia permission theo mức rủi ro:
- Normal (INTERNET, VIBRATE): khai báo trong manifest là được cấp khi cài.
- Dangerous / runtime (camera, vị trí, danh bạ, micro, POST_NOTIFICATIONS từ Android 13): từ Android 6.0 (API 23) phải xin lúc chạy; người dùng có thể từ chối hoặc thu hồi bất cứ lúc nào trong Settings.
- Special (SYSTEM_ALERT_WINDOW, SCHEDULE_EXACT_ALARM): phải đưa người dùng tới màn Settings riêng để bật.
Xin quyền bằng Activity Result API:
private val requestCamera =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
if (granted) openCamera() else showFallback()
}
fun onScanClick() {
when {
ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) ==
PackageManager.PERMISSION_GRANTED -> openCamera()
shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> showRationaleDialog()
else -> requestCamera.launch(Manifest.permission.CAMERA)
}
}Nguyên tắc: xin đúng lúc cần (khi bấm nút quét mã), không xin dồn lúc mở app; luôn kiểm tra lại trước khi dùng vì quyền có thể bị thu hồi.
Lưu ý: từ Android 11, người dùng từ chối hai lần thì hệ thống không hiện hộp thoại xin quyền nữa — chỉ còn cách hướng dẫn vào Settings. Gọi API được bảo vệ khi chưa có quyền sẽ ném SecurityException. Với chọn ảnh/video, cân nhắc Photo Picker — không cần xin quyền đọc bộ nhớ.