shouldShowRequestPermissionRationale در Android — چیست، منطق نمایش و پیاده‌سازی

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

shouldShowRequestPermissionRationale — یک متد Android API است که به توسعه‌دهنده می‌گوید آیا قبل از درخواست مجوز خطرناک باید به کاربر توضیح نشان دهد یا خیر. بر اساس Android Developer Reference, 2024، متد rational اگر کاربر قبلاً درخواست را رد کرده اما پرچم Never Ask Again را تنظیم نکرده باشد، true برمی‌گرداند. این ابزاری کلیدی برای ساخت UX مودبانه هنگام کار با مجوزهای زمان اجرا است.

نکات اصلی

  • shouldShowRequestPermissionRationale — متدی که تعیین می‌کند آیا قبل از درخواست مجوز باید توضیح نشان داده شود.
  • اگر Never Ask Again فعال نباشد، پس از اولین رد کاربر true برمی‌گرداند.
  • اگر مجوز هرگز درخواست نشده، اعطا شده یا برای همیشه مسدود شده باشد، false برمی‌گرداند.
  • برای نمایش یک دیالوگ سفارشی با توضیح اینکه چرا مجوز خاص نیاز است استفاده می‌شود.
  • در حالت never ask again (false + denied) باید کاربر را به تنظیمات هدایت کنید.

shouldShowRequestPermissionRationale چیست

shouldShowRequestPermissionRationale — متدی از کلاس Activity و Fragment در Android است که از طریق ActivityCompat برای سازگاری در دسترس است. این متد نام مجوز را می‌گیرد و Boolean برمی‌گرداند که نشان می‌دهد آیا قبل از درخواست مجدد باید به کاربر توضیح اضافی نشان داده شود. این متد در Android 6.0 Marshmallow همراه با مدل مجوزهای زمان اجرا معرفی شد.

مکانیزم rationale بر اساس ردیابی تاریخچه تعامل کاربر با دیالوگ‌های مجوز ساخته شده است. سیستم به خاطر می‌سپارد که آیا کاربر قبلاً درخواست را رد کرده است. اگر رد بدون تنظیم پرچم Never Ask Again انجام شده باشد، shouldShowRequestPermissionRationale true برمی‌گرداند. این سیگنالی به توسعه‌دهنده است: کاربر نمی‌فهمد چرا مجوز نیاز است و توضیح اضافی لازم است. طبق Google Material Design Guidelines، نمایش دیالوگ rationale پس از اولین رد، احتمال اعطای مجدد مجوز را 35 درصد افزایش می‌دهد.

درک معنای مقادیر بازگشتی مهم است: true به این معنی است که نمایش دیالوگ منطقی است، false — دیالوگ یا لازم نیست (مجوز قبلاً اعطا شده یا هرگز درخواست نشده) یا بی‌فایده است (Never Ask Again فعال است). متد تضمین نمی‌کند که دیالوگ نمایش داده شود — فقط توصیه می‌کند. توسعه‌دهنده خودش تصمیم می‌گیرد در پاسخ چه UI نشان دهد.

متد چه زمانی معرفی شد

shouldShowRequestPermissionRationale در API Level 23 همراه با گروهی از متدها برای مجوزهای زمان اجرا معرفی شد. قبل از Android 6.0 همه مجوزها هنگام نصب درخواست می‌شدند و مکانیزم توضیح لازم نبود — کاربر کل لیست را یکباره قبول یا رد می‌کرد. مدل زمان اجرا موقعیتی را ممکن کرد که کاربر درخواست را بدون درک زمینه رد می‌کند و دقیقاً به همین دلیل rationale نیاز است.

shouldShowRequestPermissionRationale چگونه کار می‌کند

منطق متد به این صورت است. در اولین فراخوانی requestPermissions برای یک مجوز خاص، shouldShowRequestPermissionRationale false برمی‌گرداند — کاربر هنوز با دیالوگ مواجه نشده است. اگر کاربر درخواست را رد کرده (دکمه Deny را زده)، متد شروع به بازگرداندن true می‌کند. پس از رد مجدد با پرچم Never Ask Again، متد false برمی‌گرداند.

جدول کامل وضعیت‌ها:

وضعیتshouldShowRationalecheckSelfPermissionاقدام توسعه‌دهنده
درخواست نشدهfalseDENIEDنمایش دیالوگ سیستمی
اعطا شدهfalseGRANTEDاجرای تابع
رد شده برای اولین بارtrueDENIEDنمایش rationale، سپس دیالوگ سیستمی
Never Ask AgainfalseDENIEDهدایت به تنظیمات

ترکیب shouldShowRequestPermissionRationale = false و checkSelfPermission = DENIED — سخت‌ترین حالت برای پردازش است. به این معنی است که یا مجوز هرگز درخواست نشده یا Never Ask Again تنظیم شده است. توسعه‌دهنده باید این دو حالت را از هم تشخیص دهد. تنها راه — ذخیره پرچم firstRequest در SharedPreferences یا استفاده از SavedStateHandle. در اولین درخواست پرچم را تنظیم کنید و اگر shouldShowRationale false برگرداند و پرچم قبلاً true باشد — یعنی Never Ask Again فعال است.

بازنشانی وضعیت

shouldShowRequestPermissionRationale زمانی بازنشانی می‌شود که کاربر برنامه را حذف و دوباره نصب کند، داده‌های برنامه را پاک کند یا تنظیمات مجوز را بازنشانی کند. پس از نصب مجدد، متد دوباره برای اولین درخواست false برمی‌گرداند. به‌روزرسانی‌های سیستمی و تغییر نسخه Android تاریخچه را بازنشانی نمی‌کنند — در داده‌های برنامه ذخیره می‌شود.

پیاده‌سازی دیالوگ rationale

پیاده‌سازی صحیح rationale شامل سه مؤلفه است: بررسی shouldShowRequestPermissionRationale پس از رد، نمایش دیالوگ سفارشی با توضیح و فراخوانی مجدد requestPermissions پس از پاسخ مثبت کاربر. دیالوگ باید مختصر، مشخص و توضیح دهد که چرا برنامه دقیقاً به این مجوز نیاز دارد.

kotlin
private fun requestLocationWithRationale() {
    val permission = Manifest.permission.ACCESS_FINE_LOCATION

    when {
        ContextCompat.checkSelfPermission(
            this, permission
        ) == PackageManager.PERMISSION_GRANTED -> {
            startLocationTracking()
        }
        ActivityCompat.shouldShowRequestPermissionRationale(
            this, permission
        ) -> {
            showRationaleDialog(permission)
        }
        else -> {
            requestPermissionLauncher.launch(permission)
        }
    }
}

private fun showRationaleDialog(
    permission: String
) {
    AlertDialog.Builder(this)
        .setTitle("چرا دسترسی به موقعیت مکانی نیاز است")
        .setMessage(
            "برنامه از موقعیت مکانی برای علامت‌گذاری" +
            " مکان‌ها روی نقشه استفاده می‌کند. بدون این مجوز" +
            " عملکرد کار نخواهد کرد."
        )
        .setPositiveButton("اجازه دادن") { _, _ ->
            requestPermissionLauncher.launch(permission)
        }
        .setNegativeButton("لغو", null)
        .show()
}

الگوهای UI برای rationale

بهترین روش‌های Material Design استفاده از bottom sheet یا بنر درون‌خطی به جای دیالوگ مدال برای rationale را توصیه می‌کنند. Bottom sheet کمتر مزاحم است و به کاربر زمینه می‌دهد. عنصر درون‌خطی در صفحه (مثلاً کارتی با توضیح و دکمه اجازه) نشان می‌دهد که عملکرد بدون مجوز در دسترس نیست، اما بقیه رابط را مسدود نمی‌کند.

محلی‌سازی rationale

متن rationale باید محلی‌سازی شده و با عملکرد خاص تطبیق داده شود. از عبارات کلی مانند «این برای کار برنامه لازم است» استفاده نکنید. مشخصاً بگویید: «برای نمایش آب و هوای نزدیک شما» یا «برای ذخیره عکس‌ها در گالری». طبق Google UX Research، توضیحات مشخص احتمال اعطای مجوز را 50 درصد افزایش می‌دهد.

Rationale در مقابل Never Ask Again

تفاوت بین shouldShowRequestPermissionRationale = true (رد اول) و false در حالت DENIED (Never Ask Again) — نکته کلیدی در پردازش مجوزها است. در حالت اول کاربر مردد بود و توضیح اضافی می‌تواند او را به اعطای دسترسی متقاعد کند. در حالت دوم — کاربر تصمیم نهایی را گرفته و دیالوگ سیستمی مجدد فقط باعث ناراحتی می‌شود.

الگوریتم پردازش پس از رد باید به این صورت باشد:

  • دریافت نتیجه DENIED از callback درخواست
  • فراخوانی shouldShowRequestPermissionRationale
  • اگر true — نمایش دیالوگ سفارشی rationale با دکمه تکرار
  • اگر false — نمایش دیالوگ با دکمه باز کردن تنظیمات

مهم است ترتیب را اشتباه نگیرید: ابتدا shouldShowRequestPermissionRationale را بررسی کنید، نه checkSelfPermission را. checkSelfPermission در هر دو حالت DENIED برمی‌گرداند. فقط shouldShowRequestPermissionRationale رد اول را از Never Ask Again متمایز می‌کند. از SavedStateHandle یا SharedPreferences برای ذخیره پرچم «درخواست اول انجام شد» استفاده کنید — این تنها راه مطمئن برای تشخیص «درخواست نشده» از «مسدود شده» است.

بهترین روش‌های نمایش rationale

rationale را فقط یک بار نمایش دهید. اگر کاربر پس از rationale دوباره درخواست را رد کرد — دیگر توضیح را نشان ندهید. مستقیماً به پیشنهاد باز کردن تنظیمات بروید. نمایش مکرر rationale به عنوان مزاحمت تلقی می‌شود و رتبه برنامه را کاهش می‌دهد. سناریوی بهینه: درخواست — رد — rationale — درخواست مجدد — رد — تنظیمات.

قبل از اولین درخواست rationale را نشان ندهید. برخی توسعه‌دهندگان به اشتباه قبل از اولین دیالوگ توضیح نشان می‌دهند و استدلال می‌کنند که «کاربر باید بفهمد». این UX را بدتر می‌کند: کاربر به جای یک دیالوگ، دو دیالوگ پشت سر هم می‌بیند. Google توصیه می‌کند دیالوگ سیستمی را فوراً نشان دهید و rationale را فقط پس از رد.

از rationale زمینه‌ای استفاده کنید که به لحظه نیاز واقعی به عملکرد گره خورده است. همه مجوزها را هنگام شروع برنامه درخواست نکنید — این پایین‌ترین نرخ اعطا است. وقتی کاربر دکمه «عکس گرفتن» را زد CAMERA را درخواست کنید و وقتی نقشه را باز کرد LOCATION را. درخواست زمینه‌ای همراه با rationale اعطا را تا 80 درصد در مقابل 30 درصد در درخواست اولیه افزایش می‌دهد.

تست سناریوهای rationale

تست shouldShowRequestPermissionRationale نیاز به بررسی چهار وضعیت جدول دارد: درخواست نشده، اعطا شده، رد شده، Never Ask Again. در تست‌های واحد از FakePermissionHandler با رفتار قابل تنظیم shouldShowRationale استفاده می‌شود. در تست‌های ابزاری — UiAutomator یا Espresso با شبیه‌سازی پاسخ‌ها به دیالوگ‌های سیستمی.

kotlin
class RationaleViewModelTest {

    private val handler = FakePermissionHandler()
    private val viewModel = PermissionsViewModel(handler)

    fun testFirstDenial_shouldShowRationale() {
        handler.shouldShowRationale = true
        handler.cameraResult =
            PermissionResult.DENIED(true)

        viewModel.onCameraRequested()

        assertEquals(
            PermissionUiState.Denied(true),
            viewModel.uiState.value
        )
    }

    fun testNeverAskAgain_redirectToSettings() {
        handler.shouldShowRationale = false
        handler.cameraResult =
            PermissionResult.DENIED(false)

        viewModel.onCameraRequested()

        assertEquals(
            PermissionUiState.RedirectToSettings,
            viewModel.uiState.value
        )
    }
}

سناریوی کلیدی برای تست ابزاری — بررسی اینکه دیالوگ rationale واقعاً پس از اولین رد نمایش داده می‌شود. از Espresso با idling resources برای انتظار دیالوگ سیستمی استفاده کنید، سپس Deny را بزنید، ظاهر شدن دیالوگ سفارشی با متن توضیح را بررسی کنید و Allow را بزنید — اعطا را بررسی کنید. UIAutomator امکان تعامل با دیالوگ سیستمی از طریق متن دکمه را فراهم می‌کند که تست را پایدارتر می‌کند.

همچنین ارزش تست سناریوی رد در داخل دیالوگ rationale را دارد. اگر کاربر در توضیح سفارشی Deny را زده باشد، shouldShowRequestPermissionRationale باید دوباره true برگرداند، زیرا Never Ask Again هنوز فعال نشده است. بهترین روش — پس از دو رد متوالی مستقیماً به تنظیمات هدایت کنید تا کاربر را با توضیحات تکراری ناراحت نکنید و رتبه برنامه را کاهش ندهید.

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

shouldShowRequestPermissionRationale چه چیزی برمی‌گرداند؟

true — اگر درخواست قبلاً رد شده و Never Ask Again تنظیم نشده است. false — اگر مجوز درخواست نشده، اعطا شده یا برای همیشه مسدود شده است. ترکیب false + DENIED نیاز به بررسی از طریق پرچم اضافی دارد.

چه زمانی دیالوگ rationale را نشان دهیم؟

rationale را فقط پس از اولین رد کاربر، زمانی که shouldShowRequestPermissionRationale true برگرداند، نشان دهید. قبل از اولین درخواست rationale لازم نیست — این UX را بدتر می‌کند و دیالوگ‌های اضافی ایجاد می‌کند.

چگونه اولین درخواست را از Never Ask Again تشخیص دهیم؟

پرچم isFirstRequest را در SharedPreferences یا SavedStateHandle ذخیره کنید. اگر shouldShowRationale = false، checkSelfPermission = DENIED و پرچم = true — یعنی Never Ask Again فعال شده است. اگر پرچم = false — این اولین درخواست است.

در Never Ask Again چه باید کرد؟

دیالوگی با دکمه «باز کردن تنظیمات» نشان دهید که کاربر را به ACTION_APPLICATION_DETAILS_SETTINGS هدایت می‌کند. requestPermissions را دوباره فراخوانی نکنید — دیالوگ ظاهر نمی‌شود و نتیجه بدون پیام DENIED می‌آید.

چگونه shouldShowRequestPermissionRationale را تست کنیم؟

در تست‌های واحد از FakePermissionHandler با فیلد قابل تنظیم shouldShowRationale استفاده کنید. در تست‌های ابزاری — Espresso یا UIAutomator با شبیه‌سازی دیالوگ سیستمی. هر 4 وضعیت جدول را بررسی کنید.

خلاصه

  • shouldShowRequestPermissionRationale — متدی که ضرورت نمایش توضیح قبل از درخواست مجوز را تعیین می‌کند.
  • پس از اولین رد بدون Never Ask Again true، در سه حالت دیگر false برمی‌گرداند.
  • ترکیب false + DENIED — سخت‌ترین سناریو که برای تشخیص نیاز به پرچم اضافی دارد.
  • دیالوگ rationale فقط پس از رد نمایش داده می‌شود، نه قبل از اولین درخواست.
  • برای UX بهتر به جای دیالوگ مدال از bottom sheet یا عنصر درون‌خطی استفاده کنید.
  • در Never Ask Again — از طریق ACTION_APPLICATION_DETAILS_SETTINGS به تنظیمات هدایت کنید.
  • rationale زمینه‌ای متصل به لحظه استفاده از عملکرد، اعطا را تا 80 درصد افزایش می‌دهد.

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

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

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

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