Android Tutorial - Android External Storage








Load the file from the external storage

The following code shows how to Load the file from the external storage.

Example

Main layout file

<?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" >

 <TextView
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:text="Please enter some text" />

 <EditText
     android:id="@+id/txtText1"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content" />

 <Button
     android:id="@+id/btnSave"
     android:text="Save"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:onClick="onClickSave" />

 <Button
     android:id="@+id/btnLoad"
     android:text="Load"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:onClick="onClickLoad" />

</LinearLayout>

MainActivity.java file

package com.java2s.myapplication3.app;
//from  w w  w  .  j a  v  a  2  s  .c  o  m
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class MainActivity extends Activity {
    EditText textBox;
    static final int READ_BLOCK_SIZE = 100;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textBox = (EditText) findViewById(R.id.txtText1);
    }

    public void onClickLoad(View view) {
        try {
            //SD Storage
            File sdCard = Environment.getExternalStorageDirectory();
            File directory = new File(sdCard.getAbsolutePath() +
                    "/MyFiles");
            File file = new File(directory, "textfile.txt");
            FileInputStream fIn = new FileInputStream(file);
            InputStreamReader isr = new InputStreamReader(fIn);
            char[] inputBuffer = new char[READ_BLOCK_SIZE];
            String s = "";

            int charRead;
            while ((charRead = isr.read(inputBuffer)) > 0) {
                String readString =
                        String.copyValueOf(inputBuffer, 0,
                                charRead);
                s += readString;

                inputBuffer = new char[READ_BLOCK_SIZE];
            }
            textBox.setText(s);
            Toast.makeText(getBaseContext(),
                    "File loaded successfully!",
                    Toast.LENGTH_SHORT).show();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
    public void onClickSave(View view) {
        String str = textBox.getText().toString();
        try {
            //SD Card Storage
            File sdCard = Environment.getExternalStorageDirectory();
            File directory = new File(sdCard.getAbsolutePath() +
                    "/MyFiles");
            directory.mkdirs();
            File file = new File(directory, "textfile.txt");
            FileOutputStream fOut = new FileOutputStream(file);
            OutputStreamWriter osw = new
                    OutputStreamWriter(fOut);

            osw.write(str);
            osw.flush();
            osw.close();

            Toast.makeText(getBaseContext(),
                    "File saved successfully!",
                    Toast.LENGTH_SHORT).show();

            textBox.setText("");
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }

    }

}




Note

In order to write to the external storage, you need to add the WRITE_EXTERNAL_STORAGE permission in your AndroidManifest.xml file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.java2s.Files"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="14" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:label="@string/app_name"
            android:name=".FilesActivity" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>





Choose the Best Storage Option

There are three main ways to save data in your Android applications:

  • SharedPreferences object,
  • internal storage, and
  • external storage.

Here are some guidelines:

  • To store name/value pairs, use the SharedPreferences object.
  • To store ad-hoc data, then using the internal storage.
  • To share your application data with other users, store your files on the SD card.

Save to External Storage (SD Card)

The following code shows how to Save to External Storage (SD Card).

Main layout file

<?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" >

 <TextView
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:text="Please enter some text" />

 <EditText
     android:id="@+id/txtText1"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content" />

 <Button
     android:id="@+id/btnSave"
     android:text="Save"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:onClick="onClickSave" />

 <Button
     android:id="@+id/btnLoad"
     android:text="Load"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:onClick="onClickLoad" />

</LinearLayout>

MainActivity.java file

package com.java2s.myapplication3.app;
//  w  w  w .j a  v  a2 s.com
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {
    EditText textBox;
    static final int READ_BLOCK_SIZE = 100;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textBox = (EditText) findViewById(R.id.txtText1);
    }

    public void onClickSave(View view) {
        String str = textBox.getText().toString();
        try
        {
            FileOutputStream fOut =
                    openFileOutput("textfile.txt",
                            MODE_WORLD_READABLE);
            OutputStreamWriter osw = new
                    OutputStreamWriter(fOut);
            osw.write(str);
            osw.flush();
            osw.close();
            Toast.makeText (getBaseContext(),
                    "File saved successfully!",
                    Toast.LENGTH_SHORT).show();
            textBox.setText("");
        }
        catch (IOException ioe)
        {
            ioe.printStackTrace();
        }
    }
    public void onClickLoad(View view) {
        try{
            FileInputStream fIn =
                    openFileInput("textfile.txt");
            InputStreamReader isr = new
                    InputStreamReader(fIn);

            char [] inputBuffer = new char [READ_BLOCK_SIZE];
            String s = "";

            int charRead;
            while ((charRead = isr.read(inputBuffer))>0)
            {
                String readString =
                        String.copyValueOf(inputBuffer, 0,
                                charRead);
                s += readString;

                inputBuffer = new char [READ_BLOCK_SIZE];
            }
            textBox.setText(s);
            Toast.makeText (getBaseContext(),
                    "File loaded successfully!",
                    Toast.LENGTH_SHORT).show();
        }
        catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}

Write and read External storage with File Utilities

The following code shows how to Write and read External storage with File Utilities.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.java2s.myapplication3.app" >

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="java2s.com"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.java2s.myapplication3.app.MainActivity"
            android:label="java2s.com"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

</manifest>

Main layout xml file

<?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">

    <TextView
        android:id="@+id/external_storage_label"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10px"
        android:text="Enter some text to write on the external storage, then read back:" />

    <EditText
        android:id="@+id/external_storage_input"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10px" />

    <Button
        android:id="@+id/external_storage_write_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Write" />

    <Button
        android:id="@+id/external_storage_read_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Read" />

    <TextView
        android:id="@+id/external_storage_output"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10px" />


</LinearLayout>

Main Activity Java code

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.os.Environment;
import android.util.Log;
/*w ww  .j  a  v a 2 s  .  c  o  m*/

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.nio.channels.FileChannel;

import java.io.File;

public class MainActivity extends Activity {
   private EditText input;
   private TextView output;
   private Button write;
   private Button read;

   @Override
   public void onCreate(final Bundle icicle) {
      super.onCreate(icicle);
      this.setContentView(R.layout.external_storage);

      this.input = (EditText) findViewById(R.id.external_storage_input);
      this.output = (TextView) findViewById(R.id.external_storage_output);

      this.write = (Button) findViewById(R.id.external_storage_write_button);
      this.write.setOnClickListener(new OnClickListener() {
         public void onClick(final View v) {
            write();
         }
      });

      this.read = (Button) findViewById(R.id.external_storage_read_button);
      this.read.setOnClickListener(new OnClickListener() {
         public void onClick(final View v) {
            read();
         }
      });
   }

   private void write() {
      if (FileUtil.isExternalStorageWritable()) {
         File dir = FileUtil.getExternalFilesDirAllApiLevels(this.getPackageName());
         File file = new File(dir, "test.txt");
         FileUtil.writeStringAsFile(input.getText().toString(), file);
         Toast.makeText(this, "File written", Toast.LENGTH_SHORT).show();
         input.setText("");
         output.setText("");
      } else {
         Toast.makeText(this, "External storage not writable", Toast.LENGTH_SHORT).show();
      }
   }

   private void read() {
      if (FileUtil.isExternalStorageReadable()) {
         File dir = FileUtil.getExternalFilesDirAllApiLevels(this.getPackageName());
         File file = new File(dir, "test.txt");
         if (file.exists() && file.canRead()) {
            output.setText(FileUtil.readFileAsString(file));  
            Toast.makeText(this, "File read", Toast.LENGTH_SHORT).show();
         } else {
            Toast.makeText(this, "Unable to read file: " + file.getAbsolutePath(), Toast.LENGTH_SHORT).show();  
         }
      } else {
         Toast.makeText(this, "External storage not readable", Toast.LENGTH_SHORT).show();
      }
   }
}



/**
 * FileUtil methods. 
 * 
 * @author ccollins
 *
 */
final class FileUtil {

   // from the Android docs, these are the recommended paths
   private static final String EXT_STORAGE_PATH_PREFIX = "/Android/data/";
   private static final String EXT_STORAGE_FILES_PATH_SUFFIX = "/files/";
   private static final String EXT_STORAGE_CACHE_PATH_SUFFIX = "/cache/";

   // Object for intrinsic lock (per docs 0 length array "lighter" than a normal Object)
   public static final Object[] DATA_LOCK = new Object[0];

   private FileUtil() {
   }

   /**
    * Use Environment to check if external storage is writable.
    * 
    * @return
    */
   public static boolean isExternalStorageWritable() {
      return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
   }

   /**
    * Use environment to check if external storage is readable.
    * 
    * @return
    */
   public static boolean isExternalStorageReadable() {
      if (isExternalStorageWritable()) {
         return true;
      }
      return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY);
   }

   /**
    * Return the recommended external files directory, whether using API level 8 or lower.
    * (Uses getExternalStorageDirectory and then appends the recommended path.)
    * 
    * @param packageName
    * @return
    */
   public static File getExternalFilesDirAllApiLevels(final String packageName) {
      return FileUtil.getExternalDirAllApiLevels(packageName, EXT_STORAGE_FILES_PATH_SUFFIX);
   }
   
   /**
    * Return the recommended external cache directory, whether using API level 8 or lower.
    * (Uses getExternalStorageDirectory and then appends the recommended path.)
    * 
    * @param packageName
    * @return
    */
   public static File getExternalCacheDirAllApiLevels(final String packageName) {
      return FileUtil.getExternalDirAllApiLevels(packageName, EXT_STORAGE_CACHE_PATH_SUFFIX);
   }

   private static File getExternalDirAllApiLevels(final String packageName, final String suffixType) {
      File dir =
               new File(Environment.getExternalStorageDirectory() + EXT_STORAGE_PATH_PREFIX + packageName + suffixType);
      synchronized (FileUtil.DATA_LOCK) {
         try {
            dir.mkdirs();
            dir.createNewFile();
         } catch (IOException e) {
            Log.e(Constants.LOG_TAG, "Error creating file", e);
         }
      }
      return dir;
   }

   /**
    * Copy file, return true on success, false on failure.
    * 
    * @param src
    * @param dst
    * @return
    */
   public static boolean copyFile(final File src, final File dst) {
      boolean result = false;
      FileChannel inChannel = null;
      FileChannel outChannel = null;
      synchronized (FileUtil.DATA_LOCK) {
         try {
            inChannel = new FileInputStream(src).getChannel();
            outChannel = new FileOutputStream(dst).getChannel();
            inChannel.transferTo(0, inChannel.size(), outChannel);
            result = true;
         } catch (IOException e) {

         } finally {
            if (inChannel != null && inChannel.isOpen()) {
               try {
                  inChannel.close();
               } catch (IOException e) {
                  // ignore
               }
            }
            if (outChannel != null && outChannel.isOpen()) {
               try {
                  outChannel.close();
               } catch (IOException e) {
                  // ignore
               }
            }
         }
      }
      return result;
   }

   /**
    * Replace entire File with contents of String, return true on success, false on failure.
    * 
    * @param fileContents
    * @param file
    * @return
    */
   public static boolean writeStringAsFile(final String fileContents, final File file) {
      boolean result = false;
      try {
         synchronized (FileUtil.DATA_LOCK) {
            if (file != null) {
               file.createNewFile(); // ok if returns false, overwrite
               Writer out = new BufferedWriter(new FileWriter(file), 1024);
               out.write(fileContents);
               out.close();
               result = true;
            }
         }
      } catch (IOException e) {
         Log.e(Constants.LOG_TAG, "Error writing string data to file " + e.getMessage(), e);
      }
      return result;
   }

   /**
    * Append String to end of File, return true on success, false on failure.
    * 
    * @param appendContents
    * @param file
    * @return
    */
   public static boolean appendStringToFile(final String appendContents, final File file) {
      boolean result = false;
      try {
         synchronized (FileUtil.DATA_LOCK) {
            if ((file != null) && file.canWrite()) {
               file.createNewFile(); // ok if returns false, overwrite
               Writer out = new BufferedWriter(new FileWriter(file, true), 1024);
               out.write(appendContents);
               out.close();
               result = true;
            }
         }
      } catch (IOException e) {
         Log.e(Constants.LOG_TAG, "Error appending string data to file " + e.getMessage(), e);
      }
      return result;
   }

   /**
    * Read file as String, return null if file is not present or not readable.
    * 
    * @param file
    * @return
    */
   public static String readFileAsString(final File file) {
      StringBuilder sb = null;
      try {
         synchronized (FileUtil.DATA_LOCK) {
            if ((file != null) && file.canRead()) {
               sb = new StringBuilder();
               String line = null;
               BufferedReader in = new BufferedReader(new FileReader(file), 1024);
               while ((line = in.readLine()) != null) {
                  sb.append(line + System.getProperty("line.separator"));
               }
            }
         }
      } catch (IOException e) {
         Log.e(Constants.LOG_TAG, "Error reading file " + e.getMessage(), e);
      }
      if (sb != null) {
         return sb.toString();
      }
      return null;
   }
}
null