今回はAndroidでのファイルの扱い方を紹介する。(※以下で紹介するソースコードは前回作ったものを流用している)
ファイルシステムは、一塊で意味を成すファイル(例えば画像や音声などのデータ)を扱うときに適している。
外部ストレージと内部ストレージ
Androidのファイルシステムには、
外部ストレージ(External Storage)と内部ストレージ(Internal Storage)が存在する。
おおまかに言えば、前者がSDカードなどの取り外し可能なディスクで、後者が内部ディスクなどだ。
前者は他のアプリからも読み書き可能だが、後者はデフォルトではファイルを作成したアプリからのみ読み書き可能である。
外部ストレージ利用のパーミッション
アプリに外部ストレージへの読み書きを可能にするためにパーミッションを与える。
現状では他のアプリからもアクセス可能なのだが、将来的には規制されるようだ。以下のパーミッション設定はそのときのための備えである
AndroidManifest.xml
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
...
</manifest>
以下は一般的に良く利用するであろう、内部ストレージへのファイル読み書きのサンプルである。
これを理解できれば、外部ストレージへのファイル読み書きも応用が効くはずだ。
activity_main.xml(画面)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<EditText
android:id="@+id/edit_message"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="@string/edit_message" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="sendMessage"
android:text="@string/button_send" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="saveToSP"
android:text="@string/button_save_to_sp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="readFromSP"
android:text="@string/button_read_from_sp" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="saveToFile"
android:text="@string/button_save_to_file" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="readFromFile"
android:text="@string/button_read_from_file" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="deleteFile"
android:text="@string/button_delete_file" />
</LinearLayout>
</LinearLayout>
strings.xml(リソースファイル)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">My First App</string>
<string name="edit_message">Enter a message</string>
<string name="button_send">Send</string>
<string name="menu_settings">Settings</string>
<string name="title_activity_main">MainActivity</string>
<string name="action_settings">Settings</string>
<string name="hello_world">Hello world!</string>
<string name="title_activity_display_message">My Message</string>
<!-- SharedPreferences -->
<string name="sp_key">my_sp_key</string>
<string name="button_save_to_sp">save to SP</string>
<string name="button_read_from_sp">read from SP</string>
<!-- File -->
<string name="button_save_to_file">save to file</string>
<string name="button_read_from_file">read from file</string>
<string name="button_delete_file">delete file</string>
</resources>
MainActivity.java
package com.example.myfirstapp;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE";
// InstanceStateへ状態を保存するためのキー
public final static String STATE_ENTERED_MESSAGE = "state.enteredmessage";
private String message = null;
private final static String FILENAME = "myfile.txt";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
/** Called when the user clicks the Send button */
public void sendMessage(View view) {
Intent intent = new Intent(this, DisplayMessageActivity.class);
EditText editText = (EditText) findViewById(R.id.edit_message);
message = editText.getText().toString();
intent.putExtra(EXTRA_MESSAGE, message);
startActivity(intent);
}
/**
* メッセージをSharedPreferencesへ保存
*/
public void saveToSP(View view) {
// 入力ボックスの値を取得
EditText editText = (EditText) findViewById(R.id.edit_message);
message = editText.getText().toString();
// SPへ保存
SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString(getString(R.string.sp_key), message);
editor.commit();
// トースト表示
Toast.makeText(this, "SPへ保存しました:" + message, Toast.LENGTH_LONG).show();
}
/**
* SharedPreferencesに保存されたメッセージを読み込み
*/
@SuppressLint("ShowToast")
public void readFromSP(View view) {
// SPからデータを取得
SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
String message = sharedPref.getString(getString(R.string.sp_key),
"default message");
// トースト表示
Toast.makeText(this, "SPから読み込みました:" + message, Toast.LENGTH_LONG)
.show();
}
/**
* ファイルへ保存
*
* @param view
*/
@SuppressLint("ShowToast")
public void saveToFile(View view) {
// 入力ボックスの値を取得
EditText editText = (EditText) findViewById(R.id.edit_message);
message = editText.getText().toString();
try {
FileOutputStream fos = openFileOutput(FILENAME,
Context.MODE_PRIVATE);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
bw.write(message);
bw.flush();
bw.close();
} catch (Exception e) {
e.printStackTrace();
}
// トースト表示
Toast.makeText(this, "saved to file:" + message, Toast.LENGTH_SHORT)
.show();
}
/**
* ファイルから読み込み
*
* @param view
*/
@SuppressLint("ShowToast")
public void readFromFile(View view) {
FileInputStream file;
String str = null;
try {
file = openFileInput(FILENAME);
BufferedReader br = new BufferedReader(new InputStreamReader(file));
str = br.readLine();
br.close();
} catch (Exception e) {
e.printStackTrace();
}
// トースト表示
Toast.makeText(this, "read from file:" + str, Toast.LENGTH_LONG).show();
}
/**
* ファイルを削除
*
* @param view
*/
@SuppressLint("ShowToast")
public void deleteFile(View view) {
// 内部ストレージのファイルを削除
deleteFile(FILENAME);
// // 任意のファイルを削除する場合はこっちを使う
// File file = new File(Environment.getExternalStorageDirectory(), "/" +
// FILENAME);
// file.delete();
// トースト表示
Toast.makeText(this, "file deleted:" + FILENAME, Toast.LENGTH_LONG)
.show();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
// InstanceState へ 入力されたメッセージを保存しておく。
outState.putString(STATE_ENTERED_MESSAGE, message);
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
message = savedInstanceState.getString(STATE_ENTERED_MESSAGE);
}
}
"save to file"ボタンを押すと、入力ボックスのメッセージを内部ストレージにファイルとして書き込まれる(#saveToFile)。
"read from file"ボタンを押すと内部ストレージに書き込まれているファイルの文字列を読み込んでトースト表示(#readFromFile)。
"delete file"ボタンを押すとファイル自体が削除される(#deleteFile)。
次回はデータベースを使ったデータ保存を紹介する予定。