Androidの外部ストレージ – ファイルを読み書きし、保存
Androidの外部ストレージは、データの書き込みや保存、設定ファイルの読み取りなどに使用することができます。この記事は、Androidの内部ストレージチュートリアルシリーズの一続きで、Androidでの構造化データのストレージに関するものです。
アンドロイドの外部ストレージ
SDカードなどの外部ストレージには、アプリケーションデータを保存することもできますが、保存するファイルにはセキュリティが適用されません。一般的には、外部ストレージには2種類あります。
- Primary External Storage: In built shared storage which is “accessible by the user by plugging in a USB cable and mounting it as a drive on a host computer”. Example: When we say Nexus 5 32 GB.
- Secondary External Storage: Removable storage. Example: SD Card
すべてのアプリケーションは、外部ストレージに配置されたファイルを読み書きすることができ、ユーザーはそれらを削除することができます。SDカードが利用可能かどうか、また書き込み可能かどうかを確認する必要があります。外部ストレージが利用可能であることを確認した後に初めて書き込むことができます。そうでない場合、保存ボタンは無効になります。
Android 外部ストレージの例のプロジェクト構造
まず、ユーザーのSDカードへのデータの読み書き許可がアプリケーションにあるか確認する必要があります。AndroidManifest.xmlを開いて、以下の許可を追加しましょう。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
また、外部ストレージは、ユーザーがUSBストレージとしてマウントしたことで利用されている可能性もあります。そのため、外部ストレージが利用可能であり、読み取り専用ではないかを確認する必要があります。
if (!isExternalStorageAvailable() || isExternalStorageReadOnly()) {
saveButton.setEnabled(false);
}
private static boolean isExternalStorageReadOnly() {
String extStorageState = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(extStorageState)) {
return true;
}
return false;
}
private static boolean isExternalStorageAvailable() {
String extStorageState = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(extStorageState)) {
return true;
}
return false;
}
getExternalStorageState()は、外部ストレージが現在利用可能かどうかを判断するためのEnvironmentの静的メソッドです。条件が偽の場合、保存ボタンを無効にしています。
アンドロイド外部ストレージの例題コード
activity_main.xmlのレイアウトは以下のように定義されています:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Reading and Writing to External Storage"
android:textSize="24sp"/>
<EditText android:id="@+id/myInputText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" android:lines="5"
android:minLines="3" android:gravity="top|left"
android:inputType="textMultiLine">
<requestFocus />
</EditText>
<LinearLayout
android:layout_width="match_parent" android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="1.0"
android:layout_marginTop="20dp">
<Button android:id="@+id/saveExternalStorage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="SAVE"
android:layout_weight="0.5"/>
<Button android:id="@+id/getExternalStorage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:text="READ" />
</LinearLayout>
<TextView android:id="@+id/response"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:padding="5dp"
android:text=""
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
以下のように、ネイティブの日本語で言い換えることができます。
前のチュートリアルでは、Androidトーストが表示されていたのに対し、ここでは保存/読み込みの応答を外部ストレージに保存/読み込みするためのボタン以外に、テキストビューに表示します。以下にMainActivity.javaクラスが記載されています。
package com.scdev.externalstorage;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import android.os.Bundle;
import android.app.Activity;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
EditText inputText;
TextView response;
Button saveButton,readButton;
private String filename = "SampleFile.txt";
private String filepath = "MyFileStorage";
File myExternalFile;
String myData = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
inputText = (EditText) findViewById(R.id.myInputText);
response = (TextView) findViewById(R.id.response);
saveButton =
(Button) findViewById(R.id.saveExternalStorage);
saveButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
FileOutputStream fos = new FileOutputStream(myExternalFile);
fos.write(inputText.getText().toString().getBytes());
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
inputText.setText("");
response.setText("SampleFile.txt saved to External Storage...");
}
});
readButton = (Button) findViewById(R.id.getExternalStorage);
readButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
FileInputStream fis = new FileInputStream(myExternalFile);
DataInputStream in = new DataInputStream(fis);
BufferedReader br =
new BufferedReader(new InputStreamReader(in));
String strLine;
while ((strLine = br.readLine()) != null) {
myData = myData + strLine;
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
inputText.setText(myData);
response.setText("SampleFile.txt data retrieved from Internal Storage...");
}
});
if (!isExternalStorageAvailable() || isExternalStorageReadOnly()) {
saveButton.setEnabled(false);
}
else {
myExternalFile = new File(getExternalFilesDir(filepath), filename);
}
}
private static boolean isExternalStorageReadOnly() {
String extStorageState = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(extStorageState)) {
return true;
}
return false;
}
private static boolean isExternalStorageAvailable() {
String extStorageState = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(extStorageState)) {
return true;
}
return false;
}
}
-
- Environment.getExternalStorageState() : “/mnt/sdcard”のような内部SDマウントポイントへのパスを返します。
- getExternalFilesDir() : SDカード内のAndroid/data/data/application_package/内のファイルフォルダへのパスを返します。このフォルダには、アプリで必要なファイル(ウェブからダウンロードされた画像やキャッシュファイルなど)を保存するために使用されます。アプリがアンインストールされると、このフォルダに保存されたデータは削除されます。
また、外部ストレージが利用できない場合は、先にこのチュートリアルで説明したif条件を使用して保存ボタンを無効にします。以下は、ファイルにデータを書き込んでから読み込むためにアプリケーションがAndroidエミュレータで実行されている状態です。 注意:Androidエミュレータが下のAVDのイメージダイアログに表示されるSDカードを持つように構成されていることを確認してください。ツール->Android->Android Virtual Deviceに移動し、設定を編集->詳細設定を表示します。これでこのチュートリアルは終了です。次のチュートリアルでは、Shared Preferencesを使用したストレージについて説明します。最終的なAndroid External Storage Projectは、以下のリンクからダウンロードできます。
Androidの外部ストレージの例プロジェクトをダウンロードしてください。