從 Android 6.0 Marshmallow 開始 權限模型,可簡化應用程式安裝和訓練過程 自動更新程序。請改為在執行階段要求權限,而不是之前要求的權限 應用程式安裝。此外,使用者也可以選擇拒絕特定權限。 如要讓使用者享有彈性,請務必確保應用程式以下列方式 預期使用者啟用/停用特定權限時的狀況。
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
。
如果呼叫傳回 false,表示系統未授予您相關權限
應使用 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;
}
}
較新的 GoogleApi
型 API 呼叫將自動顯示對話方塊 (如果
用戶端已由 Activity
例項化,或是系統匣通知 (如果
用戶端已由 Context
例項化,使用者只要輕觸即可啟動
權限解析意圖系統會將呼叫排入佇列,並在
已授予適當權限