shouldShowRequestPermissionRationale trong Android — khái niệm, logic hiển thị và triển khai

Tác giả: IT Sectr Đã đăng: 2026-05-20 Thời gian đọc: 8 phút

shouldShowRequestPermissionRationale là một phương thức của Android API cho nhà phát triển biết có cần hiển thị lời giải thích cho người dùng trước khi yêu cầu quyền nguy hiểm hay không. Theo Tài liệu Tham khảo Nhà phát triển Android, 2024, phương thức này trả về true nếu người dùng trước đó đã từ chối yêu cầu nhưng không đặt cờ Never Ask Again. Đây là công cụ chính để xây dựng UX lịch sự khi làm việc với quyền runtime.

Những điểm chính

  • shouldShowRequestPermissionRationale — phương thức xác định liệu có cần hiển thị lời giải thích trước khi yêu cầu quyền hay không.
  • Trả về true sau lần từ chối đầu tiên của người dùng nếu Never Ask Again chưa được kích hoạt.
  • Trả về false nếu quyền chưa bao giờ được yêu cầu, đã được cấp hoặc bị chặn vĩnh viễn.
  • Được sử dụng để hiển thị hộp thoại tùy chỉnh giải thích lý do cần quyền cụ thể.
  • Khi never ask again (false + denied), cần chuyển hướng người dùng đến Cài đặt.

shouldShowRequestPermissionRationale là gì

shouldShowRequestPermissionRationale là phương thức của các lớp Activity và Fragment trong Android, có sẵn qua ActivityCompat để tương thích. Nó nhận tên quyền và trả về Boolean cho biết có nên hiển thị cho người dùng lời giải thích bổ sung trước khi yêu cầu lại hay không. Phương thức này xuất hiện trong Android 6.0 Marshmallow cùng với mô hình quyền runtime.

Cơ chế giải thích được xây dựng dựa trên việc theo dõi lịch sử tương tác của người dùng với các hộp thoại quyền. Hệ thống ghi nhớ liệu người dùng đã từ chối yêu cầu trước đó hay chưa. Nếu việc từ chối xảy ra mà không đặt cờ Never Ask Again, shouldShowRequestPermissionRationale trả về true. Đây là tín hiệu cho nhà phát triển: người dùng không hiểu tại sao cần quyền này và cần giải thích thêm. Theo Nguyên tắc Thiết kế Material của Google, hiển thị hộp thoại giải thích sau lần từ chối đầu tiên làm tăng khả năng cấp lại quyền lên 35 phần trăm.

Điều quan trọng là hiểu ngữ nghĩa của các giá trị trả về: true có nghĩa là hiển thị hộp thoại có ý nghĩa, false có nghĩa là hộp thoại không cần thiết (quyền đã được cấp hoặc chưa bao giờ được yêu cầu) hoặc vô ích (Never Ask Again đang hoạt động). Phương thức này không đảm bảo rằng hộp thoại sẽ được hiển thị — nó chỉ đưa ra khuyến nghị. Nhà phát triển quyết định UI nào sẽ hiển thị để phản hồi.

Khi nào phương thức được giới thiệu

shouldShowRequestPermissionRationale được giới thiệu ở Cấp API 23 cùng với một nhóm phương thức cho quyền runtime. Trước Android 6.0, tất cả quyền được yêu cầu khi cài đặt và không cần cơ chế giải thích — người dùng chấp nhận hoặc từ chối toàn bộ danh sách cùng một lúc. Mô hình runtime đã tạo ra khả năng người dùng từ chối yêu cầu mà không hiểu ngữ cảnh, và chính vì điều này mà cần có giải thích.

Cách shouldShowRequestPermissionRationale hoạt động

Logic của phương thức hoạt động như sau. Ở lần gọi requestPermissions đầu tiên cho một quyền cụ thể, shouldShowRequestPermissionRationale trả về false — người dùng chưa gặp hộp thoại. Nếu người dùng từ chối yêu cầu (nhấn Từ chối), phương thức bắt đầu trả về true. Sau khi từ chối lặp lại với cờ Never Ask Again, phương thức trả về false.

Bảng trạng thái đầy đủ:

Trạng tháishouldShowRationalecheckSelfPermissionHành động của nhà phát triển
Chưa yêu cầufalseDENIEDHiển thị hộp thoại hệ thống
Đã cấpfalseGRANTEDThực thi chức năng
Từ chối lần đầutrueDENIEDHiển thị giải thích, sau đó hộp thoại hệ thống
Never Ask AgainfalseDENIEDChuyển hướng đến Cài đặt

Sự kết hợp shouldShowRequestPermissionRationale = false và checkSelfPermission = DENIED là trường hợp khó xử lý nhất. Nó có nghĩa là quyền chưa bao giờ được yêu cầu hoặc Never Ask Again đã được đặt. Nhà phát triển cần phân biệt hai trạng thái này. Cách duy nhất là lưu cờ isFirstRequest trong SharedPreferences hoặc sử dụng SavedStateHandle. Đặt cờ ở lần yêu cầu đầu tiên, và nếu shouldShowRationale trả về false trong khi cờ đã là true — điều đó có nghĩa là Never Ask Again.

Đặt lại trạng thái

shouldShowRequestPermissionRationale được đặt lại nếu người dùng gỡ cài đặt và cài đặt lại ứng dụng, xóa dữ liệu ứng dụng hoặc đặt lại cài đặt quyền. Sau khi cài đặt lại, phương thức sẽ lại trả về false cho lần yêu cầu đầu tiên. Cập nhật hệ thống và thay đổi phiên bản Android không đặt lại lịch sử — nó được lưu trong dữ liệu ứng dụng.

Triển khai hộp thoại giải thích

Triển khai đúng cách giải thích bao gồm ba thành phần: kiểm tra shouldShowRequestPermissionRationale sau khi từ chối, hiển thị hộp thoại tùy chỉnh với lời giải thích và gọi lại requestPermissions sau phản hồi tích cực của người dùng. Hộp thoại phải ngắn gọn, cụ thể và giải thích tại sao ứng dụng cần quyền đặc biệt này.

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("Tại sao cần quyền truy cập vị trí")
        .setMessage(
            "Ứng dụng sử dụng vị trí để đánh dấu" +
            " các địa điểm trên bản đồ. Nếu không có quyền này," +
            " chức năng sẽ không hoạt động."
        )
        .setPositiveButton("Cho phép") { _, _ ->
            requestPermissionLauncher.launch(permission)
        }
        .setNegativeButton("Hủy", null)
        .show()
}

Mẫu UI cho giải thích

Các thực hành tốt nhất của Material Design khuyên dùng bottom sheet hoặc banner nội dòng thay vì hộp thoại modal cho giải thích. Bottom sheet ít xâm phạm hơn và cung cấp ngữ cảnh cho người dùng. Một phần tử nội dòng trên màn hình (ví dụ: thẻ có giải thích và nút Cho phép) cho thấy chức năng không khả dụng nếu không có quyền, nhưng không chặn phần còn lại của giao diện.

Bản địa hóa giải thích

Văn bản giải thích cần được bản địa hóa và điều chỉnh theo chức năng cụ thể. Đừng sử dụng các cụm từ chung chung như “Điều này cần thiết để ứng dụng hoạt động.” Hãy chỉ rõ: “Để hiển thị thời tiết gần bạn” hoặc “Để lưu ảnh vào thư viện.” Giải thích cụ thể làm tăng khả năng cấp quyền lên 50 phần trăm theo Nghiên cứu UX của Google.

Giải thích so với Never Ask Again

Sự khác biệt giữa shouldShowRequestPermissionRationale = true (từ chối lần đầu) và false với DENIED (Never Ask Again) là điểm mấu chốt trong xử lý quyền. Trong trường hợp đầu, người dùng đã do dự và giải thích thêm có thể thuyết phục họ cấp quyền truy cập. Trong trường hợp thứ hai, người dùng đã đưa ra quyết định cuối cùng và việc lặp lại hộp thoại hệ thống sẽ chỉ gây ra sự khó chịu.

Thuật toán xử lý sau khi từ chối sẽ như sau:

  • Nhận kết quả DENIED từ callback yêu cầu
  • Gọi shouldShowRequestPermissionRationale
  • Nếu true — hiển thị hộp thoại giải thích tùy chỉnh với nút Thử lại
  • Nếu false — hiển thị hộp thoại với nút Mở Cài đặt

Điều quan trọng là không nhầm lẫn thứ tự: kiểm tra shouldShowRequestPermissionRationale trước, không phải checkSelfPermission. checkSelfPermission vẫn sẽ trả về DENIED trong cả hai trường hợp. Chỉ shouldShowRequestPermissionRationale mới phân biệt được lần từ chối đầu tiên với Never Ask Again. Sử dụng SavedStateHandle hoặc SharedPreferences để lưu cờ “đã yêu cầu lần đầu” — đây là cách duy nhất đáng tin cậy để phân biệt “chưa yêu cầu” với “đã bị chặn.”

Thực hành tốt nhất khi hiển thị giải thích

Hiển thị giải thích chỉ một lần. Nếu người dùng từ chối lại yêu cầu sau khi thấy giải thích, đừng hiển thị giải thích nữa. Hãy chuyển thẳng sang đề nghị mở Cài đặt. Hiển thị giải thích nhiều lần bị coi là quấy rầy và làm giảm điểm đánh giá ứng dụng. Kịch bản tối ưu: yêu cầu — từ chối — giải thích — yêu cầu lại — từ chối — Cài đặt.

Đừng hiển thị giải thích trước lần yêu cầu đầu tiên. Một số nhà phát triển sai lầm khi hiển thị giải thích trước hộp thoại đầu tiên, lý luận rằng “người dùng phải hiểu.” Điều này làm xấu UX: người dùng thấy hai hộp thoại liên tiếp thay vì một. Google khuyến nghị hiển thị hộp thoại hệ thống ngay lập tức và chỉ hiển thị giải thích sau khi từ chối.

Sử dụng giải thích theo ngữ cảnh gắn liền với thời điểm chức năng thực sự cần thiết. Đừng yêu cầu tất cả quyền khi khởi động ứng dụng — đây là tỷ lệ cấp thấp nhất. Yêu cầu CAMERA khi người dùng nhấn nút “Chụp ảnh” và VỊ TRÍ khi họ mở bản đồ. Yêu cầu theo ngữ cảnh kết hợp với giải thích làm tăng tỷ lệ cấp lên 80 phần trăm so với 30 phần trăm khi yêu cầu lúc khởi động.

Kiểm tra các kịch bản giải thích

Kiểm tra shouldShowRequestPermissionRationale yêu cầu xác minh bốn trạng thái trong bảng: chưa yêu cầu, đã cấp, đã từ chối, Never Ask Again. Trong kiểm thử đơn vị, sử dụng FakePermissionHandler với hành vi shouldShowRationale có thể cấu hình. Trong kiểm thử thiết bị, sử dụng UiAutomator hoặc Espresso với mô phỏng phản hồi hộp thoại.

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
        )
    }
}

Kịch bản chính cho kiểm thử thiết bị là xác minh rằng hộp thoại giải thích thực sự xuất hiện sau lần từ chối đầu tiên. Sử dụng Espresso với idling resources để chờ hộp thoại hệ thống, sau đó nhấn Từ chối, kiểm tra sự xuất hiện của hộp thoại giải thích tùy chỉnh và nhấn Cho phép — xác minh việc cấp quyền. UIAutomator cho phép tương tác với hộp thoại hệ thống bằng văn bản nút, làm cho kiểm thử ổn định hơn.

Cũng nên kiểm tra kịch bản từ chối bên trong hộp thoại giải thích. Nếu người dùng nhấn Từ chối trong giải thích tùy chỉnh, shouldShowRequestPermissionRationale sẽ lại trả về true, vì Never Ask Again chưa được kích hoạt. Thực hành tốt nhất là chuyển hướng đến Cài đặt sau hai lần từ chối liên tiếp để tránh làm phiền người dùng với các giải thích lặp lại và làm giảm điểm đánh giá ứng dụng.

Câu hỏi thường gặp

shouldShowRequestPermissionRationale trả về gì?

true — nếu yêu cầu đã bị từ chối trước đó và Never Ask Again chưa được đặt. false — nếu quyền chưa bao giờ được yêu cầu, đã được cấp hoặc bị chặn vĩnh viễn. Sự kết hợp false + DENIED yêu cầu kiểm tra qua cờ bổ sung.

Khi nào nên hiển thị hộp thoại giải thích?

Chỉ hiển thị giải thích sau lần từ chối đầu tiên của người dùng, khi shouldShowRequestPermissionRationale trả về true. Trước lần yêu cầu đầu tiên, giải thích là không cần thiết — điều này làm xấu UX và tạo ra các hộp thoại không cần thiết.

Làm thế nào để phân biệt yêu cầu đầu tiên với Never Ask Again?

Lưu cờ isFirstRequest trong SharedPreferences hoặc SavedStateHandle. Nếu shouldShowRationale = false, checkSelfPermission = DENIED và cờ là true — Never Ask Again đang hoạt động. Nếu cờ là false — đây là yêu cầu đầu tiên.

Làm gì khi Never Ask Again?

Hiển thị hộp thoại với nút “Mở Cài đặt” chuyển hướng người dùng đến ACTION_APPLICATION_DETAILS_SETTINGS. Đừng gọi requestPermissions lại — hộp thoại sẽ không xuất hiện và kết quả sẽ trả về DENIED mà không có thông báo.

Làm thế nào để kiểm tra shouldShowRequestPermissionRationale?

Trong kiểm thử đơn vị, sử dụng FakePermissionHandler với trường shouldShowRationale có thể cấu hình. Trong kiểm thử thiết bị, sử dụng Espresso hoặc UIAutomator với mô phỏng hộp thoại hệ thống. Kiểm tra tất cả 4 trạng thái từ bảng.

Tổng kết

  • shouldShowRequestPermissionRationale — phương thức xác định liệu có cần hiển thị giải thích trước khi yêu cầu quyền hay không.
  • Trả về true sau lần từ chối đầu tiên không có Never Ask Again, false trong ba trường hợp còn lại.
  • Sự kết hợp false + DENIED là kịch bản khó nhất, yêu cầu cờ bổ sung để phân biệt.
  • Hộp thoại giải thích chỉ được hiển thị sau khi từ chối, không phải trước lần yêu cầu đầu tiên.
  • Sử dụng bottom sheet hoặc phần tử nội dòng thay vì hộp thoại modal để có UX tốt hơn.
  • Khi Never Ask Again đang hoạt động — chuyển hướng đến Cài đặt qua ACTION_APPLICATION_DETAILS_SETTINGS.
  • Giải thích theo ngữ cảnh gắn với thời điểm sử dụng chức năng làm tăng tỷ lệ cấp lên 80 phần trăm.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm