ตั้งแต่ Android 6.0 Marshmallow ทาง Android ใช้ รูปแบบสิทธิ์ที่ช่วยปรับปรุงการติดตั้งแอปและ การอัปเดตอัตโนมัติ มีการขอสิทธิ์ระหว่างรันไทม์แทนที่จะเป็นก่อน การติดตั้งแอป นอกจากนี้ ผู้ใช้ยังเลือกที่จะปฏิเสธสิทธิ์บางอย่างได้ด้วย เพื่อให้ผู้ใช้มีความยืดหยุ่นเช่นนี้ คุณต้องตรวจสอบว่าแอปของคุณมีลักษณะการทำงาน จะมีผลเมื่อผู้ใช้เปิดหรือปิดสิทธิ์บางอย่าง
บริการ Google Play เองมีสิทธิ์รันไทม์ที่ผู้ใช้เลือกได้ ปฏิเสธแยกต่างหากจากการอนุญาตที่คำขอเฉพาะ แอปพลิเคชัน บริการ Google Play จะได้รับสิทธิ์ทั้งหมดที่จำเป็นโดยอัตโนมัติ เพื่อรองรับ API อย่างไรก็ตาม แอปก็ยังควรตรวจสอบและขอรันไทม์ ตามความเหมาะสมและจัดการกับข้อผิดพลาดอย่างเหมาะสมในกรณีที่ผู้ใช้ ได้ปฏิเสธสิทธิ์ที่จำเป็นสำหรับ API ที่แอปของคุณใช้กับบริการ Google Play
คุณควรจัดการความคาดหวังของผู้ใช้ในการกำหนดสิทธิ์ที่ ที่รันไทม์อาจจำเป็นต้องใช้ แนวทางปฏิบัติแนะนำต่อไปนี้จะช่วยให้คุณหลีกเลี่ยง ปัญหาที่อาจเกิดขึ้น
ข้อกำหนดเบื้องต้น
คุณจะต้องประกาศสิทธิ์ในไฟล์ AndroidManifest.xml
เช่น
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
หลักเกณฑ์
ยืนยันสิทธิ์ก่อนเรียกใช้ API
เมื่อคุณประกาศ API ที่ต้องการใช้ใน
AndroidManifest.xml
ไฟล์ โปรดตรวจสอบว่าคุณมีสิทธิ์ที่จำเป็น
ก่อนเรียกใช้ API ซึ่งทำได้โดยใช้เมธอด checkSelfPermission
ของ ActivityCompat
หรือ ContextCompat
หากการเรียกแสดงค่า "เท็จ" แสดงว่าไม่มีการให้สิทธิ์และคุณ
ควรใช้ requestPermissions
เพื่อส่งคำขอ การตอบสนองต่อกรณีนี้คือ
แสดงใน Callback ซึ่งคุณจะเห็นในขั้นตอนถัดไป
เช่น
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Check Permissions Now
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_LOCATION);
} else {
// permission has been granted, continue as usual
Task<Location> locationResult = LocationServices
.getFusedLocationProviderClient(this /** Context */)
.getLastLocation();
}
ใช้ Callback เกี่ยวกับสิทธิ์คำขอ
หากผู้ใช้ไม่ได้ให้สิทธิ์ที่แอปของคุณต้องการ
ควรเรียกเมธอด requestPermissions
เพื่อขอการเรียก
ให้ผู้ใช้ให้สิทธิ์ ระบบจะบันทึกคำตอบจากผู้ใช้ไว้ในส่วน
onRequestPermissionsResult
ติดต่อกลับ แอปของคุณควร
ให้ใช้สิ่งนี้และตรวจสอบมูลค่า
การแสดงผลเสมอเนื่องจากคำขออาจ
ปฏิเสธหรือยกเลิก คุณยังขอและตรวจสอบสิทธิ์หลายรายการได้ที่
เพียงครั้งเดียว ตัวอย่างต่อไปนี้จะตรวจหาเฉพาะสิทธิ์เดียวเท่านั้น
public void onRequestPermissionsResult(int requestCode,
String[] permissions,
int[] grantResults) {
if (requestCode == REQUEST_LOCATION) {
if(grantResults.length == 1
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// We can now safely use the API we requested access to
Task<Location> locationResult = LocationServices
.getFusedLocationProviderClient(this /** Context */)
.getLastLocation();
} else {
// Permission was denied or request was cancelled
}
}
}
แสดงเหตุผลของสิทธิ์
หากสิทธิ์ที่แอปของคุณขอจำเป็นสำหรับฟีเจอร์หลักของ และผู้ใช้เคยปฏิเสธคำขอสิทธิ์ก่อนหน้านี้ แอปของคุณควร แสดงคำอธิบายเพิ่มเติมก่อนขอสิทธิ์อีกครั้ง ผู้ใช้ มีแนวโน้มที่จะให้สิทธิ์มากขึ้นเมื่อเข้าใจเหตุผลในการให้สิทธิ์ เป็นสิ่งจำเป็นและจะได้รับประโยชน์โดยทันที
ในกรณีนี้ ก่อนโทรหา requestPermissions
คุณควรโทรหา
shouldShowRequestPermissionRationale
หากส่งคืน
จริง คุณควรสร้าง UI บางอย่างเพื่อแสดงบริบทเพิ่มเติมสำหรับฟิลด์
สิทธิ์
ตัวอย่างเช่น โค้ดของคุณอาจมีลักษณะดังนี้
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Check Permissions Now
private static final int REQUEST_LOCATION = 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},
ACCESS_FINE_LOCATION);
}
} else {
// permission has been granted, continue as usual
Task<Location> locationResult = LocationServices
.getFusedLocationProviderClient(this /** Context */)
.getLastLocation();
}
จัดการความล้มเหลวในการเชื่อมต่อ
หากแอปใช้ GoogleApiClient
ที่เลิกใช้งานแล้ว เมื่อคุณเรียกใช้
connect()
บริการ Google Play จะตรวจสอบว่า
สิทธิ์ที่จำเป็น connect()
ล้มเหลวเมื่อมีกลุ่มสิทธิ์ใดก็ได้
ที่บริการ Google Play ต้องการ
หากโทรหา connect()
ไม่สำเร็จ โปรดตรวจสอบว่าแอปเป็นผู้จัดการ
การเชื่อมต่อล้มเหลวอย่างถูกต้อง หากบริการ Google Play
ตัวเองไม่มีสิทธิ์ คุณสามารถเรียกใช้ startResolutionForResult()
เพื่อ
เริ่มขั้นตอนการใช้งานของผู้ใช้เพื่อแก้ไข
เช่น
@Override
public void onConnectionFailed(ConnectionResult result) {
if (mResolvingError) {
// Already attempting to resolve an error.
return;
} else if (result.hasResolution()) {
try {
mResolvingError = true;
result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
} catch (SendIntentException e) {
// There was an error with the resolution intent. Try again.
mGoogleApiClient.connect();
}
} else {
// Show dialog using GooglePlayServicesUtil.getErrorDialog()
showErrorDialog(result.getErrorCode());
mResolvingError = true;
}
}
การเรียก API แบบ GoogleApi
ที่ใหม่กว่าจะแสดงกล่องโต้ตอบโดยอัตโนมัติ (หาก
ไคลเอ็นต์จะสร้างอินสแตนซ์ด้วย Activity
) หรือการแจ้งเตือนในถาดระบบ (หาก
ไคลเอ็นต์จะสร้างอินสแตนซ์ด้วย Context
) ซึ่งผู้ใช้สามารถแตะเพื่อเริ่ม
ความตั้งใจในการแก้ปัญหาสิทธิ์ การโทรจะต้องมีการจัดคิวและลองใหม่เมื่อ
ได้รับสิทธิ์