Permission Handler Android ilovasining runtime ruxsatlarini tekshirish, so'rash va natijalarini qayta ishlash uchun mas'ul bo'lgan komponentidir. Android Developer Guide, 2024-ga ko'ra, ruxsat ishlov beruvchisi checkSelfPermission, requestPermissions va shouldShowRequestPermissionRationale mantiqini yagona sinf yoki ViewModel-da markazlashtiradi. Bu kodni saqlashni osonlashtiradi va testlashni yaxshilaydi.
Asosiy fikrlar
Permission Handler — Android runtime ruxsatlarini markazlashtirilgan boshqarish uchun arxitektura naqshidir. Ilova kodi bo'ylab tarqalgan ContextCompat.checkSelfPermission va ActivityCompat.requestPermissions chaqiruvlari o'rniga, barcha so'rov va natijalarni qayta ishlash mantiqi bir sinfda jamlanadi. Bu takrorlanishni kamaytiradi, saqlashni osonlashtiradi va kodni oldindan bashorat qilinadigan qiladi.
Permission Handler ehtiyoji Android 6.0 da runtime ruxsatlarining joriy etilishi bilan paydo bo'ldi. Bungacha barcha ruxsatlar o'rnatish vaqtida so'ralardi va ilova kodi hech qanday tekshiruvsiz istalgan API dan foydalana olardi. Runtime modeliga o'tgandan so'ng, har bir xavfli ruxsatdan foydalanish uch bosqichli tekshiruvni talab qiladi: checkSelfPermission, requestPermissions, onRequestPermissionsResult. Bu mantiqning Activity va Fragment lar o'rtasida tarqalishi inline takrorlanishga va xatolarga olib keladi. Google I/O 2019 ma'lumotlariga ko'ra, ruxsatlarni qayta ishlashni markazlashtirish Permission Denial bilan bog'liq xatolar sonini o'rtacha 60 foizga kamaytiradi.
Yaxshi Permission Handler chaqiruvchi kod uchun toza interfeysni ta'minlaydi. Activity yoki Fragment so'rov tafsilotlarini bilishi shart emas — ular requestCamera(callback) tipidagi metodni chaqiradi, handler esa statusni tekshirish, rationaleni ko'rsatish, tizim dialogini chaqirish va natijani callback-ga uzatishni o'zi boshqaradi. Bu yagona mas'uliyat prinsipini amalga oshiradi va biznes mantiqini ruxsatlarning platforma kodidan ajratadi.
Permission Handler ilova 3 yoki undan ortiq xavfli ruxsatlardan foydalanganda zarur bo'ladi. Bitta ruxsatli oddiy ilovalar uchun (masalan, QR kod skaneri uchun kamera) to'g'ridan-to'g'ri chaqiruv bilan o'tish mumkin. Ammo kamera, geolokatsiya, bildirishnomalar va xotiraga ega odatiy mobil ilova uchun markazlashtirilgan handler saqlash uchun majburiydir.
Odatiy Permission Handler uch darajadan iborat: interfeys-kontrakt, ActivityResultLauncher bilan amalga oshirish va ViewModel uchun qatlam. Interfeys har bir ruxsat uchun so'rov metodlarini belgilaydi — requestCamera, requestLocation, requestStorage. Amalga oshirish bu metodlarni tegishli ActivityResultContracts.RequestPermission kontraktlari bilan bog'laydi.
Arxitekturaning asosiy komponentlari:
Bunday arxitektura testlarda amalga oshirishni oson almashtirishga imkon beradi: haqiqiy ActivityResultLauncher o'rniga tizim bilan aloqasiz oldindan belgilangan natijani qaytaradigan mock ishlatiladi. Bu ruxsat dialogi uchun Activity ni ishga tushirish mumkin bo'lmagan UI mantiqining unit testlari uchun juda muhimdir.
Permission Handler Activity va Fragment ning hayotiy tsiklini hisobga olishi kerak. Launcherlar ActivityResultRegistry da ro'yxatdan o'tkaziladi, bu ekran aylantirilganda va Activity qayta yaratilganda holatni avtomatik saqlaydi va tiklaydi. Handler Activity yoki Fragment ga to'g'ridan-to'g'ri havolalarni saqlamasligi kerak — buning o'rniga WeakReference dan foydalaning yoki registry ni konstruktor orqali uzating. Bu xotira oqishlari va konfiguratsiya o'zgarishlarida crash larning oldini oladi.
Asosiy amalga oshirish Permission Handler ActivityResultContracts.RequestPermission ga asoslanadi. Handler ComponentActivity yoki Fragment dan ActivityResultRegistry oladi va har bir ruxsat uchun launcherlarni ro'yxatdan o'tkazadi. Har bir launcher foydalanuvchi javob berganidan so'ng chaqiriladigan lambda-callback ni qabul qiladi.
sealed class PermissionResult {
object GRANTED : PermissionResult()
data class DENIED(
val shouldShowRationale: Boolean
) : PermissionResult()
}
interface PermissionHandler {
fun requestCamera(
callback: (PermissionResult) -> Unit
)
fun requestLocation(
callback: (PermissionResult) -> Unit
)
fun isPermissionGranted(
permission: String
): Boolean
}
class AndroidPermissionHandler(
private val registry: ActivityResultRegistry,
private val context: Context
) : PermissionHandler {
private var cameraLauncher: ActivityResultLauncher<String>? = null
fun initialize() {
cameraLauncher = registry.register(
"camera_permission",
ActivityResultContracts.RequestPermission()
) { isGranted ->
if (isGranted) {
pendingCameraCallback?.invoke(
PermissionResult.GRANTED
)
} else {
val rationale = ActivityCompat.shouldShowRequestPermissionRationale(
context as Activity,
Manifest.permission.CAMERA
)
pendingCameraCallback?.invoke(
PermissionResult.DENIED(rationale)
)
}
}
}
private var pendingCameraCallback:
((PermissionResult) -> Unit)? = null
override fun requestCamera(
callback: (PermissionResult) -> Unit
) {
if (isPermissionGranted(
Manifest.permission.CAMERA
)) {
callback.invoke(PermissionResult.GRANTED)
return
}
pendingCameraCallback = callback
cameraLauncher?.launch(
Manifest.permission.CAMERA
)
}
override fun isPermissionGranted(
permission: String
): Boolean {
return ContextCompat.checkSelfPermission(
context, permission
) == PackageManager.PERMISSION_GRANTED
}
}
Handler Activity ning onCreate metodida registerForActivityResult orqali initsializatsiya qilinadi, bu ActivityResultRegistry ga kirishni ta'minlaydi. Initsializatsiyadan so'ng handler Activity ning butun hayotiy tsikli davomida so'rovlarni qayta ishlashga tayyor. Birinchi so'rovdan oldin initialize ni chaqirish muhim, aks holda launcher ro'yxatdan o'tkazilmaydi.
Permission Handler integratsiyasi ViewModel bilan eng ilg'or yondashuvdir. ViewModel so'rovlar holatini boshqaradi, Handler esa faqat platforma chaqiruvlarini bajaradi. ViewModel da StateFlow<PermissionUiState> mavjud, bu erda UiState qaysi ruxsat so'ralayotganini va qanday natija olinganligini tavsiflaydi. Activity bu StateFlow ga obuna bo'ladi va so'rovni Handler ga topshiradi.
class PermissionsViewModel : ViewModel() {
private val _uiState =
MutableStateFlow<PermissionUiState>(
PermissionUiState.Idle
)
val uiState: StateFlow<PermissionUiState> = _uiState.asStateFlow()
fun onCameraRequested() {
_uiState.value = PermissionUiState.RequestingCamera
}
fun onPermissionResult(
permission: String,
result: PermissionResult
) {
when (result) {
PermissionResult.GRANTED -> {
_uiState.value = PermissionUiState.Granted(permission)
}
is PermissionResult.DENIED -> {
_uiState.value = PermissionUiState.Denied(
permission,
result.shouldShowRationale
)
}
}
}
}
sealed class PermissionUiState {
object Idle : PermissionUiState()
object RequestingCamera : PermissionUiState()
data class Granted(val permission: String) : PermissionUiState()
data class Denied(
val permission: String,
val shouldShowRationale: Boolean
) : PermissionUiState()
}
Bu modelda Activity boshlang'ichda Handler orqali isPermissionGranted ni tekshiradi, ViewModel esa faqat holatni boshqaradi. Agar ruxsat berilmagan bo'lsa — Activity uiState ga obuna bo'ladi, Handler dan requestCamera ni chaqiradi va natijani onPermissionResult orqali ViewModel ga qaytaradi. Platforma kodi va biznes mantiqining ajratilishi ViewModel ni Android bog'liqliklarisiz test qilish imkonini beradi.
Unit testlar PermissionHandler interfeysi tufayli mumkin. Testlarda turli stsenariylarni simulyatsiya qiluvchi FakePermissionHandler yaratiladi: ruxsat berilgan, rad etilgan, Never Ask Again. Har bir stsenariy mustaqil ravishda tekshiriladi. Bu, ayniqsa, uchta natijaga ham to'g'ri javob berishi kerak bo'lgan UI mantiqini testlash uchun muhimdir.
class FakePermissionHandler : PermissionHandler {
var cameraResult: PermissionResult =
PermissionResult.GRANTED
var grantedPermissions: Set<String> =
setOf(Manifest.permission.CAMERA)
override fun requestCamera(
callback: (PermissionResult) -> Unit
) {
callback.invoke(cameraResult)
}
override fun isPermissionGranted(
permission: String
): Boolean {
return permission in grantedPermissions
}
}
Fake amalga oshirish ViewModel ni emulyatorsiz test qilish imkonini beradi. Faqat cameraResult ni kerakli qiymatga o'rnatish va ViewModel UiState ni to'g'ri yangilashini tekshirish kifoya. Integratsiya testlari haqiqiy PermissionHandler ni ActivityScenario bilan tekshiradi, lekin odatda butun ilova uchun 2-3 ta bunday test mavjud — qolgan stsenariylar fake lar bilan unit testlar bilan qoplanadi.
Odatiy xatolar Permission Handler bilan ishlashda: har bir API chaqiruvidan oldin checkSelfPermission tekshiruvining yo'qligi, shouldShowRequestPermissionRationale ni e'tiborsiz qoldirish, Never Ask Again holatida requestPermissions ni qayta chaqirish va launcherlarni Activity hayotiy tsiklini hisobga olmasdan saqlash. Keling, har bir muammo va uni hal qilishni ko'rib chiqaylik.
Eng keng tarqalgan xato — ruxsat holatini tekshirmasdan API chaqiruvi. Dasturchilar ruxsat bir marta berilgan bo'lsa, u abadiy qoladi deb taxmin qilishadi. Biroq, foydalanuvchi uni istalgan vaqtda sozlamalardan qaytarib olishi mumkin. Permission Handler sezgir operatsiyani bajarishdan oldin har doim isPermissionGranted ni chaqirishi kerak. Ikkinchi mashhur xato — shouldShowRequestPermissionRationale ni e'tiborsiz qoldirish va Never Ask Again holatida dialogsiz darhol rad etilishiga olib keladigan qayta so'rovdir.
Eng yaxshi amaliyotlarga kiradi: Activity ning butun hayotiy tsikli uchun bitta Handler nusxasini yaratish, natijalarni ViewModel ga uzatish uchun SharedFlow dan foydalanish, tahlil uchun barcha so'rov va rad etishlarni qayd qilish, shuningdek birinchi rad etishda tizim dialogidan oldin maxsus rationale dialogini ko'rsatish. Ushbu qoidalarga rioya qilish Android ning barcha versiyalarida ruxsatlar bilan barqaror ishlashni kafolatlaydi.
Tez-tez so'raladigan savollar
Permission Handler — checkSelfPermission, requestPermissions va shouldShowRequestPermissionRationale ni inkapsulyatsiya qiluvchi, runtime ruxsatlarini markazlashtirilgan boshqarish uchun komponent. Kodni saqlashni osonlashtiradi va testlashni yaxshilaydi.
androidx.activity kutubxonasidan ActivityResultContracts.RequestPermission tavsiya etiladi. U eskirgan onRequestPermissionsResult o'rnini bosadi va Boolean natijasi bilan toza callback API ni ta'minlaydi.
Bitta ruxsat uchun Handler majburiy emas — Activity da to'g'ridan-to'g'ri RequestPermission launcher chaqiruvidan foydalanish mumkin. Handler 3 yoki undan ortiq ruxsatlar mavjud bo'lganda kod takrorlanishining oldini olish uchun zarur bo'ladi.
PermissionHandler interfeysi va uning unit testlar uchun fake amalga oshirishini yarating. Fake tizim chaqiruvlarisiz oldindan belgilangan natijalarni qaytaradi. Bu ViewModel va UI mantiqini emulyatorsiz test qilish imkonini beradi.
Rad etilgandan so'ng shouldShowRequestPermissionRationale ni tekshiring. Agar metod false qaytarsa — Never Ask Again rejimi faollashtirilgan. Handler PermissionResult.DENIED(false) qaytarishi kerak, UI esa Sozlamalarga o'tish tugmasini ko'rsatishi kerak.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.