Ang Permission Handler ay isang component ng Android application na responsable sa pagsuri, paghiling, at pagproseso ng mga resulta ng runtime na pahintulot. Ayon sa Android Developer Guide, 2024, ang handler ng pahintulot ay nagse-centralize ng lohika ng checkSelfPermission, requestPermissions at shouldShowRequestPermissionRationale sa iisang klase o ViewModel. Pinapasimple nito ang pagpapanatili ng code at pinapabuti ang pag-test.
Mga Pangunahing Punto
Permission Handler — ay isang architectural pattern para sa sentralisadong pamamahala ng mga runtime na pahintulot sa Android. Sa halip na mga nakakalat na tawag sa ContextCompat.checkSelfPermission at ActivityCompat.requestPermissions sa buong code ng application, ang lahat ng lohika ng paghiling at pagproseso ng resulta ay nakapokus sa iisang klase. Binabawasan nito ang pagdodoble, pinapasimple ang pagpapanatili, at ginagawang mas predictable ang code.
Ang pangangailangan para sa Permission Handler ay lumitaw sa pagpapakilala ng mga runtime na pahintulot sa Android 6.0. Bago ito, lahat ng pahintulot ay hinihiling sa pag-install, at ang code ng application ay maaaring gumamit ng anumang API nang walang pagsusuri. Pagkatapos lumipat sa runtime model, ang bawat paggamit ng mapanganib na pahintulot ay nangangailangan ng tatlong-hakbang na pagsusuri: checkSelfPermission, requestPermissions, onRequestPermissionsResult. Ang pagkalat ng lohika na ito sa Activity at Fragment ay humahantong sa inline na pagdodoble at mga pagkakamali. Ayon sa datos ng Google I/O 2019, ang sentralisasyon ng pagproseso ng pahintulot ay nagbabawas ng bilang ng mga bug na may kaugnayan sa Permission Denial ng average na 60 porsyento.
Ang isang mahusay na Permission Handler ay nagbibigay ng malinis na interface para sa tumatawag na code. Hindi kailangang malaman ng Activity o Fragment ang mga detalye ng kahilingan — tumatawag sila ng method tulad ng requestCamera(callback), at ang handler mismo ang namamahala sa pagsusuri ng katayuan, pagpapakita ng rationale, pagtawag sa system dialog, at pagpapadala ng resulta sa callback. Ito ay nagpapatupad ng prinsipyo ng iisang responsibilidad at naghihiwalay ng business logic mula sa platform code ng mga pahintulot.
Ang Permission Handler ay nagiging kailangan kapag ang application ay gumagamit ng 3 o higit pang mapanganib na pahintulot. Para sa mga simpleng application na may isang pahintulot (halimbawa, camera para sa QR code scanner), maaaring gumamit ng direktang tawag. Ngunit para sa isang tipikal na mobile application na may camera, geolocation, notification at storage — ang sentralisadong handler ay sapilitan para sa pagpapanatili.
Isang tipikal na Permission Handler ay binubuo ng tatlong antas: interface-contract, implementasyon na may ActivityResultLauncher, at layer para sa ViewModel. Ang interface ay tumutukoy sa mga method ng paghiling para sa bawat pahintulot — requestCamera, requestLocation, requestStorage. Ang implementasyon ay nag-uugnay ng mga method na ito sa mga kaukulang contract ng ActivityResultContracts.RequestPermission.
Mga pangunahing component ng arkitektura:
Ang arkitekturang ito ay nagpapahintulot ng madaling pagpapalit ng implementasyon sa mga test: sa halip ng tunay na ActivityResultLauncher, ginagamit ang isang mock na nagbabalik ng paunang-natukoy na resulta nang walang interaksyon sa system. Ito ay kritikal para sa unit testing ng UI logic, kung saan hindi posible ang paglunsad ng Activity para sa dialog ng pahintulot.
Ang Permission Handler ay dapat isaalang-alang ang lifecycle ng Activity at Fragment. Ang mga launcher ay nirerehistro sa ActivityResultRegistry, na awtomatikong nagse-save at nagre-restore ng estado sa pag-ikot ng screen at muling paglikha ng Activity. Ang Handler ay hindi dapat mag-imbak ng direktang mga reference sa Activity o Fragment — sa halip, gumamit ng WeakReference o ipasa ang registry sa pamamagitan ng constructor. Ito ay pumipigil sa mga memory leak at crash sa mga pagbabago sa configuration.
Ang pangunahing implementasyon ng Permission Handler ay binuo sa ActivityResultContracts.RequestPermission. Ang Handler ay tumatanggap ng ActivityResultRegistry mula sa ComponentActivity o Fragment at nagrerehistro ng mga launcher para sa bawat pahintulot. Ang bawat launcher ay tumatanggap ng lambda-callback na tinatawag pagkatapos ng tugon ng user.
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
}
}
Ang Handler ay ini-initialize sa onCreate ng Activity sa pamamagitan ng registerForActivityResult, na nagbibigay ng access sa ActivityResultRegistry. Pagkatapos ng initialisasyon, ang handler ay handa na iproseso ang mga kahilingan sa buong lifecycle ng Activity. Mahalagang tawagan ang initialize bago ang unang kahilingan, kung hindi ay hindi marerehistro ang launcher.
Ang integrasyon ng Permission Handler sa ViewModel ay ang pinaka-advanced na approach. Ang ViewModel ay namamahala sa estado ng mga kahilingan, at ang Handler ay gumagawa lamang ng mga platform call. Ang ViewModel ay naglalaman ng StateFlow<PermissionUiState>, kung saan ang UiState ay naglalarawan kung aling pahintulot ang hinihiling at kung anong resulta ang nakuha. Ang Activity ay nag-subscribe sa StateFlow na ito at nagde-delegate ng kahilingan sa Handler.
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()
}
Sa modelong ito, sinusuri ng Activity ang isPermissionGranted sa pamamagitan ng Handler sa pagsisimula, at ang ViewModel ay namamahala lamang ng estado. Kung hindi ibinigay ang pahintulot — nag-subscribe ang Activity sa uiState, tinatawagan ang requestCamera mula sa Handler, at ibinabalik ang resulta sa ViewModel sa pamamagitan ng onPermissionResult. Ang paghihiwalay ng platform code at business logic ay nagpapahintulot sa pag-test ng ViewModel nang walang mga dependency sa Android.
Ang unit testing ng Permission Handler ay posible dahil sa interface ng PermissionHandler. Sa mga test, ginagawa ang FakePermissionHandler na ginagaya ang iba't ibang scenario: pahintulot na ibinigay, tinanggihan, Never Ask Again. Ang bawat scenario ay sinusuri nang nakapag-iisa. Ito ay lalong mahalaga para sa pag-test ng UI logic na dapat tumugon nang tama sa lahat ng tatlong resulta.
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
}
}
Ang Fake na implementasyon ay nagpapahintulot sa pag-test ng ViewModel nang walang emulator. Sapat na itakda ang cameraResult sa nais na halaga at suriin kung ang ViewModel ay tama na nag-a-update ng UiState. Ang integration test ay sumusuri sa tunay na PermissionHandler gamit ang ActivityScenario, ngunit karaniwang may 2-3 ganoong test para sa buong application — ang natitirang mga scenario ay sakop ng unit test na may mga fake.
Mga karaniwang pagkakamali sa pagtatrabaho sa Permission Handler ay kinabibilangan ng: kawalan ng pagsusuri ng checkSelfPermission bago ang bawat API call, pagwawalang-bahala sa shouldShowRequestPermissionRationale, muling pagtawag sa requestPermissions sa Never Ask Again, at pag-imbak ng mga launcher nang hindi isinasaalang-alang ang lifecycle ng Activity. Tingnan natin ang bawat problema at solusyon.
Ang pinakakaraniwang pagkakamali — pagtawag ng API nang hindi sinusuri ang katayuan ng pahintulot. Ipinapalagay ng mga developer na kung ang pahintulot ay naibigay minsan, ito ay mananatili magpakailanman. Gayunpaman, maaaring bawiin ito ng user anumang oras sa pamamagitan ng mga setting. Permission Handler ay dapat laging tumawag ng isPermissionGranted bago magsagawa ng sensitibong operasyon. Ang pangalawang karaniwang pagkakamali — pagwawalang-bahala sa shouldShowRequestPermissionRationale at muling paghiling na humahantong sa agarang pagtanggi nang walang dialog sa Never Ask Again.
Ang mga pinakamahusay na kasanayan ay kinabibilangan ng: paggawa ng isang instance ng Handler para sa buong lifecycle ng Activity, paggamit ng SharedFlow para sa pagpapadala ng mga resulta sa ViewModel, pag-log ng lahat ng mga kahilingan at pagtanggi para sa analytics, pati na rin ang pagpapakita ng custom na rationale dialog bago ang system dialog sa unang pagtanggi. Ang pagsunod sa mga patakarang ito ay ginagarantiyahan ang matatag na paggamit ng mga pahintulot sa lahat ng bersyon ng Android.
Mga Madalas Itanong
Permission Handler — isang component para sa sentralisadong pamamahala ng mga runtime na pahintulot, na nag-e-encapsulate ng checkSelfPermission, requestPermissions at shouldShowRequestPermissionRationale. Pinapasimple nito ang pagpapanatili ng code at pinapabuti ang pag-test.
Inirerekomenda ang ActivityResultContracts.RequestPermission mula sa library na androidx.activity. Pinapalitan nito ang lumang onRequestPermissionsResult at nagbibigay ng malinis na callback API na may Boolean na resulta.
Para sa isang pahintulot, ang Handler ay hindi sapilitan — maaari mong gamitin ang direktang tawag sa RequestPermission na launcher sa Activity. Ang Handler ay nagiging kailangan sa 3 o higit pang pahintulot upang maiwasan ang pagdodoble ng code.
Gumawa ng interface na PermissionHandler at ang fake na implementasyon nito para sa unit test. Ang Fake ay nagbabalik ng paunang-natukoy na mga resulta nang walang system call. Ito ay nagpapahintulot sa pag-test ng ViewModel at UI logic nang walang emulator.
Pagkatapos ng pagtanggi, suriin ang shouldShowRequestPermissionRationale. Kung ang method ay nagbalik ng false — ang Never Ask Again mode ay aktibo. Ang Handler ay dapat magbalik ng PermissionResult.DENIED(false), at ang UI ay dapat magpakita ng button para pumunta sa Settings.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din