FC2ブログ
ヽ|∵|ゝ(Fantom) の 開発blog? ホーム »Androidリファレンス
このページの記事一覧

【Android】【Java】パーミッションの付与(許可)のチェックと要求をする  


 Android 6.0 以降からは実行時のパーミッションリクエストができるが、ググったら「ContextCompat」(または「ActivityCompat」)での例がほとんどだったので、敢えて「~Compat」を使わない実装を書いておこうと思った。実際に「~Compat」はサポートライブラリが必要となるので、使えない環境で書きたい場合もあるだろう。もちろん Android6.0(API 23)以降になってしまうが、私も Unity のプラグインでは今回の方法を用いている(サポートライブラリ等、他のライブラリを入れるとファイルサイズも大きくなるため、ほぼ全ての実装を自前でやっている)。

 なので「~Compat」で書きたい場合は、公式のデベロッパーマニュアルに載っているので、そちらの方を見れば良いだろう(基本的には同じ内容である)。

(参考)
実行時のパーミッション リクエスト


(※) Android Studio 3.1.2 / Galaxy S7 Edge (Android 7.0) / Windows10(x64) で確認



■パーミッションの許可/拒否をチェックする(static メソッド)

 ここでは汎用的に使えるように、static で定義したものを書いておこう。ライブラリとして保存しておけば使い回しも簡単にできる。

●パーミッションの許可/拒否をチェックする(static メソッド)
import android.content.Context;
import android.content.pm.PackageManager;

//パーミッションの許可(付与)チェック
public static final boolean checkPermission(final Context context, final String permission) {
final PackageManager pm = context.getPackageManager();
return (pm.checkPermission(permission, context.getPackageName()) == PackageManager.PERMISSION_GRANTED);
}

●使用例(メインでのコードなど)
import android.util.Log;

//※アクティビティでの使用例
boolean granted = checkPermission(this, "android.permission.WRITE_EXTERNAL_STORAGE"); //this は Context
Log.d("DebugTag", "granted = " + granted);

granted = false (または true)

 ここでの結果はパーミッションが許可(付与)されてない状態として false が返ってきているが、元々許可されている場合は true になる。ちなみに「READ_EXTERNAL_STORAGE」(ストレージのファイル読み取り権限)というものもあるが、これは「WRITE_EXTERNAL_STORAGE」(ストレージのファイル読み書き権限)が許可されていれば、true になる。

 また「AndroidManifedt.xml」での書き方は、基本的に <manifest>~</manifest> タグの中に書く。以下に例を挙げておこう。

●AndroidManifedt.xml に「WRITE_EXTERNAL_STORAGE」パーミッションを書く例
<manifest ~・・・(略)・・・ >
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

・・・(略)・・・
</manifest>

 パーミッション自体の文字列定数は公式のデベロッパーマニュアルを見て欲しい。

(参考)
Manifest.permission (Constant Value を使う)
<uses-permission> (name 属性だけでも良い)



■パーミッションのチェックとその理由→要求をする(インスタンス メソッド)

 次にリアルタイムにパーミッションをチェックし、必要なら(許可されてなければ)そのパーミッションが必要な理由と要求ダイアログを出す方法をやってみよう。またここでは前述した static な checkPermission() を使っても良いが、単一のアクティビティ上での実装として、インスタンスメソッドで書くことにしよう。実際には static で書いても構わない(ちなみに Unity のプラグインは static で書いてある)。

●パーミッションのチェックとその理由→要求をする(※アクティビティでの実装例)
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.widget.Toast;

//定数など
//https://developer.android.com/reference/android/Manifest.permission.html
private static final String PERMISSION_WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE"; //ストレージの読み書き権限
private static final int REQUEST_WRITE_EXTERNAL_STORAGE = 1; //※番号は任意:onRequestPermissionsResult() で合わせる

//パーミッションの許可(付与)チェック
//https://developer.android.com/training/permissions/requesting#perm-check
private boolean checkPermission(String permission) {
final PackageManager pm = getPackageManager();
return pm.checkPermission(permission, getPackageName()) == PackageManager.PERMISSION_GRANTED;
}

//パーミッションの根拠と要求(API 23 [Android 6.0])
//https://developer.android.com/training/permissions/requesting#make-the-request
private void showPermissionRationaleAndRequest(final String permission, final int requestCode) {
if (android.os.Build.VERSION.SDK_INT >= 23) { //Android 6.0

//パーミッション要求の根拠の説明を必要とするか?「今後表示しない」をチェックすると常に false になる。
boolean isShouldRationale = shouldShowRequestPermissionRationale(permission); //API 23 (Android 6.0)
if (isShouldRationale) {
//根拠の説明ダイアログを必要とするとき
AlertDialog.Builder builder = new AlertDialog.Builder(this); //this は Context //※この実装では画面回転で消えるので注意
builder.setTitle("以下の理由で○○の権限が必要です。")
.setMessage("・説明1\n・説明2\n・説明3")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
requestPermission(permission, requestCode);
}
})
.show();
} else {
//根拠の説明ダイアログ不要のとき
requestPermission(permission, requestCode);
}
}
}

//パーミッションを要求する(API 23 [Android 6.0])
private void requestPermission(String permission, int requestCode) {
if (android.os.Build.VERSION.SDK_INT >= 23) { //Android 6.0
requestPermissions(new String[]{ permission }, requestCode);
}
}

//パーミッション要求の結果コールバックハンドラ(API 23 [Android 6.0])
//https://developer.android.com/training/permissions/requesting#handle-response
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_WRITE_EXTERNAL_STORAGE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "ユーザーによってストレージ読み書き権限が許可されました。", Toast.LENGTH_SHORT).show(); //this は Context
} else {
Toast.makeText(this, "ユーザーによってストレージ読み書き権限が拒否されました。", Toast.LENGTH_SHORT).show(); //this は Context
}
return;
}
}
}

●使用例(メインでのコードなど)
import android.util.Log;

//※アクティビティでの使用例
boolean isGranted = checkPermission(PERMISSION_WRITE_EXTERNAL_STORAGE); //現在のパーミッションをチェック
Log.d("DebugTag", PERMISSION_WRITE_EXTERNAL_STORAGE + "\nisGranted = " + isGranted);

if (!granted) {
//パーミッションが付与されてないとき、根拠の説明と要求をする(ダイアログを出す)
Log.d("DebugTag", PERMISSION_WRITE_EXTERNAL_STORAGE + ", requestCode = " + REQUEST_WRITE_EXTERNAL_STORAGE);
showPermissionRationaleAndRequest(PERMISSION_WRITE_EXTERNAL_STORAGE, REQUEST_WRITE_EXTERNAL_STORAGE); //API 23 (Android 6.0)
}


 注意して欲しいのはあくまでも、あらかじめ「AndroidManifest.xml」に書かれているパーミッションでしか要求はできないという点だ。その書き方は前述の「AndroidManifest.xml にパーミッションを書く例」を参考にして欲しい。

 根拠の説明ダイアログは「AlertDialog」を利用しているが、このままでは画面回転などで消えるので注意して欲しい。今回はテーマから外れるので必要あればデベロッパーマニュアルなどを参照して欲しい。またダイアログ内のメッセージも手抜きしているが(笑)、権限によって内容を変えるにはあらかじめメッセージを定義しておくことも必要だろう。リクエストコード(requestCode)は任意なので、その辺りで紐づけしても良いかも知れない。

 またこの実装では2つ以上同時に権限要求すると、ダイアログが重なってしまうという欠点もある。もしそういう必要があるなら、要求を Queue のようなもので管理すると良い(LinkedList 等でも可)。ちょっと難しいかも知れないが、挑戦してみるのも良いだろう。


(参考)
ダイアログを表示する
実行時のパーミッション リクエスト
パーミッションの確認
必要なパーミッションのリクエスト
パーミッション リクエストへの応答の処理


(関連記事)
【Android】【Java】AlertDialog を使ってみる
【Android】【Java】WIFI接続ONを取得する
【Android】【Java】WIFI, Bluetooth 接続の暗黙的Intent
【Android】【Java】SDカードからテキストファイルを読み込む
【Android】【Java】SDカードから画像ファイルを読み込む
【Android】【Java】SDカードに画像ファイルを保存する(png)
【Android】【Java】SDカードに画像ファイルを保存する(jpg)
【Android】【Java】SDカードのファイルを削除する


スポンサーサイト

category: Android

thread: プログラミング

janre: コンピュータ

tag: Androidライブラリ  Androidリファレンス  Java 
tb: 0   cm: --


プロフィール

Social

検索フォーム

全記事一覧

カテゴリ

ユーザータグ

最新記事

リンク

PR

▲ Pagetop