Permission Handler در اندروید: نحوه عملکرد، پردازش درخواست‌ها و پیاده‌سازی

نویسنده: IT Sectr منتشر شده: 2026-05-20 زمان مطالعه: 8 دقیقه

Permission Handler مؤلفه‌ای از برنامه اندروید است که مسئول بررسی، درخواست و پردازش نتایج مجوزهای runtime می‌باشد. به گفته Android Developer Guide, 2024، handler مجوز منطق checkSelfPermission، requestPermissions و shouldShowRequestPermissionRationale را در یک کلاس یا ViewModel متمرکز می‌کند. این کار نگهداری کد را ساده‌تر و آزمایش را بهبود می‌بخشد.

نکات اصلی

  • Permission Handler — مؤلفه تخصصی برای مدیریت متمرکز مجوزهای runtime اندروید.
  • منطق checkSelfPermission، requestPermissions و shouldShowRequestPermissionRationale را کپسوله می‌کند.
  • پیاده‌سازی‌های مدرن بر ActivityResultContracts از androidx.activity مبتنی هستند.
  • آزمون واحد را به لطف وارونگی وابستگی و جداسازی کد پلتفرم ساده‌تر می‌کند.
  • بهترین شیوه‌ها شامل یک handler واحد در Activity و استفاده مجدد از طریق کانتینر DI است.

Permission Handler در اندروید چیست

Permission Handler — یک الگوی معماری برای مدیریت متمرکز مجوزهای runtime اندروید است. به جای فراخوانی‌های پراکنده ContextCompat.checkSelfPermission و ActivityCompat.requestPermissions در سراسر کد برنامه، تمام منطق درخواست‌ها و پردازش نتایج در یک کلاس متمرکز می‌شود. این کار تکرار را کاهش می‌دهد، نگهداری را ساده می‌کند و کد را قابل پیش‌بینی‌تر می‌سازد.

نیاز به Permission Handler با معرفی مجوزهای runtime در اندروید 6.0 به وجود آمد. پیش از آن، همه مجوزها هنگام نصب درخواست می‌شدند و کد برنامه می‌توانست بدون بررسی از هر API استفاده کند. پس از انتقال به مدل runtime، هر استفاده از مجوز خطرناک نیاز به بررسی سه مرحله‌ای دارد: checkSelfPermission، requestPermissions، onRequestPermissionsResult. پراکنده شدن این منطق در Activity و Fragment منجر به تکرار درون‌خطی و خطا می‌شود. طبق داده‌های Google I/O 2019، متمرکزسازی پردازش مجوزها تعداد باگ‌های مربوط به Permission Denial را به طور متوسط 60 درصد کاهش می‌دهد.

یک Permission Handler خوب رابط کاربری تمیزی برای کد فراخوان فراهم می‌کند. Activity یا Fragment نیازی به دانستن جزئیات درخواست ندارند — آنها متدی مانند requestCamera(callback) را فراخوانی می‌کنند و handler خودش بررسی وضعیت، نمایش rationale، فراخوانی دیالوگ سیستمی و ارسال نتیجه به callback را مدیریت می‌کند. این اصل مسئولیت واحد را پیاده‌سازی کرده و منطق کسب‌وکار را از کد پلتفرم مجوزها جدا می‌کند.

چه زمانی Permission Handler لازم است

Permission Handler زمانی ضروری می‌شود که برنامه از 3 مجوز خطرناک یا بیشتر استفاده می‌کند. برای برنامه‌های ساده با یک مجوز (مثلاً دوربین برای اسکنر QR) می‌توان با فراخوانی مستقیم کار کرد. اما برای یک برنامه موبایل معمولی با دوربین، موقعیت‌یابی، اعلان‌ها و حافظه — handler متمرکز برای نگهداری اجباری است.

معماری Permission Handler

یک Permission Handler معمولی از سه لایه تشکیل شده است: رابط-قرارداد، پیاده‌سازی با ActivityResultLauncher و لایه برای ViewModel. رابط متدهای درخواست برای هر مجوز را تعریف می‌کند — requestCamera، requestLocation، requestStorage. پیاده‌سازی این متدها را با قراردادهای ActivityResultContracts.RequestPermission مرتبط می‌کند.

مؤلفه‌های کلیدی معماری:

  • PermissionHandlerContract — رابط با متدهایی برای هر مجوز
  • PermissionHandlerImpl — پیاده‌سازی متصل به ActivityResultRegistry
  • PermissionResult — کلاس sealed با وضعیت‌های GRANTED، DENIED، NEVER_ASK_AGAIN
  • RationaleHandler — مؤلفه برای نمایش توضیحات قبل از درخواست

این معماری امکان جایگزینی آسان پیاده‌سازی را در آزمایش‌ها فراهم می‌کند: به جای ActivityResultLauncher واقعی از یک mock استفاده می‌شود که بدون تعامل با سیستم نتیجه از پیش تعیین‌شده را برمی‌گرداند. این برای آزمون واحد منطق UI که در آن راه‌اندازی Activity برای دیالوگ مجوز غیرممکن است، حیاتی می‌باشد.

مدیریت چرخه حیات

Permission Handler باید چرخه حیات Activity و Fragment را در نظر بگیرد. Launcherها در ActivityResultRegistry ثبت می‌شوند که به طور خودکار وضعیت را در هنگام چرخش صفحه و بازآفرینی Activity ذخیره و بازیابی می‌کند. Handler نباید ارجاعات مستقیم به Activity یا Fragment نگه دارد — به جای آن از WeakReference استفاده کنید یا registry را از طریق سازنده ارسال کنید. این کار از نشت حافظه و crash در هنگام تغییرات پیکربندی جلوگیری می‌کند.

پیاده‌سازی Permission Handler در Kotlin

پیاده‌سازی پایه Permission Handler بر ActivityResultContracts.RequestPermission ساخته می‌شود. Handler از ComponentActivity یا Fragment ActivityResultRegistry را دریافت کرده و برای هر مجوز launcherهایی ثبت می‌کند. هر launcher یک لامبدا-کالبک دریافت می‌کند که پس از پاسخ کاربر فراخوانی می‌شود.

kotlin
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

Handler در onCreate Activity از طریق registerForActivityResult مقداردهی می‌شود که دسترسی به ActivityResultRegistry را فراهم می‌کند. پس از مقداردهی، handler آماده پردازش درخواست‌ها در طول چرخه حیات Activity است. مهم است که initialize قبل از اولین درخواست فراخوانی شود، در غیر این صورت launcher ثبت نخواهد شد.

Permission Handler با ViewModel

ادغام Permission Handler با ViewModel پیشرفته‌ترین رویکرد است. ViewModel وضعیت درخواست‌ها را مدیریت می‌کند و Handler فقط فراخوانی‌های پلتفرم را انجام می‌دهد. ViewModel شامل StateFlow<PermissionUiState> است که در آن UiState مشخص می‌کند کدام مجوز درخواست شده و چه نتیجه‌ای دریافت شده است. Activity مشترک این StateFlow می‌شود و درخواست را به Handler واگذار می‌کند.

kotlin
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 می‌شود، requestCamera را از Handler فراخوانی کرده و نتیجه را از طریق onPermissionResult به ViewModel برمی‌گرداند. جداسازی کد پلتفرم و منطق کسب‌وکار امکان آزمایش ViewModel را بدون وابستگی‌های اندروید فراهم می‌کند.

آزمایش Permission Handler

آزمون واحد Permission Handler به لطف رابط PermissionHandler امکان‌پذیر است. در آزمایش‌ها یک FakePermissionHandler ایجاد می‌شود که سناریوهای مختلف را شبیه‌سازی می‌کند: مجوز اعطا شده، رد شده، Never Ask Again. هر سناریو به طور مستقل آزمایش می‌شود. این به ویژه برای آزمایش منطق UI که باید به هر سه نتیجه به درستی واکنش نشان دهد، مهم است.

kotlin
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 امکان آزمایش ViewModel را بدون شبیه‌ساز فراهم می‌کند. کافی است cameraResult را روی مقدار مورد نظر تنظیم کنید و بررسی کنید که ViewModel به درستی UiState را به‌روزرسانی می‌کند. آزمایش‌های یکپارچه‌سازی Permission Handler واقعی را با ActivityScenario بررسی می‌کنند، اما معمولاً 2-3 مورد از این آزمایش‌ها برای کل برنامه کافی است — بقیه سناریوها با آزمایش‌های واحد با fake پوشش داده می‌شوند.

الگوهای رایج و خطاها

خطاهای رایج هنگام کار با Permission Handler شامل: عدم بررسی checkSelfPermission قبل از هر فراخوانی API، نادیده گرفتن shouldShowRequestPermissionRationale، فراخوانی مجدد requestPermissions در حالت Never Ask Again و ذخیره launcherها بدون در نظر گرفتن چرخه حیات Activity است. بیایید هر مشکل و راه‌حل آن را بررسی کنیم.

رایج‌ترین خطا — فراخوانی API بدون بررسی وضعیت مجوز. توسعه‌دهندگان فرض می‌کنند که اگر مجوز یک بار اعطا شده باشد، برای همیشه باقی می‌ماند. اما کاربر می‌تواند آن را در هر لحظه از طریق تنظیمات لغو کند. Permission Handler باید قبل از انجام عملیات حساس همیشه isPermissionGranted را فراخوانی کند. دومین خطای رایج — نادیده گرفتن shouldShowRequestPermissionRationale و درخواست مجدد که در حالت Never Ask Again منجر به رد فوری بدون دیالوگ می‌شود.

بهترین شیوه‌ها شامل: ایجاد یک نمونه Handler برای کل چرخه حیات Activity، استفاده از SharedFlow برای ارسال نتایج به ViewModel، ثبت تمام درخواست‌ها و ردها برای تحلیل، و همچنین نمایش دیالوگ rationale سفارشی قبل از دیالوگ سیستمی در اولین رد. پیروی از این قوانین عملکرد پایدار با مجوزها را در تمام نسخه‌های اندروید تضمین می‌کند.

سوالات متداول

Permission Handler در اندروید چیست؟

Permission Handler — مؤلفه‌ای برای مدیریت متمرکز مجوزهای runtime است که checkSelfPermission، requestPermissions و shouldShowRequestPermissionRationale را کپسوله می‌کند. نگهداری کد را ساده و آزمایش را بهبود می‌بخشد.

در سال 2024 از چه API برای Handler استفاده کنیم؟

ActivityResultContracts.RequestPermission از کتابخانه androidx.activity توصیه می‌شود. این API جایگزین onRequestPermissionsResult قدیمی شده و یک API callback تمیز با نتیجه Boolean ارائه می‌دهد.

آیا برای یک مجوز Handler لازم است؟

برای یک مجوز Handler اجباری نیست — می‌توانید از فراخوانی مستقیم RequestPermission launcher در Activity استفاده کنید. Handler با 3 مجوز یا بیشتر برای جلوگیری از تکرار کد ضروری می‌شود.

چگونه Permission Handler را آزمایش کنیم؟

یک رابط PermissionHandler و پیاده‌سازی fake آن برای آزمایش‌های واحد ایجاد کنید. Fake نتایج از پیش تعیین‌شده را بدون فراخوانی سیستمی برمی‌گرداند. این امکان آزمایش ViewModel و منطق UI را بدون شبیه‌ساز فراهم می‌کند.

چگونه Never Ask Again را در Handler پردازش کنیم؟

پس از رد، shouldShowRequestPermissionRationale را بررسی کنید. اگر متد false برگرداند — حالت Never Ask Again فعال شده است. Handler باید PermissionResult.DENIED(false) را برگرداند و UI باید دکمه انتقال به تنظیمات را نمایش دهد.

خلاصه

  • Permission Handler — مؤلفه معماری برای مدیریت متمرکز مجوزهای runtime اندروید.
  • بر ActivityResultContracts.RequestPermission از کتابخانه androidx.activity مبتنی است.
  • رابط با متدهایی برای هر مجوز آزمون واحد را از طریق پیاده‌سازی‌های fake ساده می‌کند.
  • ادغام با ViewModel از طریق StateFlow کد پلتفرم را از منطق کسب‌وکار جدا می‌کند.
  • خطاهای رایج: عدم وجود checkSelfPermission، نادیده گرفتن rationale و Never Ask Again.
  • بهترین روش — یک Handler در Activity با ثبت در onCreate.
  • متمرکزسازی تعداد باگ‌های Permission Denial را در پروژه‌های معمولی 60 درصد کاهش می‌دهد.

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید