API 29
AndroidX
Multi Runtime Permissions
GPSは ACCESS_FINE_LOCATION のパーミッションが必要です。
また外部のストレージに書き込むときには WRITE_EXTERNAL_STORAGE も必要となります。
この2つはAndroidManifestに登録するだけではなくユーザーの許可を必要とするRuntime Prmissionです。更にユーザーの許可を必要とする場面で複数のパーミッションを許可を得られるようにします。
GPS と 外部ストレージ書き込み許可
例えば、最初に位置情報へのアクセス許可を尋ねます。
その後、続けて同じ許可を求めるステージで
メディアファイルへのアクセス許可を確認するダイアログが表示。
![[Android]複数の Runtime Permission 設定を GPSで実行する 1x1.trans - [Android]複数の Runtime Permission 設定を GPSで実行する](https://akira-watson.com/wp-content/themes/simplicity2/images/1x1.trans.gif)
このような形でパーミッションの許可を取得するようにコードを記述していきます。
ここでどちらかを「許可しない」とすると、これ以降この場面では許可しなかったパーミッションだけを確認するようにします。
例として位置情報は許可して、メディアアクセスを許可しない選択をした後では、次回から表示しないという選択肢が増えます。
requestPermissions
複数のパーミッションを扱うには、配列あるいはArrayとして例えばPERMISSIONS[]を作り requestPermissions() をコールします。
1 2 3 4 5 6 7 8 9 |
// 複数のパーミッションを扱う String[] PERMISSIONS = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.WRITE_CONTACTS, Manifest.permission.READ_SMS, Manifest.permission.CAMERA}; // ... ActivityCompat.requestPermissions(this, PERMISSIONS, REQUEST_CODE); |
onRequestPermissionsResult
onRequestPermissionsResult から結果を受け取りますが、permissions[]のインデックスに応じてgrantResults[]が、拒否ならば「-1」、許可すれば「0」が返ってきます。それぞれの結果を確認して、全て許可されない場合はユーザーに拒否された機能が使えないと明示して終わります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == REQUEST_MULTI_PERMISSIONS) { if (grantResults.length > 0) { for (int i = 0; i < permissions.length; i++) { if (permissions[i]. equals(Manifest.permission.ACCESS_FINE_LOCATION)) { if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { // 許可された } else { // それでも拒否された時の対応 } } else if (permissions[i]. equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { // 許可された } else { // それでも拒否された時の対応 } } } } } } |
サンプルコード
GPS パーミッションを考慮して実装する で説明した内容を元に、パーミッションを複数の Runtime Permission に対応させています。
パーミッションを得た後でGPSと外部ストレージの保存をする手前までです。
AndroidManifest.xml
1 2 3 4 5 6 7 8 9 10 11 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" ... <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application ... </application> </manifest> |
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
package com.example.testmultipermission; import androidx.appcompat.app.AppCompatActivity; import androidx.annotation.NonNull; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; //import android.support.annotation.NonNull; //import android.support.v4.content.ContextCompat; //import android.support.v7.app.AppCompatActivity; //import android.support.v4.app.ActivityCompat; import android.os.Bundle; import android.content.pm.PackageManager; import android.util.Log; import android.view.Gravity; import android.Manifest; import android.os.Build; import android.widget.Toast; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { private static final int REQUEST_MULTI_PERMISSIONS = 101; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Android 6, API 23以上でパーミッシンの確認 if(Build.VERSION.SDK_INT >= 23){ checkMultiPermissions(); } else{ startLocationService(); } } // 位置情報、外部書き込み許可の確認 private void checkMultiPermissions(){ // 位置情報の Permission int permissionLocation = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION); // 外部ストレージ書き込みの Permission int permissionExtStorage = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE); ArrayList<String> reqPermissions = new ArrayList<>(); // 位置情報の Permission が許可されているか確認 if (permissionLocation == PackageManager.PERMISSION_GRANTED) { Log.d("debug","permissionLocation: GRANTED"); } else{ Log.d("debug","request ACCESS_FINE_LOCATION"); reqPermissions.add(Manifest.permission.ACCESS_FINE_LOCATION); } // 外部ストレージ書き込みが許可されているか確認 if (permissionExtStorage == PackageManager.PERMISSION_GRANTED) { Log.d("debug","permissionExtStorage: GRANTED"); } else{ Log.d("debug","request WRITE_EXTERNAL_STORAGE"); reqPermissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); } // 未許可 if (!reqPermissions.isEmpty()) { ActivityCompat.requestPermissions(this, reqPermissions.toArray(new String[0]), REQUEST_MULTI_PERMISSIONS); } else{ startLocationService(); } } // 結果の受け取り @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == REQUEST_MULTI_PERMISSIONS) { Log.d("debug","REQUEST_MULTI_PERMISSIONS"); if (grantResults.length > 0) { for (int i = 0; i < permissions.length; i++) { // 位置情報 if (permissions[i]. equals(Manifest.permission.ACCESS_FINE_LOCATION)) { if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { Log.d("debug","ACCESS_FINE_LOCATION: GRANTED"); } else { // それでも拒否された時の対応 toastMake("位置情報の許可がないので計測できません"); } } // 外部ストレージ else if (permissions[i]. equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { Log.d("debug","WRITE_EXTERNAL_STORAGE: GRANTED"); } else { // それでも拒否された時の対応 toastMake("外部書込の許可がないので書き込みできません"); } } } startLocationService(); } } } private void startLocationService() { // GPS 測位 // 位置情報を外部ストレージに保存 // ... } // トーストの生成 private void toastMake(String message){ Toast toast = Toast.makeText(this, message, Toast.LENGTH_LONG); // 位置調整 toast.setGravity(Gravity.CENTER, 0, 200); toast.show(); } } |
位置測定とそれを外部ストレージに保存するコードは以下を参考にしてください
関連ページ:
- FusedLocationProviderClient による位置情報取得
- GPSでの位置情報
- GPS パーミッションを考慮して実装する
- GPSログをテキストで保存、複数の Runtime Permissionの設定
- バックグラウンドでGPSログを取り続けるには
- Runtime Permission, Android 6.0 からの変更
References:
LocationManager | Android Developers
Criteria | Android Developers
Runtime Permissions | Android Developers
Location Strategies | Android Developers
Location | Android Developers