ตั้งแต่ 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
เพื่อขอสิทธิ์ การตอบกลับนี้จะแสดงผลในการเรียกกลับซึ่งคุณจะเห็นในขั้นตอนถัดไป
เช่น
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();
}
ติดตั้งใช้งานโค้ดเรียกกลับเพื่อขอสิทธิ์
หากผู้ใช้ไม่ได้ให้สิทธิ์ที่แอปต้องการ ควรเรียกใช้เมธอด 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
) ที่ผู้ใช้แตะเพื่อเริ่มจุดประสงค์การแก้ไขปัญหาสิทธิ์ได้ ระบบจะจัดคิวการโทรและลองใหม่เมื่อได้รับสิทธิ์แล้ว