3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Android/Java】権限の取得方法から取得後の処理

Last updated at Posted at 2021-04-27

今回は、

  • アプリ起動時にカメラ、ストレージ、位置情報権限を取得したい
  • 途中で位置情報権限を許可しないに変えることを想定
  • ボタン押下時に位置情報権限がない場合は権限取得OSダイアログ表示

をするための方法をまとめる。

複数の権限を取得する方法

requestPermissionsを扱うが、パッと調べた限りだと3つある。
1.ActivityCompat#requestPermissions

public static void requestPermissions (Activity activity, String[] permissions, int requestCode)
そもそもActivityCompatクラスって何なの?と気にしたことがなかったのでそのついで公式ドキュメントをみると

Helper for accessing features in Activity.

とあった。このクラスのメソッドの大半は引数にActivityが必要だったので、必要になったら確認することにする。

2.Activity#requestPermissions

public final void requestPermissions (String[] permissions, int requestCode)
ActivityクラスはAPI1からなので、Androidの元祖みたいなものだと思うが、このrequestPermissionsは意外にもAPI23から。

3.Fragment#requestPermissions

public final void requestPermissions (String[] permissions, int requestCode)
ただこれはAPI23で追加されたもののAPI28で非推奨となっているので注意。この代わりに何を使えば良いかは後述。

以上の3つは使える環境に合わせてどれを使っても変わらない気もする(一語一句公式の説明を読んだわけではないが)。今回は実際に使っていた環境がFragmentクラスだったので(今や非推奨だが)、3のFragment#requestPermissionsを扱う

取得したい権限はManifestに記載する必要がある。AndroidManifest.xmlでapplicationタグの上に

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />

ACCESS_MEDIA_LOCATIONはAPI29からの権限になるが、OSバージョン分岐せずにしていても特に大丈夫そう。この権限は

Allows an application to access any geographic locations persisted in the user's shared collection.

とあるが、確か画像から位置情報を取得するときにAPI29以上なら必要だった覚えが。。(残課題)

Fragmentクラス内で

private static final int REQUEST_PERMISSION = 1000;
private static String[] permissions = {
    Manifest.permission.ACCESS_FINE_LOCATION,
    Manifest.permission.READ_EXTERNAL_STORAGE,
    Manifest.permission.WRITE_EXTERNAL_STORAGE,
    Manifest.permission.ACCESS_MEDIA_LOCATION,
    Manifest.permission.CAMERA
};

/*
 * 中略
 */

ActivityCompat.requestPermissions(this.getActivity(), permissions, REQUEST_PERMISSION);

これでpermissions配列内の権限全てがチェックされ、不足している権限OSダイアログが表示される。

権限を許可・拒否した次の処理

一度でも実装したことがある人には周知のことだが、以下のように書くと権限取得結果関係なしに次の処理が実行されてしまう

ActivityCompat.requestPermissions(this.getActivity(), permissions, REQUEST_PERMISSION);

//次の処理
doNextTask();

もし権限を取得できたら次の処理を実行したい場合はonRequestPermissionsResultをオーバーライドする必要がある。

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    if (requestCode == REQUEST_PERMISSION_LOCATION) {
        if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            //許可された場合
            doNextTask();
        }
    }
}

第一引数(requestCode)はrequestPermissionsの第三引数になるので、上のサンプルだとREQUEST_PERMISSION_LOCATIONと一致していたらOK。
第三引数(grantResults)の0番目はユーザーがOSダイアログで許可したのかどうかの結果が返ってくる。
 許可:PERMISSION_GRANTED
 拒否:PERMISSION_GRANTED
 要素数0:ユーザーがキャンセルした

onRequestPermissionsResultが呼ばれないことがあった

実際に実装していると、なぜかFragment内でrequestPermissionsを実行してもonRequestPermissionsResultが呼ばれずに時間を要したことがあった。ちなみにとある修正をする前までは普通に動いていたのだが、なぜか関係ないと思っている修正をした後だとNGになった。

呼ばれない原因・対策を調べ、こちらの記事を読んでみたものの該当する内容はなし。

結果としてはFragmentクラスでもonRequestPermissionsResultをオーバーライドしていたが、親ActivityクラスでもonRequestPermissionsResultをオーバーライドしていていたことが原因だった。
Fragment#requestPermissionsでも親Activity側のonRequestPermissionsResultが呼ばれる様子。なのでその時は全て親Activity側にまとめるように修正した。

クリックイベント時に権限あるかないかみて処理を分ける

ボタン押下時に位置情報権限がある場合は任意の処理を、権限がない場合は権限取得OS表示するように実装

//細かい設定は省略
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            //位置情報権限が既にある場合
        } else {
            //ない場合は再度リエクエスト
            requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSION_LOCATION);
        }
    }
});

これで位置情報権限は取得されるまで要求がループされます。

参考文献(本文中で記載していないもの)

環境

  • Android Studio4.1.2
  • Android10
3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?