ขอสิทธิ์เข้าถึงตำแหน่งขณะรันไทม์

ก่อนขอสิทธิ์เข้าถึงตำแหน่งที่รันไทม์ โปรดอ่านตัวเลือกและแนวทางปฏิบัติแนะนำสำหรับการเข้าถึงตำแหน่ง รวมถึงคำแนะนำในการลดคำขอสิทธิ์ แหล่งข้อมูลเหล่านี้จะช่วยคุณตัดสินใจว่าจะขอสิทธิ์ใด และปุ่มตำแหน่งเป็นทางเลือกที่ดีกว่าสำหรับกรณีการใช้งานของคุณหรือไม่

หลักเกณฑ์ในการเข้าถึงสิทธิ์เข้าถึงตำแหน่ง

กฎทั่วไปบางข้อที่ควรปฏิบัติตามเมื่อตัดสินใจว่าจะใช้การเข้าถึงตำแหน่งในแอปอย่างไร

เข้าถึงตำแหน่งในบริบท

เมื่อฟีเจอร์ในแอปต้องการสิทธิ์เข้าถึงตำแหน่ง คุณต้องรอจนกว่าผู้ใช้จะโต้ตอบกับฟีเจอร์ดังกล่าวก่อนที่จะส่งคำขอสิทธิ์ ซึ่งเป็นไปตามแนวทางปฏิบัติแนะนำในการขอสิทธิ์รันไทม์ในบริบท ตามที่อธิบายไว้ในคู่มือที่อธิบายวิธีขอสิทธิ์ของแอป

รูปที่ 1 แสดงวิธีดำเนินการตามกระบวนการนี้ แอปมีฟีเจอร์ "แชร์ตำแหน่ง" ที่ต้องใช้สิทธิ์เข้าถึงตำแหน่งในเบื้องหน้า อย่างไรก็ตาม แอปจะไม่ขอสิทธิ์เข้าถึงตำแหน่งจนกว่าผู้ใช้จะเลือกปุ่มแชร์ตำแหน่ง

หลังจากผู้ใช้เลือกปุ่มแชร์ตำแหน่ง กล่องโต้ตอบสิทธิ์เข้าถึงตำแหน่งของระบบจะปรากฏขึ้น
รูปที่ 1 ฟีเจอร์การแชร์ตำแหน่งที่ต้องใช้สิทธิ์เข้าถึงตำแหน่งในเบื้องหน้า ฟีเจอร์นี้จะเปิดใช้หากผู้ใช้เลือกอนุญาตขณะใช้แอปเท่านั้น

ผู้ใช้ให้สิทธิ์เข้าถึงตำแหน่งโดยประมาณเท่านั้นได้

ใน Android 12 (API ระดับ 31) ขึ้นไป ผู้ใช้สามารถขอให้แอปของคุณดึงข้อมูลตำแหน่งโดยประมาณเท่านั้น แม้ว่าแอปจะขอสิทธิ์รันไทม์ ACCESS_FINE_LOCATION ก็ตาม

เพื่อจัดการกับพฤติกรรมของผู้ใช้ที่อาจเกิดขึ้นนี้ อย่าขอสิทธิ์ ACCESS_FINE_LOCATION เพียงอย่างเดียว แต่ให้ขอทั้งสิทธิ์ ACCESS_FINE_LOCATION และสิทธิ์ ACCESS_COARSE_LOCATION ในคำขอรันไทม์เดียวแทน หากคุณพยายามขอเฉพาะ ACCESS_FINE_LOCATION ระบบจะไม่สนใจคำขอใน Android 12 บางรุ่น หากแอปกำหนดเป้าหมายเป็น Android 12 ขึ้นไป ระบบจะบันทึกข้อความแสดงข้อผิดพลาดต่อไปนี้ใน Logcat

ACCESS_FINE_LOCATION must be requested with ACCESS_COARSE_LOCATION.

เมื่อแอปขอทั้ง ACCESS_FINE_LOCATION และ ACCESS_COARSE_LOCATION กล่องโต้ตอบสิทธิ์ของระบบจะมีตัวเลือกต่อไปนี้ให้ผู้ใช้

  • ตำแหน่งที่แน่นอน: อนุญาตให้แอปได้รับข้อมูลตำแหน่งที่แน่นอน
  • โดยประมาณ: อนุญาตให้แอปเข้าถึงเฉพาะข้อมูลตำแหน่งโดยประมาณ

รูปที่ 3 แสดงให้เห็นว่ากล่องโต้ตอบมีภาพที่ช่วยให้ผู้ใช้เลือกตัวเลือกทั้ง 2 ตัวเลือกได้ หลังจากผู้ใช้ตัดสินใจเลือกความแม่นยำของตำแหน่งแล้ว ผู้ใช้จะแตะปุ่มใดปุ่มหนึ่งจาก 3 ปุ่มเพื่อเลือกระยะเวลาของการให้สิทธิ์

ใน Android 12 ขึ้นไป ผู้ใช้สามารถไปที่การตั้งค่าระบบเพื่อตั้งค่าความแม่นยำของตำแหน่งที่ต้องการสำหรับแอปใดก็ได้ ไม่ว่าแอปนั้นจะมีเวอร์ชัน SDK เป้าหมายใดก็ตาม ซึ่งรวมถึงกรณีที่แอปของคุณติดตั้งอยู่ในอุปกรณ์ที่ใช้ Android 11 หรือต่ำกว่า แล้วผู้ใช้อัปเกรดอุปกรณ์เป็น Android 12 ขึ้นไป

กล่องโต้ตอบจะอ้างอิงถึงตำแหน่งโดยประมาณเท่านั้นและมีปุ่ม 3 ปุ่มเรียงซ้อนกัน
รูปที่ 2 กล่องโต้ตอบสิทธิ์ของระบบที่ปรากฏขึ้นเมื่อแอปของคุณขอ ACCESS_COARSE_LOCATION เท่านั้น
กล่องโต้ตอบมีตัวเลือก 2 ชุด โดยชุดหนึ่งอยู่เหนืออีกชุดหนึ่ง
รูปที่ 3 กล่องโต้ตอบสิทธิ์ของระบบที่ปรากฏขึ้นเมื่อแอปขอทั้ง ACCESS_FINE_LOCATION และ ACCESS_COARSE_LOCATION ในคำขอรันไทม์เดียว

ตัวเลือกของผู้ใช้ส่งผลต่อการให้สิทธิ์

ตารางต่อไปนี้แสดงสิทธิ์ที่ระบบมอบให้แอปของคุณ โดยอิงตามตัวเลือกที่ผู้ใช้เลือกในกล่องโต้ตอบรันไทม์ของสิทธิ์

แน่นอน โดยประมาณ
ขณะใช้แอป ACCESS_FINE_LOCATION และ
ACCESS_COARSE_LOCATION
ACCESS_COARSE_LOCATION
เฉพาะครั้งนี้ ACCESS_FINE_LOCATION และ
ACCESS_COARSE_LOCATION
ACCESS_COARSE_LOCATION
ปฏิเสธ ไม่มีสิทธิ์เข้าถึงตำแหน่ง ไม่มีสิทธิ์เข้าถึงตำแหน่ง

หากต้องการตรวจสอบว่าระบบให้สิทธิ์ใดแก่แอปของคุณบ้าง ให้ตรวจสอบค่าที่แสดงผลของคำขอสิทธิ์ คุณสามารถใช้ไลบรารี Jetpack ในโค้ดที่คล้ายกับโค้ดต่อไปนี้ หรือจะใช้ไลบรารีแพลตฟอร์มที่คุณจัดการโค้ดคำขอสิทธิ์ด้วยตนเองก็ได้

Kotlin

@RequiresApi(Build.VERSION_CODES.N)
fun requestPermissions() {
    val locationPermissionRequest = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { permissions ->
        when {
            permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false) -> {
                // Precise location access granted.
            }
            permissions.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false) -> {
                // Only approximate location access granted.
            }
            else -> {
                // No location access granted.
            }
        }
    }

    // Before you perform the actual permission request, check whether your app
    // already has the permissions, and whether your app needs to show a permission
    // rationale dialog. For more details, see Request permissions:
    // https://developer.android.com/training/permissions/requesting#request-permission
    locationPermissionRequest.launch(
        arrayOf(
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION
        )
    )
}

Java

private void requestPermissions() {

    ActivityResultLauncher<String[]> locationPermissionRequest =
            registerForActivityResult(new ActivityResultContracts
                            .RequestMultiplePermissions(), result -> {

                Boolean fineLocationGranted = null;
                Boolean coarseLocationGranted = null;

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    fineLocationGranted = result.getOrDefault(
                            Manifest.permission.ACCESS_FINE_LOCATION, false);
                    coarseLocationGranted = result.getOrDefault(
                            Manifest.permission.ACCESS_COARSE_LOCATION,false);
                }

                if (fineLocationGranted != null && fineLocationGranted) {
                    // Precise location access granted.
                } else if (coarseLocationGranted != null && coarseLocationGranted) {
                    // Only approximate location access granted.
                } else {
                    // No location access granted.
                }
            }
        );

    // ...

    // Before you perform the actual permission request, check whether your app
    // already has the permissions, and whether your app needs to show a permission
    // rationale dialog. For more details, see Request permissions.
    locationPermissionRequest.launch(new String[] {
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION
    });
}

ขออัปเกรดเป็นตำแหน่งที่แน่นอน

คุณสามารถขอให้ผู้ใช้อัปเกรดสิทธิ์เข้าถึงของแอปจากตำแหน่งโดยประมาณเป็นตำแหน่งที่แน่นอนได้ อย่างไรก็ตาม ก่อนที่จะขอให้ผู้ใช้อัปเกรดสิทธิ์เข้าถึงตำแหน่งที่แน่นอนของแอป ให้พิจารณาว่ากรณีการใช้งานของแอปจำเป็นต้องใช้ความแม่นยำระดับนี้หรือไม่ หากแอปของคุณต้องจับคู่อุปกรณ์กับอุปกรณ์ที่อยู่ใกล้เคียงผ่านบลูทูธหรือ Wi-Fi ให้พิจารณาใช้การจับคู่อุปกรณ์ที่ใช้ร่วมกันหรือสิทธิ์เข้าถึงบลูทูธแทนการขอสิทธิ์ ACCESS_FINE_LOCATION

หากต้องการขอให้ผู้ใช้อัปเกรดสิทธิ์เข้าถึงตำแหน่งของแอปจากตำแหน่งโดยประมาณเป็นตำแหน่งที่แน่นอน ให้ทำดังนี้

  1. หากจำเป็น ให้อธิบายเหตุผลที่แอปของคุณต้องการสิทธิ์
  2. ขอสิทธิ์ ACCESS_FINE_LOCATION และ ACCESS_COARSE_LOCATION พร้อมกันอีกครั้ง เนื่องจากผู้ใช้ได้อนุญาตให้ระบบให้สิทธิ์เข้าถึงตำแหน่งโดยประมาณแก่แอปของคุณแล้ว กล่องโต้ตอบของระบบจึงแตกต่างออกไปในครั้งนี้ ดังที่แสดงในรูปที่ 4 และรูปที่ 5
กล่องโต้ตอบมีตัวเลือก &quot;เปลี่ยนเป็นตำแหน่งที่แน่นอน&quot; &quot;เฉพาะครั้งนี้&quot; และ &quot;ปฏิเสธ&quot;
รูปที่ 4 ก่อนหน้านี้ผู้ใช้เลือกโดยประมาณและขณะใช้แอป (ในกล่องโต้ตอบจากรูปที่ 3)
กล่องโต้ตอบมีตัวเลือก &quot;เฉพาะครั้งนี้&quot; และ &quot;ปฏิเสธ&quot;
รูปที่ 5 ก่อนหน้านี้ผู้ใช้เลือกโดยประมาณและเฉพาะครั้งนี้ (ในกล่องโต้ตอบจากรูปที่ 3)

ขอตำแหน่งในเบื้องหน้าเท่านั้นในตอนแรก

แม้ว่าฟีเจอร์หลายรายการในแอปของคุณต้องใช้สิทธิ์เข้าถึงตำแหน่ง แต่ก็เป็นไปได้ว่ามีเพียงบางฟีเจอร์เท่านั้นที่ต้องใช้สิทธิ์เข้าถึงตำแหน่งในเบื้องหลัง ดังนั้น เราขอแนะนำให้แอปของคุณทำคำขอแบบเพิ่มทีละส่วนสำหรับสิทธิ์เข้าถึงตำแหน่ง โดยขอสิทธิ์เข้าถึงตำแหน่งในเบื้องหน้าก่อน แล้วจึงขอสิทธิ์เข้าถึงตำแหน่งในเบื้องหลัง การส่งคำขอแบบเพิ่มขึ้นจะช่วยให้ผู้ใช้ควบคุมและมีความโปร่งใสมากขึ้น เนื่องจากผู้ใช้จะเข้าใจได้ดีขึ้นว่าฟีเจอร์ใดในแอปที่ต้องเข้าถึงตำแหน่งในเบื้องหลัง

รูปที่ 6 แสดงตัวอย่างแอปที่ออกแบบมาเพื่อจัดการคำขอแบบเพิ่มทีละส่วน ทั้งฟีเจอร์ "แสดงตำแหน่งปัจจุบัน" และ "แนะนำสถานที่ใกล้เคียง" ต้องใช้สิทธิ์เข้าถึงตำแหน่งในเบื้องหน้า อย่างไรก็ตาม มีเพียงฟีเจอร์ "แนะนำสถานที่ใกล้เคียง" เท่านั้นที่ต้องใช้สิทธิ์เข้าถึงตำแหน่งในเบื้องหลัง

ปุ่มที่เปิดใช้การเข้าถึงตำแหน่งในเบื้องหน้าอยู่ห่างจากปุ่มที่เปิดใช้ตำแหน่งในเบื้องหลังครึ่งหน้าจอ
รูปที่ 6 ทั้ง 2 ฟีเจอร์ต้องใช้สิทธิ์เข้าถึงตำแหน่ง แต่มีเพียงฟีเจอร์ "แนะนำสถานที่น่าสนใจในบริเวณใกล้เคียง" เท่านั้นที่ต้องใช้สิทธิ์เข้าถึงตำแหน่งในเบื้องหลัง

ขั้นตอนการส่งคำขอแบบเพิ่มขึ้นมีดังนี้

  1. ในตอนแรก แอปควรแนะนำผู้ใช้ไปยังฟีเจอร์ที่ต้องใช้สิทธิ์เข้าถึงตำแหน่งในเบื้องหน้า เช่น ฟีเจอร์ "แชร์ตำแหน่ง" ในรูปที่ 1 หรือฟีเจอร์ "แสดงตำแหน่งปัจจุบัน" ในรูปที่ 2

    เราขอแนะนำให้คุณปิดใช้สิทธิ์เข้าถึงของผู้ใช้สำหรับฟีเจอร์ที่ต้องใช้สิทธิ์เข้าถึงตำแหน่งในเบื้องหลังจนกว่าแอปจะมีสิทธิ์เข้าถึงตำแหน่งในเบื้องหน้า

  2. ในภายหลัง เมื่อผู้ใช้สำรวจฟีเจอร์ที่ต้องใช้สิทธิ์เข้าถึงตำแหน่งในเบื้องหลัง คุณสามารถขอสิทธิ์เข้าถึงตำแหน่งในเบื้องหลังได้

แหล่งข้อมูลเพิ่มเติม

ดูข้อมูลเพิ่มเติมเกี่ยวกับสิทธิ์เข้าถึงตำแหน่งใน Android ได้จากแหล่งข้อมูลต่อไปนี้

Codelab

วิดีโอ

ตัวอย่าง