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 Level 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

คำอธิบายเทียบกับ Never Ask Again

ความแตกต่างระหว่าง shouldShowRequestPermissionRationale = true (การปฏิเสธครั้งแรก) และ false กับ DENIED (Never Ask Again) เป็นจุดสำคัญในการจัดการสิทธิ์ ในกรณีแรก ผู้ใช้ลังเล และคำอธิบายเพิ่มเติมสามารถโน้มน้าวให้เขาให้การเข้าถึงได้ ในกรณีที่สอง ผู้ใช้ตัดสินใจครั้งสุดท้ายแล้ว และการทำซ้ำกล่องโต้ตอบระบบจะทำให้เกิดความหงุดหงิดเท่านั้น

อัลกอริทึมการจัดการหลังจากการปฏิเสธควรเป็นดังนี้:

  • รับผลลัพธ์ DENIED จาก callback ของคำขอ
  • เรียก 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 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม