概要
Android で SD カードにデータを書き込む方法です。Android 6.0 以降では、権限設定に変更があります。
確認環境
- Android Studio 2.1.2
- Build Tools Version 24.0.1
- Compile SDK Version 23
- Target SDK Version 23
- 実行環境 Sony SOV32 Android 6.0, API 23
参考情報
公式の情報。Android 6.0 (API level 23) 以降での権限要求の方法が説明されている。
対処方法
AndroidManifest.xml に uses-permission
を追加することは Android 5.1 以前までと同じ。インストール時、ユーザーに権限を要求する。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Android 6.0 以降では、実行時にも権限を要求する。
現在の権限は、設定アプリから確認できる。
SOV32 の場合は、設定アプリを起動したのち アプリ > アプリの設定(歯車アイコン) > アプリの権限 > ストレージ
と辿れば確認できる。
これら設定のON/OFFは checkSelfPermission
メソッドを呼ぶことで PERMISSION_GRANTED/PERMISSION_DENIED
として得られる。
つまり、checkSelfPermission
メソッドは、
アプリに権限が与えられている時に PERMISSION_GRANTED
を返し、
与えられていない時に PERMISSION_DENIED
を返す。
アプリに権限が与えられていない場合には、requestPermissions
メソッドにより権限を要求する。
requestPermissions
メソッドを実行するとシステムダイアログが表示され、許可/拒否の選択をユーザーに要求する。
ユーザーが許可/拒否を選択すると onRequestPermissionsResult
メソッドが呼ばれる。SD カードのディレクトリパスは getExternalStorageDirectory
メソッドにより得られる。
補足
Android 6.0 (API level 23) 以降では、システム権限が 2 つに分類される。
- Normal 権限 : ユーザーのプライバシーに直接的なリスクとならない。
- Dangerous 権限 : ユーザーの機密情報への読み書きを許すことになる。ユーザーが許可を明示する必要がある。
デバイスの Android Version とアプリの Target SDK Version によって、権限要求の振る舞いが異なる。
- Android Version ≦ 5.1 もしくは Target SDK Version ≦ 22 ならば、アプリ実行時に権限は自動的に与えられる。
- Android Version ≧ 6.0 かつ Target SDK Version ≧ 23 ならば、アプリ実行時に Dangerous 権限を要求し、ユーザーは許可/拒否を選択する。
AndroidManifest.xml にて要求する権限を指定することは同じである。
また、本投稿のサンプルコードでは省略しているが、権限を要求する理由をユーザーに伝える事が推奨される。
ユーザーとしては、説明なく許可/拒否の選択を求められても判断がつかない。
しかし、頻繁に確認を求められるとユーザーは煩わしく感じ、アプリの使用をやめてしまう恐れがある。
このような場合のために shouldShowRequestPermissionRationale
メソッドが用意されている。
shouldShowRequestPermissionRationale
が true を返した場合のみ、権限を要求する理由をユーザーに提示するように実装すれば良い。
ユーザーへの提示は何らかの形で自ら実装する必要がある。