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 গ্রহণ করে এবং প্রতিটি অনুমতির জন্য লঞ্চার নিবন্ধন করে। প্রতিটি লঞ্চার একটি কলব্যack ল্যাম্বডা গ্রহণ করে যা ব্যবহারকারীর উত্তর দেওয়ার পরে আহ্বান করা হয়।
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 কল করা গুরুত্বপূর্ণ, অন্যথায় লঞ্চার নিবন্ধিত হবে না।
ViewModel-এর সাথে Permission Handler একীভূত করা সবচেয়ে উন্নত পদ্ধতি। 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টি such পরীক্ষা থাকে — বাকি পরিস্থিতিগুলি ফেকের সাথে ইউনিট পরীক্ষা দ্বারা আচ্ছাদিত হয়।
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 অন্তর্ভুক্ত করে। এটি কোড রক্ষণাবেক্ষণ সহজ করে এবং পরীক্ষার উন্নতি ঘটায়।
androidx.activity লাইব্রেরি থেকে ActivityResultContracts.RequestPermission ব্যবহার করার পরামর্শ দেওয়া হয়। এটি পুরানো 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 অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন