shouldShowRequestPermissionRationale в Android — що це, логіка показу та реалізація

Автор: IT Sectr Опубліковано: 2026-05-20 Час читання: 8 хв

shouldShowRequestPermissionRationale — це метод Android API, який підказує розробнику, чи потрібно показати користувачеві пояснення перед запитом небезпечного дозволу. Згідно з Android Developer Reference, 2024, метод повертає true, якщо користувач раніше відхилив запит, але не встановив прапорець Never Ask Again. Це ключовий інструмент для побудови ввічливого UX під час роботи з дозволами часу виконання.

Головне

  • shouldShowRequestPermissionRationale — метод, який визначає, чи потрібно показувати пояснення перед запитом дозволу.
  • Повертає true після першої відмови користувача, якщо Never Ask Again не активовано.
  • Повертає false, якщо дозвіл ніколи не запитувався, надано або заблоковано назавжди.
  • Використовується для показу кастомного діалогу з поясненням, навіщо потрібен конкретний дозвіл.
  • При never ask again (false + denied) необхідно перенаправляти користувача в Налаштування.

Що таке shouldShowRequestPermissionRationale

shouldShowRequestPermissionRationale — це метод класів Activity та Fragment в Android, доступний через ActivityCompat для сумісності. Він приймає назву дозволу та повертає Boolean, який вказує, чи потрібно показати користувачеві додаткове пояснення перед повторним запитом. Метод з'явився в Android 6.0 Marshmallow разом із моделлю дозволів часу виконання.

Механізм обґрунтування побудований на відстеженні історії взаємодії користувача з діалогами дозволів. Система запам'ятовує, чи відхилив користувач запит раніше. Якщо відхилення відбулося без встановлення прапорця Never Ask Again, shouldShowRequestPermissionRationale повертає true. Це сигнал розробнику: користувач не розуміє, навіщо потрібен дозвіл, і потрібне додаткове пояснення. Згідно з Рекомендаціями Material Design від Google, показ діалогу обґрунтування після першої відмови збільшує ймовірність повторного надання дозволу на 35 відсотків.

Важливо розуміти семантику значень, що повертаються: true означає, що діалог має сенс показати, false — що діалог або не потрібен (дозвіл уже надано або ніколи не запитувався), або марний (Never Ask Again активний). Метод не є гарантією, що діалог буде показано — він лише дає рекомендацію. Розробник сам вирішує, який UI показати у відповідь.

Коли метод з'явився

shouldShowRequestPermissionRationale був представлений на рівні API 23 разом із групою методів для дозволів часу виконання. До Android 6.0 всі дозволи запитувалися під час встановлення, і механізм пояснення не був потрібен — користувач приймав або відхиляв весь список цілком. Модель часу виконання зробила можливою ситуацію, коли користувач відхиляє запит, не розуміючи контексту, і саме для цього потрібне обґрунтування.

Як працює shouldShowRequestPermissionRationale

Логіка методу виглядає наступним чином. При першому виклику requestPermissions для конкретного дозволу shouldShowRequestPermissionRationale повертає false — користувач ще не стикався з діалогом. Якщо користувач відхилив запит (натиснув Відхилити), метод починає повертати true. Після повторного відхилення з прапорцем Never Ask Again метод повертає false.

Повна таблиця станів:

СтанshouldShowRationalecheckSelfPermissionДія розробника
Не запитувавсяfalseDENIEDПоказати системний діалог
НаданоfalseGRANTEDВиконати функцію
Відхилено впершеtrueDENIEDПоказати обґрунтування, потім системний діалог
Never Ask AgainfalseDENIEDПеренаправити в Налаштування

Комбінація shouldShowRequestPermissionRationale = false та checkSelfPermission = DENIED — це найскладніший для обробки випадок. Він означає, що або дозвіл ніколи не запитувався, або встановлено Never Ask Again. Розробнику потрібно розрізнити ці два стани. Єдиний спосіб — зберігати прапорець isFirstRequest у SharedPreferences або використовувати SavedStateHandle. При першому запиті встановлюйте прапорець, і якщо shouldShowRationale повернув false, а прапорець уже true — це означає Never Ask Again.

Скидання стану

shouldShowRequestPermissionRationale скидається, якщо користувач видаляє та перевстановлює додаток, очищає дані додатка або скидає налаштування дозволів. Після перевстановлення метод знову поверне false для першого запиту. Системні оновлення та зміна версії Android не скидають історію — вона зберігається в даних додатка.

Реалізація діалогу обґрунтування

Правильна реалізація обґрунтування включає три компоненти: перевірку 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-патерни для обґрунтування

Найкращі практики Material Design рекомендують використовувати нижній аркуш або вбудований банер замість модального діалогу для обґрунтування. Нижній аркуш менш нав'язливий і дає користувачеві контекст. Вбудований елемент на екрані (наприклад, картка з поясненням і кнопкою Дозволити) показує, що функція недоступна без дозволу, але не блокує решту інтерфейсу.

Локалізація обґрунтування

Текст обґрунтування має бути локалізований і адаптований під конкретну функцію. Не використовуйте загальні фрази на кшталт «Це потрібно для роботи додатку». Вкажіть конкретно: «Для відображення погоди поруч із вами» або «Для збереження фото в галерею». Конкретні пояснення підвищують ймовірність надання дозволу на 50 відсотків згідно з дослідженнями UX від Google.

Обґрунтування vs Never Ask Again

Різниця між shouldShowRequestPermissionRationale = true (перша відмова) та false при DENIED (Never Ask Again) — ключовий момент в обробці дозволів. У першому випадку користувач вагався, і додаткове пояснення може переконати його надати доступ. У другому — користувач прийняв остаточне рішення, і повторний системний діалог лише викличе роздратування.

Алгоритм обробки після відмови має виглядати так:

  • Отримати результат DENIED з колбеку запиту
  • Викликати shouldShowRequestPermissionRationale
  • Якщо true — показати кастомний діалог обґрунтування з кнопкою Повторити
  • Якщо false — показати діалог з кнопкою Відкрити налаштування

Важливо не плутати порядок: спочатку перевіряти shouldShowRequestPermissionRationale, а не checkSelfPermission. checkSelfPermission все одно поверне DENIED в обох випадках. Тільки shouldShowRequestPermissionRationale відрізняє першу відмову від Never Ask Again. Використовуйте SavedStateHandle або SharedPreferences для зберігання прапорця «перший запит був» — це єдиний надійний спосіб відрізнити «не запитувався» від «заблоковано».

Найкращі практики показу обґрунтування

Показуйте обґрунтування лише один раз. Якщо користувач повторно відхилив запит після обґрунтування — більше не показуйте пояснення. Переходьте одразу до пропозиції відкрити налаштування. Багаторазовий показ обґрунтування сприймається як нав'язливість і знижує рейтинг додатка. Оптимальний сценарій: запит — відмова — обґрунтування — повторний запит — відмова — Налаштування.

Не показуйте обґрунтування до першого запиту. Деякі розробники помилково показують пояснення перед найпершим діалогом, аргументуючи це тим, що «користувач повинен зрозуміти». Це погіршує UX: користувач бачить два діалоги поспіль замість одного. Google рекомендує показувати системний діалог одразу, а обґрунтування — лише після відмови.

Використовуйте контекстне обґрунтування, прив'язане до моменту, коли функція дійсно потрібна. Не запитуйте всі дозволи при запуску додатка — це найнижчий показник надання. Запитуйте КАМЕРУ, коли користувач натиснув кнопку «Зробити фото», і МІСЦЕЗНАХОДЖЕННЯ, коли він відкрив карту. Контекстний запит у поєднанні з обґрунтуванням збільшує надання до 80 відсотків проти 30 відсотків при стартовому запиті.

Тестування сценаріїв обґрунтування

Тестування 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
        )
    }
}

Ключовий сценарій для інструментального тесту — перевірка, що діалог обґрунтування дійсно відображається після першої відмови. Використовуйте Espresso з idling resources для очікування системного діалогу, потім натисніть Відхилити, перевірте появу кастомного діалогу з текстом пояснення та натисніть Дозволити — перевірте надання. UIAutomator дозволяє взаємодіяти з системним діалогом за текстом кнопки, що робить тест більш стабільним.

Також варто протестувати сценарій відмови всередині діалогу обґрунтування. Якщо користувач натиснув Відхилити в кастомному поясненні, shouldShowRequestPermissionRationale має знову повернути true, оскільки Never Ask Again ще не активовано. Найкраща практика — після двох відмов поспіль одразу перенаправляти в Налаштування, щоб не дратувати користувача повторними поясненнями та не знижувати рейтинг додатка.

Часті запитання

Що повертає shouldShowRequestPermissionRationale?

true — якщо запит відхилявся раніше і не встановлено Never Ask Again. false — якщо дозвіл не запитувався, надано або заблоковано назавжди. Комбінація false + DENIED вимагає перевірки через додатковий прапорець.

Коли показувати діалог обґрунтування?

Показуйте обґрунтування лише після першої відмови користувача, коли shouldShowRequestPermissionRationale повернув true. До першого запиту обґрунтування не потрібне — це погіршує 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 — метод, який визначає необхідність показу пояснення перед запитом дозволу.
  • Повертає true після першої відмови без Never Ask Again, false — в інших трьох випадках.
  • Комбінація false + DENIED — найскладніший сценарій, що вимагає додаткового прапорця для розрізнення.
  • Діалог обґрунтування показується лише після відмови, не до першого запиту.
  • Використовуйте нижній аркуш або вбудований елемент замість модального діалогу для кращого UX.
  • При Never Ask Again — перенаправляйте в Налаштування через ACTION_APPLICATION_DETAILS_SETTINGS.
  • Контекстне обґрунтування, прив'язане до моменту використання функції, підвищує надання до 80 відсотків.

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також