ตั้งแต่ Android 6.0 Marshmallow เป็นต้นไป Android ใช้รูปแบบสิทธิ์ที่ปรับปรุงกระบวนการติดตั้งแอปและการอัปเดตอัตโนมัติให้มีประสิทธิภาพยิ่งขึ้น ระบบจะขอสิทธิ์ระหว่างรันไทม์แทนที่จะขอก่อนการติดตั้งแอป นอกจากนี้ ผู้ใช้ยังเลือกปฏิเสธสิทธิ์บางอย่างได้ด้วย หากต้องการให้ผู้ใช้มีความยืดหยุ่นนี้ คุณต้องตรวจสอบว่าแอปทำงานตามที่คาดไว้เมื่อผู้ใช้เปิดหรือปิดใช้สิทธิ์บางอย่าง
บริการ Google Play เองมีสิทธิ์รันไทม์ที่ผู้ใช้เลือกปฏิเสธแยกต่างหากจากสิทธิ์เหล่านั้นที่แอปของคุณขอโดยเฉพาะได้ บริการ Google Play จะได้รับสิทธิ์ทั้งหมดที่จําเป็นเพื่อรองรับ API โดยอัตโนมัติ อย่างไรก็ตาม แอปของคุณควรตรวจสอบและขอสิทธิ์รันไทม์ตามที่จำเป็น รวมถึงจัดการข้อผิดพลาดอย่างเหมาะสมในกรณีที่ผู้ใช้ปฏิเสธไม่ให้สิทธิ์ Google Play บริการที่จำเป็นสำหรับ API ที่แอปของคุณใช้
แนวทางปฏิบัติแนะนำคือจัดการความคาดหวังของผู้ใช้ในการตั้งค่าสิทธิ์ที่รันไทม์อาจต้องใช้ แนวทางปฏิบัติแนะนำต่อไปนี้จะช่วยคุณหลีกเลี่ยงปัญหาที่อาจเกิดขึ้น
ข้อกำหนดเบื้องต้น
คุณจะต้องประกาศสิทธิ์ในไฟล์ AndroidManifest.xml
เช่น
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
หลักเกณฑ์
ยืนยันสิทธิ์ก่อนเรียก API
เมื่อประกาศ API ที่ต้องการใช้ในไฟล์ AndroidManifest.xml
แล้ว ให้ตรวจสอบว่าคุณมีสิทธิ์ที่จำเป็นก่อนที่จะเรียกใช้ API ซึ่งทำได้โดยใช้เมธอด checkSelfPermission
ของ ActivityCompat
หรือ ContextCompat
หากการเรียกใช้แสดงผลเป็นเท็จ แสดงว่ายังไม่มีการให้สิทธิ์และคุณควรใช้ requestPermissions
เพื่อขอสิทธิ์ ระบบจะแสดงผลลัพธ์ของการเรียกกลับซึ่งคุณจะเห็นในขั้นตอนถัดไป
เช่น
Kotlin
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Request Permissions Now ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), REQUEST_LOCATION_PERMISSION_CODE) } else { // permission has been granted, continue as usual val locationResult = LocationServices .getFusedLocationProviderClient(this /* Context */) .lastLocation }
Java
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Request Permissions Now ActivityCompat.requestPermissions( this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_PERMISSION_CODE); } else { // permission has been granted, continue as usual TasklocationResult = LocationServices .getFusedLocationProviderClient(this /** Context */) .getLastLocation(); }
ใช้การติดต่อกลับเพื่อขอสิทธิ์
หากผู้ใช้ยังไม่ได้ให้สิทธิ์ที่จําเป็นสําหรับแอป คุณควรเรียกใช้เมธอด requestPermissions
เพื่อขอให้ผู้ใช้ให้สิทธิ์ ระบบจะบันทึกคําตอบของผู้ใช้ไว้ในการเรียกกลับ onRequestPermissionsResult
แอปของคุณควรใช้วิธีนี้และตรวจสอบค่าผลลัพธ์เสมอ เนื่องจากคำขออาจถูกปฏิเสธหรือยกเลิก นอกจากนี้ คุณยังขอและตรวจสอบสิทธิ์หลายรายการพร้อมกันได้ด้วย ตัวอย่างต่อไปนี้จะตรวจสอบสิทธิ์เพียงรายการเดียว
Kotlin
fun onRequestPermissionsResult( requestCode: Int, permissions: Array, grantResults: IntArray ) { if (requestCode == REQUEST_LOCATION_PERMISSION_CODE) { if (grantResults.singleOrNull() == PackageManager.PERMISSION_GRANTED) { // We can now safely use the API we requested access to val locationResult: Task = LocationServices .getFusedLocationProviderClient(this /* Context */) .lastLocation // Request the last known location. } else { // Permission was denied or request was cancelled } } }
Java
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == REQUEST_LOCATION_PERMISSION_CODE) { if(grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // We can now safely use the API we requested access to TasklocationResult = LocationServices .getFusedLocationProviderClient(this /** Context */) .getLastLocation(); // Request the last known location. } else { // Permission was denied or request was cancelled } } }
แสดงเหตุผลของสิทธิ์
หากสิทธิ์ที่แอปขอจําเป็นสําหรับฟีเจอร์หลักของแอปและผู้ใช้เคยปฏิเสธคําขอสิทธิ์ไว้ แอปของคุณควรแสดงคําอธิบายเพิ่มเติมก่อนที่จะขอสิทธิ์อีกครั้ง ผู้ใช้มีแนวโน้มที่จะให้สิทธิ์มากขึ้นเมื่อเข้าใจเหตุผลที่ต้องมีสิทธิ์และประโยชน์ที่ได้รับทันที
ในกรณีนี้ ก่อนโทรหา requestPermissions
คุณควรโทรหา shouldShowRequestPermissionRationale
หากผลลัพธ์คือ "จริง" คุณควรสร้าง UI เพื่อแสดงบริบทเพิ่มเติมสําหรับสิทธิ์
ตัวอย่างเช่น โค้ดอาจมีลักษณะดังนี้
Kotlin
private const val REQUEST_LOCATION_PERMISSION_CODE = 2 if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Check Permissions Now if ActivityCompat.shouldShowRequestPermissionRationale( this, Manifest.permission.ACCESS_FINE_LOCATION ) { // Display UI and wait for user interaction } else { ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), REQUEST_LOCATION_PERMISSION_CODE) } } else { // Permission has already been granted, continue as usual val locationResult: Task= LocationServices .getFusedLocationProviderClient(this /* Context */) .lastLocation }
Java
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Check Permissions Now private static final int REQUEST_LOCATION_PERMISSION_CODE = 2; if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) { // Display UI and wait for user interaction } else { ActivityCompat.requestPermissions( this, new String[]{Manifest.permission.LOCATION_FINE}, REQUEST_LOCATION_PERMISSION_CODE); } } else { // permission has been granted, continue as usual TasklocationResult = LocationServices .getFusedLocationProviderClient(this /** Context */) .getLastLocation(); }
การเรียก API ของบริการ Google Play จะแสดงกล่องโต้ตอบ (หากสร้างอินสแตนซ์ไคลเอ็นต์ด้วย Activity
) หรือการแจ้งเตือนในถาดระบบ (หากสร้างอินสแตนซ์ไคลเอ็นต์ด้วย Context
) โดยอัตโนมัติ ซึ่งผู้ใช้แตะเพื่อเริ่มความตั้งใจในการแก้ไขสิทธิ์ได้ ระบบจะจัดคิวการโทรและลองอีกครั้งเมื่อได้รับสิทธิ์