KitKatで外部記憶領域の一部の読み書きがパミッションなしでできるようになりました。
また、READ_EXTERNAL_STORAGEも正式対応となりました。
そんな領域のお話です。

外部記憶領域

アンドロイドでは、画像や動画、音楽等の大きなファイルの保存領域として、外部記憶領域が存在します。外部記憶領域の代表的な物はSDカードですが、SDカードは抜き差し可能なため、アンドロイド内でファイルのアクセス制御をしたとしても、SDカードを端末から抜きPCに持っていくとアクセス制御ができなくなります。このためアンドロイドでは外部記憶領域の暗号化機能等も用意されましたが、最近ではメモリの単価が安くなってきた事と安全性を高める方向により、SDカードは用意せずに、内部メモリ内に仮想的な外部記憶領域を持つ端末が多くなってきています。

アプリケーションが外部記憶領域を使用する目的は2つあります。

  1. アプリケーション間でデータを共有する目的
  2. アプリケーション自身のみが使用するサイズの大きなデータを置く目的

カメラで撮った写真を、スライドショーアプリケーションで表示したり、SNSアプリケーションで投稿する場合は、1のアプリケーション間でデータを共有する目的となります。
電子書籍アプリがサーバからダウンロードした電子書籍ファイル等は2の自身のみが使用するサイズの大きいデータを置く目的となります。

外部記憶領域の使用は、これらの2つの目的が混在しているのですが、アンドロイドOSでは外部記憶領域のアクセス制限機能としてWRITE_EXTERNAL_STORAGEパミッションしか用意されていませんでした。Android OS 4.1で新たにREAD_EXTERNAL_STORAGEパミッションが加わりましたが、まだ移行期間という位置づけで正式対応ではなく、今後どのようになるかの詳しい説明もなかったため、対処のしようがなかったのですが、Android 4.4 KitKatで正式対応となりました。外部記憶領域の一部の読み書きがパミッションなしでアクセスできるようになった仕様変更と絡んで、うまくまとまった仕様となっています。

おさらい

WRITE_EXTERNAL_STORAGE

アプリケーションが外部記憶領域に書き込む事を許可します。
WRITE_EXTERNAL_STRRAGEを指定した場合は書き込みだけでなく読み込みも可能ですので、READ_EXTERNAL_STORAGEパミッションを指定する必要はありません。

READ_EXTERNAL_STORAGE

アプリケーションが外部記憶領域から読み込む事を許可します。

読み書きにパミッションがいらない外部記憶領域

KitKat以前は、外部記憶領域に書き込みする場合は、必ずパミッションが必要でしたが、KitKatでは、「外部記憶領域上のアプリケーションデータディレクトリ」は、パミッションが必要なくなりました。

ここでいう、「外部記憶領域上のアプリケーションデータディレクトリ」とは、
<外部記憶領域>/Android/data/<パッケージ名>/ディレクトリ
で、ContextクラスのgetExternalFilesDir(null)等で取得できるディレクトリをさします。

Nexus5の場合は以下のようなディレクトリとなります


/storage/emulated/0/Android/data/com.example.externaldir/

パスの中にパッケージ名が入っているため、他のアプリケーションと重複することなく使用できまた、アプリケーションをアンインストールした時に、同時にこのディレクトリは削除されるため、不必要なデータが端末上に残る事はありません。
今回の変更でこのディレクトリに対して書き込みする時WRITE_EXTERNAL_STORAGEは必要ありませんし、もちろん読み込む時もREAD_EXTERNAL_STORAGEは必要ありません。

この仕様変更により、先に述べた2のパターン(アプリ自身のみで使用するデータの保存)の場合パミッションを付ける必要がなくなりました。今まではダウンロードしたファイルの一次置き場として使用するだけの場合も、WRITE_EXTERNAL_STORAGEパミッションを付けなければいけませんでした。

WRITE_EXTERNAL_STORAGEパミッションは強力で端末の写真データを全て削除する事も出来ますし、INTERNETパミッションと組み合わせる事で、全ての写真データをネットワーク経由でどこかのサーバに吸い上げる事も出来てしまします。このような可能性があるのでアプリケーション作成者としては、ユーザの立場を考えるとあまり使用したくないパミッションだったのですが、仕様的に使わざるをえないパターンが多いパミッションでした。

使用者の立場から見てみると、現状沢山のアプリがWRITE_EXTERNAL_STORAGEを使っているため、WRITE_EXTERNAL_STORAGEが存在しないアプリを見つけるのが非常に難しく付いていても仕方がないとなっていたと思います。しかしKitKat以降は本当に共有データにアクセスする時だけパミッションが必要となりましたので、パミッションを持つアプリが減り、またアプリケーションの機能を見てパミッションが本当に必要なアプリなのか判断することができるようになります。

注意すべき点は、外部記憶領域上のアプリケーションデータディレクトリは特に保護されているわけではなく、暗号化が施されているわけでもありません。WRITEやREADのパミッションを持っていれば別のアプリケーションから参照可能です。従って今まで通り重要なデータを平文で置いたり、失ってはいけないデータを置くような事はしないでください。

読み書きにパミッションが必要な場合

「外部記憶領域上のアプリケーションデータディレクトリ」に自分自身が読み書きを行う場合はパミッションは必要ありませんが、その他の外部記憶領域に対しては今まで通りパミッションが必要です。

パミッションが必要な例

  • 写真ディレクトリ
  • 音楽ディレクトリ
  • 他のアプリケーションの外部記憶領域上のアプリケーションデータディレクトリ

先に記載した1に類するアプリケーション間でデータを共有するようなアプリケーションは引き続きパミッションが必要になりますが、このようなアプリでもKitKatから、READ_EXTERNAL_STORAGEが正式対応になった事による恩恵を受け、ユーザにとっても嬉しい仕様変更になっています

写真を加工するアプリは、写真を読み込むためにREAD_EXTERNAL_STORAGEは必要となります。加工したファイルを保存する時に他のアプリとも共有したいときは、書き込み権限を取得するが必要がありますが、アプリケーションによっては、加工したファイルをアプリ内でのみ共有する場合もあります。このような場合は書き込み権限を取得する必要はありません。

まとめ

このように、WRITE_EXTERNAL_STORAGEパミッションが必要な機能はかなり減る事となりました。安心してユーザにアプリケーションを使用してもらうためにも、大変良い仕様変更だと思いましたが…..
今回の仕様変更はKitKatからです。この変更を既存のアプリに適用してしまうと、KitKat以前のアプリケーションでは、Security Exceptionが出てしまいます。Google PlayではMultiple APK機能によりAPI Level別のアプリケーションを公開することができます。この機能を使用すれば、KitKat以降用としてSTRAGEパミッションを整理したバージョンと、それ以前のバージョンを同時に公開する事もできますが、そこまでされる方は少ないと思います。まだまだこの仕様変更の恩恵を受けるのは先の事だと思っています。
しかしながらKitKatの新機能を使うアプリケーションやプレインストールをするアプリケーション等では適用できますので、その時は是非忘れないでやってください。

図表となく文字ばかりで読みにくい記事になってしまいました。申し訳ありません。

ブログ内の関連する記事