Android外部存储-读取,写入,保存文件

时间:2020-02-23 14:28:55  来源:igfitidea点击:

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()"是"环境"的静态方法,用于确定外部存储是否当前可用。
如您所见,条件是否为假,我们已禁用了保存按钮。

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>

其中除了"保存和从外部存储读取"按钮外,我们还在文本视图中显示保存/读取/从外部存储读取的响应,这与之前显示android toast的教程不同。

MainActivity.java类如下所示:

package com.theitroad.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 /中的files文件夹的路径。
    它用于存储应用程序所需的任何文件(例如从网络下载的图像或者缓存文件)。
    卸载应用后,该文件夹中存储的所有数据也将消失。

另外,如果外部存储不可用,我们将使用本教程前面讨论的if条件禁用保存按钮。

以下是我们在android模拟器中运行的应用程序,我们其中将数据写入文件,然后读取它。

注意:请确保您的Android仿真器已配置为具有SD卡,如下面AVD中的图像对话框所示。
转到工具-> Android-> Android虚拟设备,编辑配置->显示高级设置。