Android

[Android] データの永続化領域について -getFilesDir() vs getExternalFilesDirs()-(アプリ内で取得した画像の置き場所に迷ったので)

More than 3 years have passed since last update.

アプリ内でダウンロードした画像や動画はどこに置いたらいんだっけ、というのが自分の中で割りと曖昧だったので調べました。

似たような記事はいろいろありますが、自分の言葉でまとめておきたかったので備忘録的に。

Androidではデータの永続化領域としていくつかの場所が用意されている。

大きく分けると、「アプリ内のデータ領域」と「外部ストレージ」があると思います。


アプリ内データ領域


Context.getCacheDir()

ex) /data/data/{パッケージ名}/cache

これで得られるディレクトリ以下のファイルはあくまでキャッシュ用。容量が足りなくなった時に削除可能性がある。また、Androidの設定画面のClear Cacheでも削除される。


Context.getFilesDir()

ex) /data/data/{パッケージ名}/files

アプリ内データの永続化領域。アプリのアンイストール時にここのファイル達は失われる。


外部ストレージ領域

getExternalFilesDirs()のようにExternalという言葉が使われているが、外部といっても必ずしもSDカードのようなものではない。端末内蔵のストレージの場合もあればSDカードのように取り外し可能なものある。つまりアプリから見て外部というような意味合いかと。

公式レファレンスにも同様のことが書かれており、アプリケーション間で共有しているストレージ領域だとのこと。

逆に、端末内蔵ストレージかSDカードかといったような区別は特にしていない模様。

基本的に外部ストレージを使うためには現在そこへアクセス可能かを確認する必要がある。内蔵ストレージが端末にマウントされていなかったり、SDカードが外されている場合には当然そこへアクセスすることはできない。

http://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory()


Environment.getDataDirectory()

ex) /data

Androidのデータ保存領域


Environment.getExternalStorageDirectory()

ex) /storage/emulated/0

外部ストレージのディレクトリを取得する。

ただし、直接ここへ何かを置くべきではない。アプリケーションプライベートであればContext.getExternalFilesDir、共有ファイルであればEnvironment.getExternalStoragePublicDirectory(String)経由でこの外部ストレージ領域を利用すべきとのこと。


Environment.getExternalStoragePublicDirectory(String)

ex)getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)):

/storage/emulated/0/Download



外部ストレージ領域の最上位パス。タイプを指定する必要がある。


Context.getExternalFilesDirs()

ex) /storage/emulated/0/Android/data/{パッケージ名}/files

アプリ固有の外部ストレージ領域。

アプリ固有のデータを保存するという点ではgetFilesDir()と同様だが、以下の2点が重要な違いだ。


  • 常に利用可能というわけではない。(上述)


  • WRITE_EXTERNAL_STORAGE権限があれば他アプリからの書き込みが可能


まとめ

Context経由で呼び出せるものはアプリ固有のデータ領域。

Externalが付いているものは外部ストレージ領域。マウントされていない場合には使えない。

Externalが付いているものは、アプリ固有のデータであっても、アプリアンインストールで消えることはない。例えば、Context.getExternalFilesDirs()で得られる領域はContext経由なのでアプリ固有のデータ領域だが、Externalなのでアプリを削除してもデータは残る。

Externalはストレージがマウントされてない可能性を考えないといけないからアプリ固有のデータであればContext.getFilesDir()がいいかなあ。