Androidのファイル操作はjavaのファイル操作とほとんど同様ですが、操作対象となるディレクトリを内部ストレージと外部ストレージというAndroidの作法に従う必要があります。
Table of Contents
1 内部ストレージ
Androidがインストールされているストレージです。
ファイルサイズがそれほど大きくない場合はこちらを用いれば良いでしょう。
1.1 永続的なディレクトリfilesと一時的なディレクトリcache
Androidアプリケーションのファイル操作で使用する内部ストレージのディレクトリは以下のとおりです。
/data/data/[PackageName]/files | 永続的に残るディレクトリ |
/data/data/[PackageName]/cache | 一時的なディレクトリ |
/data/data/[PackageName]を使うよりもContextの次のメソッドを用いるべきです。
getFilesDir | filesディレクトリまでのパス |
getCacheDir | cacheディレクトリまでのパス |
1.2 サンプルコード
getFilesDirメソッドを利用したコードは次の通りです。
File file = new File(getFilesDir(), "hello.txt"); FileWriter fileWriter = null; try { fileWriter = new FileWriter(file); } catch (IOException e) { e.printStackTrace(); return; } PrintWriter printWriter = new PrintWriter(new BufferedWriter(fileWriter)); printWriter.println("hello"); printWriter.close();
端末に接続してhello.txtにアクセスするとhelloという文字列が書かれていることを確認できます。
$ adb shell # cat /data/data/com.hiroom2.samplefile/files/hello.txt hello
2 外部ストレージ
AndroidがインストールされていないSDカード等のストレージです。
ファイルサイズが大きい場合はこちらを用いるべきです。
パーミッション追加とマウント確認が必要になります。
2.1 パーミッション
外部ストレージへのアクセスには次のパーミッションがあります。
WRITE_EXTERNAL_STORAGE | 外部ストレージへの書き込み |
READ_EXTERNAL_STORAGE | 外部ストレージからの読み込み(将来的に必要) |
AndroidManifest.xmlで次のようにパーミッションを指定します。
<?xml version="1.0" encoding="utf-8"?> <manifest package="com.hiroom2.samplefile" xmlns:android="http://schemas.android.com/apk/res/android"> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".SampleActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest>
2.2 外部ストレージのマウント確認
外部ストレージへアクセスする前に外部ストレージがマウントされているかどうがを確認する必要があります。
getExternalStorageStateメソッドが返す戻り値で外部ストレージがマウントされているかを確認できます。
Environment.MEDIA_MOUNTED | 書き込み可能でマウント済み |
Environment.MEDIA_MOUNTED_READ_ONLY | 書き込み禁止でマウント済み |
上記以外 | マウントされてない |
2.3 外部ストレージのディレクトリ
Environmentクラスのstaticなメソッドは複数のアプリケーションの共有ディレクトリを取得できます。
Environment.getExternalStorageDirectory | トップディレクトリ |
Environment.getExternalStoragePublicDirectory | アプリ共有ディレクトリ |
Environment.getExternalStoragePublicDirectoryは Environment.DIRECTORY_PICTURES等を指定します。
Contextクラスのメソッドはアプリケーションのディレクトリを取得できます。
getExternalFilesDir | filesディレクトリまでのパス |
getExternalCacheDir | cacheディレクトリまでのパス |
getExternalFilesDirは引数が必要で、nullを指定した場合はfilesディレクトリを、Environment.DIRECTORY_PICTURES等を指定した場合はアプリケーション固有のPicturesディレクトリを取得できます。
2.4 サンプルコード
外部ストレージのディレクトリを取得するコードは以下のとおりです。
package com.hiroom2.samplefile; import android.os.Bundle; import android.os.Environment; import android.support.v7.app.AppCompatActivity; import android.util.Log; public class SampleActivity extends AppCompatActivity { private static final String gTag = "SampleActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sample); Log.i(gTag, Environment.getExternalStorageDirectory().toString()); Log.i(gTag, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString()); Log.i(gTag, getExternalFilesDir(null).toString()); Log.i(gTag, getExternalFilesDir(Environment.DIRECTORY_PICTURES).toString()); Log.i(gTag, getExternalCacheDir().toString()); } }
実行結果は以下のようになりました。
I/SampleActivity: /storage/emulated/0 I/SampleActivity: /storage/emulated/0/Pictures I/SampleActivity: /storage/emulated/0/Android/data/com.hiroom2.samplefile/files I/SampleActivity: /storage/emulated/0/Android/data/com.hiroom2.samplefile/files/Pictures I/SampleActivity: /storage/emulated/0/Android/data/com.hiroom2.samplefile/cache