Google Play 開発者サービスと実行時の権限

Android 6.0 Marshmallow 以降、Android は 権限モデルによって、アプリのインストールと 自動的に更新されることはありません。権限のリクエストは、事前ではなく実行時に行われる インストールできます。また、ユーザーは特定の権限を拒否するよう選択することもできます。 このような柔軟性をユーザーに提供するには、アプリが ユーザーが特定の権限を有効または無効にすると想定されます。

Google Play 開発者サービス自体に実行時の権限があり、ユーザーはその権限を選択できます。 管理者が明示的に要求する権限とは別に 説明します。Google Play 開発者サービスは、必要なすべての権限を自動的に取得します。 構築していますただし、アプリは引き続きランタイムを確認してリクエストする必要があります。 許可し、ユーザーが誤ってアクセスした場合、 が、アプリで使用する API に必要な権限を Google Play 開発者サービスに拒否しました。

権限を設定する際は、ユーザーの期待を管理することが ランタイムで必要になる場合があります。次のベスト プラクティスは、 役立ちます。

前提条件

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 コールバック。アプリは 常に戻り値をチェックしてください。これは、リクエストが 拒否またはキャンセルされました複数の権限のリクエストと確認は、 次のサンプルでは、1 つの権限のみをチェックします。

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 でインスタンス化されます)。ユーザーはこれをタップして 権限の解決インテント。通話はキューに追加され、 権限が付与されます。