●はじめに
JellyBeanでREAD_EXTERNAL_STORAGE権限が追加されました。READ_EXTERNAL_STORAGE権限は外部SDカードの読み込みを制御するものです。
JBにおいて、この権限は将来有効化される"予約された権限"という位置付けです。
(SDカードを読み込むアプリは、将来READ_EXTERNAL_STORAGE権限が必要になるということです)
そのため、JBでのREAD_EXTERNAL_STORAGE権限は何の効力も持ちません。
宣言を見ても、テスト用であることがわかります。
<!-- Allows an application to read from external storage --> <permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS" android:label="@string/permlab_sdcardRead" android:description="@string/permdesc_sdcardRead" android:protectionLevel="normal" />http://tools.oesf.biz/android-4.1.2_r1.0/xref/frameworks/base/core/res/AndroidManifest.xml#692
将来のためにも、SDカードの読み込みが必要なアプリはREAD_EXTERNAL_STORAGE権限を要求するようにしましょう。
●動作確認
JBでは、開発者オプションでSDカードの読み込み時にREAD_EXTERNAL_STORAGE権限を必須にすることが可能です。これを活用すれば、将来READ_EXTERNAL_STORAGE権限が必須になった場合の予行練習が可能です。
これを設定するには、
[設定]>[開発者向けオプション]>[SDカードの保護]
にチェックを付けます。 ※Nexus7の場合は[USBストレージの保護]になっています。
これで、SDカードの読み込み時にREAD_EXTERNAL_STORAGE権限がチェックされるようになります。
# 2012/10/22現在、最新のエミュレータ(SDK Platform 16 Rev.2)ではこの確認を実施できない可能性があります。
# この環境では何度試してもエラーが発生しませんでした。
あとは、下記のようなコードでSDにアクセスすれば動作確認できます。
File sdFile = new File(Environment.getExternalStorageDirectory(), "/memo.txt"); try { FileInputStream fis = new FileInputStream(sdFile); fis.read(); fis.close(); // TODO: move finally section. } catch (Exception e) { }READ_EXTERNAL_STORAGE権限を持っていないと、下記のようなエラーが発生します。
java.io.FileNotFoundException: /storage/sdcard0/memo.txt: open failed: EACCES (Permission denied) at libcore.io.IoBridge.open(IoBridge.java:416) at java.io.FileInputStream.<init>(FileInputStream.java:78) at com.example.sdcardread.MainActivity.onResume(MainActivity.java:28) ... Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied) at libcore.io.Posix.open(Native Method) at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110) at libcore.io.IoBridge.open(IoBridge.java:400) ... 18 more
ただし、WRITE_EXTERNAL_STORAGE権限を持っていると、READ_EXTERNAL_STORAGE権限を持っていなく
ても、SDカードの読み込みは可能です。
これは、WRITE_EXTERNAL_STORAGE権限がREAD_EXTERNAL_STORAGE権限を内包しているためです。
この辺りはPackageParserの128行目にSplitPermissionとして定義されています。
new PackageParser.SplitPermissionInfo[] { // READ_EXTERNAL_STORAGE is always required when an app requests // WRITE_EXTERNAL_STORAGE, because we can't have an app that has // write access without read access. The hack here with the target // target SDK version ensures that this grant is always done. new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE, new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE }, android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),http://tools.oesf.biz/android-4.1.2_r1.0/xref/frameworks/base/core/java/android/content/pm/PackageParser.java#128
●そのほか
GBでのSDマウントポイントは /mnt/sdcard が主流でした。ICSでは /mnt/sdcard/external_sd。
しかし、JBでは /storage/sdcard0/ が主流となりつつあるようです。
この辺はキャリアによって様々です。
動作確認の際、試験ファイルのpush先には注意しましょう。
以上です。