Sunday, June 3, 2012

Android: Copying an asset from your App into your Phone.

I was playing some Android Mobile Game the other day and I was wondering how do I create a file from my Android App into the phone itself. If I'm not wrong, I think I have done it before... Hence the journey of code searching starts again.


My Main Android Application file - CopyAssetToPhoneActivity.java
package zcs.copyAsset;

import java.io.IOException;
import java.io.InputStream;

import zcs.utility.io.FileIO;
import zcs.utility.io.FileIOResult;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.text.Html;
import android.widget.TextView;

public class CopyAssetToPhoneActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        FileIOResult myFile;
        //Create file food.jpg
        myFile = FileIO.createFile("zcs/copy from assets/food.jpg");
        //Grab the Text View on the layout
     TextView tempTxtView = (TextView)this.findViewById(R.id.txtOutput);
     String strOutput;
     
        if(myFile.get_exist() == 1)
        {
         //If file exist, get contents of file and display it
         strOutput = this.getString(R.string.str_exist);
        }else if(myFile.get_exist() == 0){
         //If file doesn't exist, show a different msg
         strOutput = this.getString(R.string.str_create);
   try {
    //Create a InputStream Instance
          InputStream is;
          //Open the file that is located in the assets
          //folder of your Application as a InputStream
    is = getAssets().open("food.jpg");
    //Write the data into myFile 
    FileIO.writeStreamIntoFile(myFile.get_file(), is);
    //Closes the InputStream
    is.close();
    //Broadcast a Command telling your phone that
    //the sdcard has been mounted again so that it will
    //scan the sdcard for images
    sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, 
      Uri.parse("file://"+ 
      Environment.getExternalStorageDirectory())));
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
        }else{
         //Error occurred
         strOutput = this.getString(R.string.str_error);
        }
        //Show the text base on the condition of the file.
        tempTxtView.setText(Html.fromHtml(strOutput));
    }
}

One of my class file used for file I/O - FileIO.java
package zcs.utility.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.os.Environment;

public class FileIO {
 
 /**
  * Function that will create the specified file
  * name.
  * @param tempPath - path of the file you are 
  *       trying to access
  * @return FileIOResult Object
  *
  */ 
 public static FileIOResult createFile(String tempPath)
 {
  FileIOResult tempResult = new FileIOResult();
  //Check if the App has access to the External 
  //Storage first.
  boolean mExternalStorageWriteable = false;
  String state = Environment.getExternalStorageState();

  if (Environment.MEDIA_MOUNTED.equals(state)) {
      // We can read and write the media
      mExternalStorageWriteable = true;
  } else {
      // Something else is wrong. 
   // It may be one of many other states, but all we need
      // to know is we can neither read nor write
      mExternalStorageWriteable = false;
  }  
  //If we have access to the storage
  if(mExternalStorageWriteable)
  {
   String tempFilePath = tempPath;
   if(!tempFilePath.startsWith("/"))
   {
    tempFilePath = "/" + tempFilePath;
   }
         File root = Environment.getExternalStorageDirectory();
         File tempFile = new File(root + tempPath);
         //Check if file exist         
         if(!tempFile.exists())
         {
          //split the string and grab all the folders first 
          String[] strPathArray = tempFilePath.split("/");
          //Create all the folders first
          String strFolder = "";
          for(int i = 0; i < (strPathArray.length - 1); i ++)
       {
           strFolder = strFolder + "/" + strPathArray[i];
       }
       File sdDir = new File(root + strFolder);
          if(!sdDir.exists()){
           sdDir.mkdirs();
          }
          //Create File Path
    tempFile = new File(root + strFolder, 
         strPathArray[strPathArray.length - 1]);
         }
         try {
          //Check for file existence.
          if(tempFile.exists())
          {
           tempResult.set_exist(1);
          }else{
           tempResult.set_exist(0);
          }
          //If file doesn't exist, let's make one. 
          if(!tempFile.exists())
          {
           tempFile.createNewFile();
          }
   } catch (IOException e) {
    e.printStackTrace();
   }
         tempResult.set_file(tempFile);
  }else{
      tempResult.set_exist(2);
  }
  return tempResult;
 }

 /**
  *
  * Writing contents to the specified file.
  * Note: Use createFile(String) to gain access to the
  * file first. 
  * @param tempFile - File you are accessing
  * @return contents as a string
  */ 
 public static String readContentFromFile(File tempFile)
 {
  FileInputStream fis = null;    
  int ch;
     StringBuffer strContent = new StringBuffer("");
  try 
  {
   fis = new FileInputStream(tempFile);
      while((ch = fis.read()) != -1)
      {
       strContent.append((char)ch);
      }
  } catch (Exception e) 
  {
   e.printStackTrace();
  } finally
  {
            try
            {
             fis.close();
             fis = null;
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
  }
  return strContent.toString();
 }

 /**
  * Writing contents to the specified file.
  * Note: Use createFile(String) to gain access to the
  * file first. 
  * @param tempFile - File you are accessing
  * @param value - value you are going to write
  *       in the file
  */ 
 public static void writeContentIntoFile(File tempFile, String value)
 {
  FileOutputStream fos = null;
  try 
  {
   fos = new FileOutputStream(tempFile);

   fos.write(value.getBytes(),0,value.getBytes().length);
   fos.flush();
  } catch (Exception e) 
  {
   e.printStackTrace();
  } finally
  {
            try
            {
                fos.close();
                fos = null;
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
  }
 }

 /**
  * Writing data to the specified file.
  * Note: Use createFile(String) to gain access to the
  * file first. 
  * @param tempFile - File you are accessing
  * @param in - data you are going to write
  *       in the file
  */ 
 public static void writeStreamIntoFile(File tempFile, InputStream in) throws IOException { 
  OutputStream out = new FileOutputStream(tempFile); 
  // Transfer bytes from in to out 
        int size = in.available();
        
  byte[] buf = new byte[size]; 
  int len; 
  while ((len = in.read(buf)) > 0) { 
   out.write(buf, 0, len); 
  } 
  out.close(); 
 } 
}

One of my class file used for file I/O - FileIOResult.java
package zcs.utility.io;

import java.io.File;

public class FileIOResult { 
 private int _exist = 0;
 private File _file = null;

 /**
  * Used to check for the existance of the file.  
  * @return one of the below integer (0-2)
  *  
0 - file does not exist and it will * be created *
1 - file exist *
2 - Error */ public int get_exist() { return _exist; } public void set_exist(int _exist) { this._exist = _exist; } public File get_file() { return _file; } public void set_file(File _file) { this._file = _file; } public FileIOResult() { } }

My App Manifest file - AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="zcs.copyAsset"
    android:versionCode="1"
    android:versionName="1.0" >

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

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

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

</manifest>

Once you have run the application once, go to gallery and it
will be showing you a new folder that contains a new image.

* Click here to download the source file of the App that I have shown here.

No comments:

Post a Comment