「内部ストレージ」にアクセスする方法について、まとめます。
「内部ストレージ」は、セキュリティが高いうえに、端末の内部メモリーに構築されるので、必ず存在します。
使いたい時に安心して使え、もっとも使い勝手のよいストレージと言えます。
アプリのデータを保存したいならば、保存先として真っ先に考えるストレージです。
※環境:Android Studio Narwhal | 2025.1.1 Patch 1
目次
内部ストレージ
「内部ストレージ」はアプリ固有のデータを保存する領域です。
アプリ間はパッケージ名(アプリ固有の文字列)のディレクトリで隔てられています。また、マルチユーザのユーザID毎に独立した領域になっています。
※マルチユーザー環境についていは「Android OSのマルチユーザー環境」を参照
# pwd /data/user # ls -ld 0/com.example.*/* ↓UserID drwxrws--x 2 u0_a174 u0_a174_cache 4096 2025-04-19 02:42 0/com.example.myapp_a/cache drwxrws--x 2 u0_a174 u0_a174_cache 4096 2025-04-19 02:42 0/com.example.myapp_a/code_cache drwxrwx--x 2 u0_a174 u0_a174 4096 2025-04-19 02:42 0/com.example.myapp_a/files drwxrws--x 2 u0_a175 u0_a175_cache 4096 2025-04-19 02:41 0/com.example.myapp_b/cache drwxrws--x 2 u0_a175 u0_a175_cache 4096 2025-04-19 02:41 0/com.example.myapp_b/code_cache drwxrwx--x 2 u0_a175 u0_a175 4096 2025-04-19 02:42 0/com.example.myapp_b/files ↑UID ↑GID ↑Package ※エミュレータ(API33)で確認
アプリ固有のデータはサンドボックス内にあるので、他のアプリからアクセスは出来ません。厳重に守られます。
ですので、秘匿性の高いデータの保存に適します。
アクセスの方法
利用可能なアクセスの方法は「Java/Android API」のみです。
内部ストレージ /data/data/ユーザーID | Java / Android API | Media Store API | SAF | |
---|---|---|---|---|
アプリ固有 (パッケージ名/files) | 他:× | |||
※自:自アプリのファイル 他:他アプリのファイル ◎:アクセスできる(最適) ○:アクセスできる △:アクセスできる(不適または制限有) ×:アクセスできない 空:アクセスできない(サポート外) w:書き込みできる r:読み出しできる p:パーミッションが必要 |
さらに、「Java/Android API」を使ってアクセスする方法は、2つに分けられます。
Contextによる直接的なアクセスアプリ固有のデータの保存場所は決まっており、Contextに定義されています。Contextオブジェクトが示す既定の場所にアクセスする方法です。
Fileによる間接的なアクセスFileオブジェクトへ前もって保存場所を指定しておきます。Fileオブジェクトが示す場所にアクセスする方法です。
直接的なアクセス
既定の場所(/data/user/ユーザID/パッケージ名/files)へアクセスします。
書き込み
Context#openFileOutputを用いると、アプリ固有の保存先へ直に書き込まれます。
fun Context.writeFile_AppArea( data: ByteArray, filename: String ) { try { openFileOutput(filename, MODE_PRIVATE).use { it.write(data) } } catch (e: Exception) { Log.i(TAG, "[write] ${e}") } }
writeFile_AppArea(_data, filename)
# pwd /data/user/0/パッケージ名 # ls -ld */* -rw-rw---- 1 u0_a174 u0_a174 47891 2025-07-12 12:42 files/1752324178427.jpg ※エミュレータ(API33)で確認
読み出し
Context#openFileInputを用いると、アプリ固有の保存先から直に読み出されます。
fun Context.readFile_AppArea(filename: String): ByteArray { val _os = ByteArrayOutputStream() openFileInput(filename).use { stream -> _os.use { stream?.copyTo(_os) } } return _os.toByteArray() }
val _data = readFile_AppArea("1752324178427.jpg") Log.i(TAG, "Data = ${_data?.take(10)}")
Data = [71, 73, 70, 56, 55, 97, 24, 1, -46, 0]
ファイル削除
Context#deleteFileを用いると、アプリ固有の保存先からファイルを削除します。
# pwd /data/user/0/パッケージ名 # ls -ld files/* -rw-rw---- 1 u0_a174 u0_a174 47891 2025-07-14 06:15 files/1752473725549.jpg -rw-rw---- 1 u0_a174 u0_a174 47891 2025-07-14 06:15 files/1752473726610.jpg -rw-rw---- 1 u0_a174 u0_a174 47891 2025-07-14 06:15 files/1752473727634.jpg ※エミュレータ(API33)で確認
val _result = deleteFile("1752473727634.jpg") // true:成功、false:失敗
# pwd /data/user/0/パッケージ名 # ls -ld files/* -rw-rw---- 1 u0_a174 u0_a174 47891 2025-07-14 06:15 files/1752473725549.jpg -rw-rw---- 1 u0_a174 u0_a174 47891 2025-07-14 06:15 files/1752473726610.jpg ※エミュレータ(API33)で確認
ディレクトリ作成・削除
Context#getDirを用いると、アプリ固有の保存先へディレクトリを作成します。
ただし、ディレクトリ名が「”app_”+指定した文字列」になります。また、filesと並んだ位置に作成されます。
val _file = getDir("temp", MODE_PRIVATE) Log.i(TAG, "File = ${_file}")
File = /data/user/0/パッケージ名/app_temp
# pwd /data/user/0/パッケージ名 # ls -ld * drwxrwx--x 2 u0_a174 u0_a174 4096 2025-07-14 06:23 app_temp drwxrws--x 2 u0_a174 u0_a174_cache 4096 2025-07-14 06:15 cache drwxrws--x 2 u0_a174 u0_a174_cache 4096 2025-07-14 06:15 code_cache drwxrwx--x 2 u0_a174 u0_a174 4096 2025-07-14 06:16 files ※エミュレータ(API33)で確認
直接的なアクセスで行えるのは作成のみです。作成したディレクトリへのアクセスは、間接的なアクセス(後述)で行います。
例えば、ディレクトリ削除は以下のようになります。
val _result = File(dataDir, "app_temp").delete() // true:成功、false:失敗
# pwd /data/user/0/パッケージ名 # ls -ld * drwxrws--x 2 u0_a174 u0_a174_cache 4096 2025-07-14 06:15 cache drwxrws--x 2 u0_a174 u0_a174_cache 4096 2025-07-14 06:15 code_cache drwxrwx--x 2 u0_a174 u0_a174 4096 2025-07-14 06:16 files ※エミュレータ(API33)で確認
ファイル一覧
Context#fileListを用いると、アプリ固有の保存先のファイル一覧が得られます。
val _files = fileList() _files.forEach { Log.i(TAG, "File = ${it}") }
# pwd /data/user/0/パッケージ名 # ls -ld files/* -rw-rw---- 1 u0_a174 u0_a174 47891 2025-07-14 13:19 files/1752499198910.jpg -rw-rw---- 1 u0_a174 u0_a174 47891 2025-07-14 13:20 files/1752499200327.jpg -rw-rw---- 1 u0_a174 u0_a174 47891 2025-07-14 13:20 files/1752499201082.jpg ※エミュレータ(API33)で確認
File = 1752499198910.jpg File = 1752499200327.jpg File = 1752499201082.jpg
間接的なアクセス
Fileに指定した場所へアクセスします。
パス(保存場所)の取得
以下のように行うと、Android APIに定義されているパスが取得できます。
val _dataDir: File = this@Activity.dataDir // /data/user/0/パッケージ名 val _filesDir: File = this@Activity.filesDir // /data/user/0/パッケージ名/files val _cacheDir: File = this@Activity.cacheDir // /data/user/0/パッケージ名/cache val _codeCacheDir: File = this@Activity.codeCacheDir // /data/user/0/パッケージ名/code_cache
既定の場所は「files」ですが、「cache」「code_cache」と言ったディレクトリも利用可能です。
書き込み
File#outputStreamを用いると、Fileに指定した保存先へ書き込まれます。
fun writeFile_Basic(data: ByteArray, file: File) { try { file.outputStream().use { stream -> stream.write(data) } } catch (e: Exception) { Log.i(TAG, "[write] ${e}") } }
val _file = File(this@Activity.filesDir, filename) writeFile_Basic(_data, _file)
# pwd /data/user/0/パッケージ名 # ls -ld */* -rw------- 1 u0_a174 u0_a174 47891 2025-07-13 01:24 files/1752369865239.jpg ※エミュレータ(API33)で確認
読み出し
File#inputStreamを用いると、Fileに指定した保存先から読み出されます。
fun readFile_Basic(file: File): ByteArray { val _os = ByteArrayOutputStream() file.inputStream().use { stream -> _os.use { stream?.copyTo(_os) } } return _os.toByteArray() }
val _file = File(this@Activity.filesDir, "1752369865239.jpg") val _data = readFile_Basic(_file) Log.i(TAG, "Data = ${_data?.take(10)}")
Data = [71, 73, 70, 56, 55, 97, 24, 1, -46, 0]
ファイル削除
File#deleteを用いると、Fileに指定したファイルを削除します。
# pwd /data/user/0/パッケージ名 # ls -ld files/* -rw------- 1 u0_a174 u0_a174 47891 2025-07-14 07:01 files/1752476467106.jpg -rw------- 1 u0_a174 u0_a174 47891 2025-07-14 07:01 files/1752476468125.jpg -rw------- 1 u0_a174 u0_a174 47891 2025-07-14 07:01 files/1752476469166.jpg ※エミュレータ(API33)で確認
val _file = File(this@Activity.filesDir, "1752476469166.jpg") val _result = _file.delete() // true:成功、false:失敗
# pwd /data/user/0/パッケージ名 # ls -ld files/* -rw------- 1 u0_a174 u0_a174 47891 2025-07-14 07:01 files/1752476467106.jpg -rw------- 1 u0_a174 u0_a174 47891 2025-07-14 07:01 files/1752476468125.jpg ※エミュレータ(API33)で確認
ディレクトリ作成・削除
File#mkdirを用いると、Fileに指定したディレクトリを作成します。
val _file = File(this@Activity.filesDir, "temp") val _result = _file.mkdir() // true:成功、false:失敗
# pwd /data/user/0/パッケージ名 # ls -ld files/* -rw------- 1 u0_a174 u0_a174 47891 2025-07-14 07:01 files/1752476467106.jpg -rw------- 1 u0_a174 u0_a174 47891 2025-07-14 07:01 files/1752476468125.jpg drwx------ 2 u0_a174 u0_a174 4096 2025-07-14 07:05 files/temp ※エミュレータ(API33)で確認
File#deleteを用いると、Fileに指定したディレクトリを削除します。
val _file = File(this@Activity.filesDir, "temp") val _result = _file.delete() // true:成功、false:失敗
# pwd /data/user/0/パッケージ名 # ls -ld files/* -rw------- 1 u0_a174 u0_a174 47891 2025-07-14 07:01 files/1752476467106.jpg -rw------- 1 u0_a174 u0_a174 47891 2025-07-14 07:01 files/1752476468125.jpg ※エミュレータ(API33)で確認
ファイル一覧
File#listを用いると、Fileに指定したディレクトリのファイル一覧を得ます。
val _files = this@Activity.filesDir.list() _files.forEach { Log.i(TAG, "File = ${it}") }
# pwd /data/user/0/パッケージ名 # ls -ld files/* -rw------- 1 u0_a174 u0_a174 47891 2025-07-14 13:30 files/1752499851049.jpg -rw------- 1 u0_a174 u0_a174 47891 2025-07-14 13:30 files/1752499851750.jpg -rw------- 1 u0_a174 u0_a174 47891 2025-07-14 13:30 files/1752499853162.jpg ※エミュレータ(API33)で確認
File = 1752499851049.jpg File = 1752499851750.jpg File = 1752499853162.jpg
File creation mode
直接的なアクセスにおいて、ファイルまたはディレクトリを作成する場合に「File creation mode」を指定します。
mode(Context.***) | 意味 | コメント |
---|---|---|
MODE_PRIVATE | the default mode, where the created file can only be accessed by the calling application (or all applications sharing the same user ID). ※ドキュメントより ----- 自アプリのみの読み書きが可能 | デフォルト |
MODE_APPEND | for use with openFileOutput(String, int), if the file already exists then write data to the end of the existing file instead of erasing it. ※ドキュメントより ----- ファイルが存在する場合、末尾に追加して書き込み (openFileOutputで使用する場合) | |
MODE_WORLD_READABLE | allow all other applications to have read access to the created file. ※ドキュメントより ----- 他アプリの読み出しが可能 | API≧17で非推奨(※1) |
MODE_WORLD_WRITEABLE | allow all other applications to have write access to the created file. ※ドキュメントより ----- 他アプリの書き込みが可能 |
|
※1:非推奨の範囲で用いた場合、SecurityExceptionを発行 |
「MODE_WORLD_READABLE/WRITEABLE」を用いると、作成したファイルはサンドボックスの外に出されてしまいます。必ず、「MODE_PRIVATE(デフォルト)」を用いて下さい。
# pwd /data/user/0/パッケージ名/files # ls -l * -rw-rw---- u0_a58 u0_a58 6 2025-07-14 01:57 sample_Private.txt ... MODE_PRIVATEを指定 -rw-rw-r-- u0_a58 u0_a58 6 2025-07-14 01:57 sample_WorldReadable.txt ... MODE_WORLD_READABLEを指定 -rw-rw--w- u0_a58 u0_a58 6 2025-07-14 01:57 sample_WorldWriteable.txt ... MODE_WORLD_WRITEABLEを指定 ↑↑ Otherのファイルパーミッションが付く ※エミュレータ(API21)で確認
API≧17で非推奨になっているので、極めて古い端末に対応することが無ければ、無縁かも知れません。
関連記事: