Google Play 服務和執行階段權限

從 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 方法完成此操作 ActivityCompatContextCompat

如果呼叫傳回 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 例項化,使用者只要輕觸即可啟動 權限解析意圖系統會將呼叫排入佇列,並在 已授予適當權限