Android外部存储可以用于写入和保存数据、读取配置文件等。本文是系列教程中关于Android结构化数据存储的Android内部存储教程的延续。
Android外部存储
外部存储,如SD卡,也可以存储应用程序数据,对保存到外部存储的文件没有强制执行安全性。一般有两种类型的外部存储:
- 主要外部存储:内置共享存储,用户通过连接USB电缆并将其挂载为主机计算机上的驱动器可访问。例如:当我们说Nexus 5 32 GB 时。
- 次要外部存储:可移动存储。例如:SD卡
所有应用程序都可以读取和写入放置在外部存储上的文件,用户可以将它们移除。我们需要检查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
的静态方法,用于确定外部存储是否可用。正如您所见,如果条件为假,我们已禁用保存按钮。
Android 外部存储示例代码
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>
除了保存和从外部存储读取的按钮之外,我们在一个TextView中显示保存/读取到/从外部存储的响应,而不像之前的教程中显示Android Toast。MainActivity.java类如下所示:
package com.journaldev.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(): 返回内部SD挂载点的路径,如“/mnt/sdcard”
- getExternalFilesDir(): 返回SD卡上Android/data/data/application_package/中文件文件夹的路径。它用于存储应用程序所需的任何文件(例如从网络下载的图像或缓存文件)。一旦应用程序被卸载,存储在此文件夹中的任何数据也将消失。
此外,如果外部存储不可用,我们将使用之前在本教程中讨论过的条件来禁用保存按钮。以下是我们在Android模拟器中运行的应用程序,我们正在将数据写入文件,然后进行读取。
注意:确保您的Android模拟器已配置为具有SD卡,如下图所示从AVD的对话框。转到“工具”->“Android”->“Android虚拟设备”,编辑配置->“显示高级设置”。
这就结束了本教程。我们将在下一个教程中讨论使用Shared Preferences进行存储。您可以从下面的链接下载最终的Android外部存储项目。
[下载Android外部存储示例项目](
)
Source:
https://www.digitalocean.com/community/tutorials/android-external-storage-read-write-save-file