Android で外部ファイルを保存する場合、どこに何を保存すれば良いのか?それぞれの違いは何なのか?
内蔵メモリなのか?SDカードなのか?
いい加減しっかり把握しておきたいと思ったので、まとめてみました。
ざっくりまとめ
それぞれの領域の名前は、この記事の中で区別するためにつけたもので、アクセス権減は非 root ユーザから見た図です。
ディレクトリ取得メソッド | アプリ専用? | ユーザがアクセス可能? | クリア方法 | アプリ削除時に | |
---|---|---|---|---|---|
内部データ領域 | Context.getFilesDir() | yes | no | データを消去 | 消える |
内部キャッシュ領域 | Context.getCacheDir() | yes | no | キャッシュを消去 | 消える |
外部データ領域 | Context.getExternalFilesDir() | yes | yes | データを消去 | 消える |
外部キャッシュ領域 | Context.getExternalCacheDir() | yes | yes | キャッシュを消去 | 消える |
外部公開領域 | Environment.getExternalStorageDirectory() | no | yes | 提供されず | 消えない |
外部公開共有領域 | Environment.getExternalStoragePublicDirectory() | no | yes | 提供されず | 消えない |
- ユーザに見せたくないファイルは内部の領域を使う
- 消えるとアプリが維持できなくなるようなファイルは、内部データ領域
- 消えても全く問題ないような一時ファイルは、ユーザが消しやすいキャッシュ領域が良さそう
- アプリが消えても消したくないファイルは、外部公開領域にディレクトリ掘って作る
- 端末全体に共有したいようなファイルは外部公開共有領域に入れる
- カメラから取得した画像を保存するなら Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) にディレクトリ掘るとか
- アプリで生成した画像を保存するなら Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURE) にディレクトリ掘るとか
その他のまめ知識
- キャッシュ領域にサイズ制限はないが、ストレージが圧迫されてくるとシステムによって消されることがあるらしい(未実験)
- http://stackoverflow.com/questions/2175843/limit-size-of-cache-directory
- 逆に言うと消えることが保証されているわけではないので、容量制限などを行う場合は自分で実装する
- こちらによると 1MB 以下が推奨とあるが、現在もそうであるか不明。キャッシュ容量二桁MB越えのアプリは珍しくない気がする
- マルチアカウント利用されている場合でも、 Context からディレクトリを取得していれば良きに計らってくれるみたい
- アプリをアンインストール時にも残しておきたいが、ユーザに見られたくない!消されたくない!は「できない」
- このようなデータは公開領域に置くのが主流っぽいが、隠蔽することはできない
- せいぜい見つけづらいところに置くくらいしかできないので、補助的に使うしかない
保存先はSDカード?内蔵ストレージ?
結論から言うと、 getExternal 系のメソッドでとれるディレクトリは、SDカードの場合もあれば内蔵ストレージの場合もあるようです。
基本的にアプリ側からSDカードを指定して扱うようなことは できない というのが正しそうです。
getExternal〜 でとれるディレクトリはシステムに決められたプライマリストレージであり、それがSDカードである保証はないということ。 よく getExternalStorageDirectory() でSDカード内のディレクトリがとれるという記事を見ますが、正確にはSDカードである可能性が高いディレクトリがとれるというのが正しそうです。
External という名前がついているので紛らわしいですが(というか完全に勘違いする)、これはSDカードのことをさしている訳ではなく、 システム領域の外のストレージという意味で External とついているようです。(参考)
とはいえ getExternal〜 で取得したディレクトリを使う場合は、プライマリストレージがSDカードである可能性を考慮しなくてはいけないため、マウントされているかどうかなどを確かめる必要があります。
1 2 3 4 5 6 7 8 |
|
今指定されているプライマリストレージが取り外し可能(普通はイコールSDカードになると思います)かどうかは以下を確認することで分かるので、取り外されるとまずい場合などは判別できそうです。
1 2 3 |
|
ちなみに手持ちの 206SH / Android 4.2.2 で確認してみたところ、Environment のさしているプライマリストレージは内蔵メモリのようでした。
ついでに 206SH でプライマリストレージを切り替えられるのかどうかを調べてみたけれど、結局切り替わる条件は不明でした。
1
|
|
あたりで切り替えられそうだなーと睨んで色々と試行錯誤してみましたが、プライマリストレージは変わりませんでした。
(おまけ)各ディレクトリのファイルパスなど
Nexus7 のほうは getExternal〜 でとれるディレクトリがマルチアカウント対応の Emulated なものになってました。
4.2 で追加されたマルチアカウントですが、 206SH では封じられているようです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|