Permission Handler एक Android एप्लिकेशन घटक है जो रनटाइम अनुमतियों की जाँच, अनुरोध और परिणाम प्रसंस्करण के लिए जिम्मेदार है। Android Developer Guide, 2024 के अनुसार, एक अनुमति हैंडलर checkSelfPermission, requestPermissions और shouldShowRequestPermissionRationale के तर्क को एक ही क्लास या ViewModel में केंद्रीकृत करता है। यह कोड रखरखाव को सरल बनाता है और परीक्षण में सुधार करता है।
मुख्य बातें
Permission Handler Android रनटाइम अनुमतियों के केंद्रीकृत प्रबंधन के लिए एक आर्किटेक्चरल पैटर्न है। एप्लिकेशन कोड में बिखरे हुए ContextCompat.checkSelfPermission और ActivityCompat.requestPermissions कॉल के बजाय, सभी अनुरोध और परिणाम प्रसंस्करण तर्क एक ही क्लास में केंद्रित होते हैं। यह दोहराव को कम करता है, रखरखाव को सरल बनाता है और कोड को अधिक पूर्वानुमानित बनाता है।
Permission Handler की आवश्यकता Android 6.0 में रनटाइम अनुमतियों की शुरुआत के साथ उत्पन्न हुई। इससे पहले, सभी अनुमतियाँ इंस्टॉलेशन के समय माँगी जाती थीं, और एप्लिकेशन कोड बिना जाँच के किसी भी API का उपयोग कर सकता था। रनटाइम मॉडल पर स्विच करने के बाद, खतरनाक अनुमति के प्रत्येक उपयोग के लिए तीन-चरणीय जाँच की आवश्यकता होती है: checkSelfPermission, requestPermissions, onRequestPermissionsResult। इस तर्क को Activity और Fragment में फैलाने से इनलाइन दोहराव और त्रुटियाँ होती हैं। Google I/O 2019 के अनुसार, अनुमति प्रबंधन को केंद्रीकृत करने से Permission Denial से संबंधित बगों की संख्या औसतन 60 प्रतिशत कम हो जाती है।
एक अच्छा Permission Handler कॉलिंग कोड के लिए एक साफ इंटरफ़ेस प्रदान करता है। Activity या Fragment को अनुरोध के विवरण नहीं जानने चाहिए — वे requestCamera(callback) जैसी विधि को कॉल करते हैं, और हैंडलर स्वयं स्थिति जाँच, तर्क प्रदर्शन, सिस्टम डायलॉग आह्वान और परिणाम को callback में भेजने का प्रबंधन करता है। यह एकल जिम्मेदारी सिद्धांत को लागू करता है और व्यावसायिक तर्क को प्लेटफ़ॉर्म अनुमति कोड से अलग करता है।
Permission Handler तब आवश्यक हो जाता है जब कोई एप्लिकेशन 3 या अधिक खतरनाक अनुमतियों का उपयोग करता है। सरल एप्लिकेशन के लिए एक अनुमति (जैसे QR कोड स्कैनर के लिए कैमरा) के साथ, प्रत्यक्ष कॉल पर्याप्त हो सकती है। लेकिन कैमरा, भू-स्थान, सूचनाएँ और भंडारण वाले सामान्य मोबाइल एप्लिकेशन के लिए — एक केंद्रीकृत हैंडलर रखरखाव के लिए आवश्यक है।
एक सामान्य Permission Handler तीन परतों से बना होता है: एक इंटरफ़ेस अनुबंध, ActivityResultLauncher के साथ एक कार्यान्वयन, और एक ViewModel परत। इंटरफ़ेस प्रत्येक अनुमति के लिए अनुरोध विधियों को परिभाषित करता है — requestCamera, requestLocation, requestStorage। कार्यान्वयन इन विधियों को संबंधित ActivityResultContracts.RequestPermission अनुबंधों से बाँधता है।
मुख्य आर्किटेक्चर घटक:
यह आर्किटेक्चर परीक्षणों में कार्यान्वयन को आसानी से बदलने की अनुमति देता है: वास्तविक ActivityResultLauncher के बजाय, एक मॉक का उपयोग किया जाता है जो सिस्टम इंटरैक्शन के बिना पूर्वनिर्धारित परिणाम लौटाता है। यह UI तर्क के यूनिट परीक्षण के लिए महत्वपूर्ण है, जहाँ अनुमति डायलॉग के लिए Activity लॉन्च करना असंभव है।
Permission Handler को Activity और Fragment के जीवनचक्र को ध्यान में रखना चाहिए। लॉन्चर ActivityResultRegistry में पंजीकृत होते हैं, जो स्क्रीन रोटेशन और Activity पुनर्निर्माण पर स्वचालित रूप से स्थिति को सहेजता और पुनर्स्थापित करता है। हैंडलर को Activity या Fragment के सीधे संदर्भ संग्रहीत नहीं करने चाहिए — इसके बजाय, WeakReference का उपयोग करें या कंस्ट्रक्टर के माध्यम से registry पास करें। यह कॉन्फ़िगरेशन परिवर्तनों के दौरान मेमोरी लीक और क्रैश को रोकता है।
Permission Handler का मूल कार्यान्वयन ActivityResultContracts.RequestPermission पर बनाया गया है। हैंडलर ComponentActivity या Fragment से ActivityResultRegistry प्राप्त करता है और प्रत्येक अनुमति के लिए लॉन्चर पंजीकृत करता है। प्रत्येक लॉन्चर एक कॉलबैक लैम्ब्डा स्वीकार करता है जो उपयोगकर्ता के उत्तर देने के बाद लागू होता है।
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
}
}
हैंडलर Activity के onCreate में registerForActivityResult के माध्यम से आरंभ किया जाता है, जो ActivityResultRegistry तक पहुँच प्रदान करता है। आरंभीकरण के बाद, हैंडलर पूरे Activity जीवनचक्र में अनुरोधों को संसाधित करने के लिए तैयार है। पहले अनुरोध से पहले initialize को कॉल करना महत्वपूर्ण है, अन्यथा लॉन्चर पंजीकृत नहीं होगा।
Permission Handler को ViewModel के साथ एकीकृत करना सबसे उन्नत दृष्टिकोण है। ViewModel अनुरोध स्थिति का प्रबंधन करता है, जबकि Handler केवल प्लेटफ़ॉर्म कॉल करता है। ViewModel में StateFlow<PermissionUiState> होता है, जहाँ UiState बताता है कि कौन सी अनुमति माँगी जा रही है और क्या परिणाम प्राप्त हुआ है। Activity इस StateFlow की सदस्यता लेती है और अनुरोध 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()
}
इस मॉडल में, Activity स्टार्टअप पर Handler के माध्यम से isPermissionGranted की जाँच करती है, जबकि ViewModel केवल स्थिति का प्रबंधन करता है। यदि अनुमति प्रदान नहीं की गई है — Activity uiState की सदस्यता लेती है, Handler से requestCamera कॉल करती है और परिणाम को onPermissionResult के माध्यम से ViewModel को वापस भेजती है। प्लेटफ़ॉर्म कोड को व्यावसायिक तर्क से अलग करना Android निर्भरताओं के बिना ViewModel का परीक्षण करने की अनुमति देता है।
PermissionHandler इंटरफ़ेस के कारण Permission Handler का यूनिट परीक्षण संभव है। परीक्षणों में, एक FakePermissionHandler बनाया जाता है जो विभिन्न परिदृश्यों का अनुकरण करता है: अनुमति प्रदान, अस्वीकृत, Never Ask Again। प्रत्येक परिदृश्य का स्वतंत्र रूप से परीक्षण किया जाता है। यह UI तर्क के परीक्षण के लिए विशेष रूप से महत्वपूर्ण है जिसे सभी तीन परिणामों पर सही ढंग से प्रतिक्रिया देनी चाहिए।
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
}
}
फ़ेक कार्यान्वयन बिना एमुलेटर के ViewModel का परीक्षण करने की अनुमति देता है। बस cameraResult को वांछित मान पर सेट करें और सत्यापित करें कि ViewModel अपने UiState को सही ढंग से अपडेट करता है। एकीकरण परीक्षण ActivityScenario के साथ वास्तविक PermissionHandler की जाँच करते हैं, लेकिन आमतौर पर प्रति एप्लिकेशन केवल 2-3 ऐसे परीक्षण होते हैं — शेष परिदृश्य फ़ेक के साथ यूनिट परीक्षणों द्वारा कवर किए जाते हैं।
Permission Handler के साथ काम करते समय सामान्य गलतियों में शामिल हैं: प्रत्येक API कॉल से पहले checkSelfPermission की जाँच न करना, shouldShowRequestPermissionRationale को अनदेखा करना, Never Ask Again के बाद requestPermissions को फिर से कॉल करना, और Activity जीवनचक्र पर विचार किए बिना लॉन्चर संग्रहीत करना। आइए प्रत्येक समस्या और उसके समाधान की जाँच करें।
सबसे आम गलती अनुमति स्थिति की जाँच किए बिना API को कॉल करना है। डेवलपर्स मान लेते हैं कि यदि एक बार अनुमति प्रदान की गई, तो यह हमेशा रहेगी। हालाँकि, उपयोगकर्ता किसी भी समय सेटिंग्स के माध्यम से इसे रद्द कर सकता है। एक Permission Handler को संवेदनशील ऑपरेशन करने से पहले हमेशा isPermissionGranted कॉल करना चाहिए। दूसरी सामान्य गलती shouldShowRequestPermissionRationale को अनदेखा करना और अनुरोध दोहराना है, जो Never Ask Again मोड में बिना डायलॉग के तत्काल अस्वीकृति की ओर ले जाता है।
सर्वोत्तम प्रथाओं में शामिल हैं: पूरे Activity जीवनचक्र के लिए Handler का एक उदाहरण बनाना, परिणामों को ViewModel में भेजने के लिए SharedFlow का उपयोग करना, विश्लेषण के लिए सभी अनुरोधों और अस्वीकृतियों को लॉग करना, और पहली अस्वीकृति पर सिस्टम डायलॉग से पहले एक कस्टम तर्क डायलॉग दिखाना। इन नियमों का पालन करने से Android के सभी संस्करणों पर स्थिर अनुमति प्रबंधन सुनिश्चित होता है।
अक्सर पूछे जाने वाले प्रश्न
Permission Handler रनटाइम अनुमतियों के केंद्रीकृत प्रबंधन के लिए एक घटक है, जो checkSelfPermission, requestPermissions और shouldShowRequestPermissionRationale को समाहित करता है। यह कोड रखरखाव को सरल बनाता है और परीक्षण में सुधार करता है।
ActivityResultContracts.RequestPermission का उपयोग करने की अनुशंसा की जाती है जो androidx.activity लाइब्रेरी से है। यह पुराने onRequestPermissionsResult को बदल देता है और Boolean परिणाम के साथ एक साफ callback API प्रदान करता है।
एक अनुमति के लिए, Handler अनिवार्य नहीं है — आप Activity में सीधे RequestPermission लॉन्चर कॉल का उपयोग कर सकते हैं। कोड दोहराव से बचने के लिए 3 या अधिक अनुमतियों के साथ Handler आवश्यक हो जाता है।
यूनिट परीक्षणों के लिए PermissionHandler इंटरफ़ेस और इसका फ़ेक कार्यान्वयन बनाएँ। फ़ेक सिस्टम कॉल के बिना पूर्वनिर्धारित परिणाम लौटाता है। यह बिना एमुलेटर के ViewModel और UI तर्क का परीक्षण करने की अनुमति देता है।
अस्वीकृति के बाद, shouldShowRequestPermissionRationale की जाँच करें। यदि विधि false लौटाती है — Never Ask Again मोड सक्रिय है। Handler को PermissionResult.DENIED(false) लौटाना चाहिए, और UI को सेटिंग्स में जाने के लिए एक बटन दिखाना चाहिए।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें