Android - Copy assets to internal storage
Asked Answered
S

8

46

Good day!

I have just started developing for android. In my app, I need to copy the items in my assets folder to the internal storage.

I have searched a lot on SO including this which copies it to the external storage. How to copy files from 'assets' folder to sdcard?

This is what I want to achieve: I have a directory already present in the internal storage as X>Y>Z. I need a file to be copied to Y and another to Z.

Can anyone help me out with a code snippet? I really don't have any idea how to go on about this.

Sorry for my bad English.

Thanks a lot.

Stylolite answered 7/10, 2013 at 7:1 Comment(2)
Did you try with the link that you have shared in the post?What is error you are getting ??Temptress
try the way I suggested it works for Me :)Backhouse
I
30

Use

 String out= Environment.getExternalStorageDirectory().getAbsolutePath() + "/X/Y/Z/" ; 

        File outFile = new File(out, Filename);

After Editing in your ref. Link Answer.

private void copyAssets() {
    AssetManager assetManager = getAssets();
    String[] files = null;
try {
    files = assetManager.list("");
} catch (IOException e) {
    Log.e("tag", "Failed to get asset file list.", e);
  }
 for(String filename : files) {
    InputStream in = null;
    OutputStream out = null;
    try {
      in = assetManager.open(filename);

      String outDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/X/Y/Z/" ; 

      File outFile = new File(outDir, filename);

      out = new FileOutputStream(outFile);
      copyFile(in, out);
      in.close();
      in = null;
      out.flush();
      out.close();
        out = null;
      } catch(IOException e) {
          Log.e("tag", "Failed to copy asset file: " + filename, e);
         }       
       }
     }
     private void copyFile(InputStream in, OutputStream out) throws IOException {
        byte[] buffer = new byte[1024];
      int read;
     while((read = in.read(buffer)) != -1){
       out.write(buffer, 0, read);
     }
   }
Ipsus answered 7/10, 2013 at 7:11 Comment(11)
How should I use this code? Please elaborate a little. I'm really new to android. Thank you.Stylolite
String out= Environment.getExternalStorageDirectory().getAbsolutePath() + "/X/Y/Z/" ; File outFile = new File(out, Filename); change the "out" to "dirout". it is conflicting with the next String outInduction
No, as should be obvious from the Environment.getExternalStorageDirectory() call this copies the data to the EXTERNAL storage.Deerdre
No, It copies the data to mobile's inbuilt storage where songs,images are stored.Ipsus
I believe that use of Environment.getExternalStorageDirectory() will result in a security exception in new Android versionsSufferance
Use System.getenv("EXTERNAL_STORAGE"); to get the correct the path or you may try it by yourself in a shell by executing "echo $EXTERNAL_STORAGE".Karelian
I think that there may be some confusion about the difference between physical and logical storage. The built-in storage (i.e. not the SD card) may have some logical "external" storage in it, so it's not really clear what the asker is asking.Counterweight
Great answer. You should remember to use the MediaScannerConnection to scan the new files.Winfield
It throws java.lang.IOException.Carcass
@HyperCreeck Check the link for new documentation. developer.android.com/training/data-storage/app-specificIpsus
When using FileOutputStream, flush() is useless, because the implemention of flush() in OutputStream is empty.Sandysandye
B
20

I did something like this. This allows you to copy all the directory structure to copy from Android AssetManager.

public String copyDirorfileFromAssetManager(String arg_assetDir, String arg_destinationDir) throws IOException
{
    File sd_path = Environment.getExternalStorageDirectory(); 
    String dest_dir_path = sd_path + addLeadingSlash(arg_destinationDir);
    File dest_dir = new File(dest_dir_path);

    createDir(dest_dir);

    AssetManager asset_manager = getApplicationContext().getAssets();
    String[] files = asset_manager.list(arg_assetDir);

    for (int i = 0; i < files.length; i++)
    {

        String abs_asset_file_path = addTrailingSlash(arg_assetDir) + files[i];
        String sub_files[] = asset_manager.list(abs_asset_file_path);

        if (sub_files.length == 0)
        {
            // It is a file
            String dest_file_path = addTrailingSlash(dest_dir_path) + files[i];
            copyAssetFile(abs_asset_file_path, dest_file_path);
        } else
        {
            // It is a sub directory
            copyDirorfileFromAssetManager(abs_asset_file_path, addTrailingSlash(arg_destinationDir) + files[i]);
        }
    }

    return dest_dir_path;
}


public void copyAssetFile(String assetFilePath, String destinationFilePath) throws IOException
{
    InputStream in = getApplicationContext().getAssets().open(assetFilePath);
    OutputStream out = new FileOutputStream(destinationFilePath);

    byte[] buf = new byte[1024];
    int len;
    while ((len = in.read(buf)) > 0)
        out.write(buf, 0, len);
    in.close();
    out.close();
}

public String addTrailingSlash(String path)
{
    if (path.charAt(path.length() - 1) != '/')
    {
        path += "/";
    }
    return path;
}

public String addLeadingSlash(String path)
{
    if (path.charAt(0) != '/')
    {
        path = "/" + path;
    }
    return path;
}

public void createDir(File dir) throws IOException
{
    if (dir.exists())
    {
        if (!dir.isDirectory())
        {
            throw new IOException("Can't create directory, a file is in the way");
        }
    } else
    {
        dir.mkdirs();
        if (!dir.isDirectory())
        {
            throw new IOException("Unable to create directory");
        }
    }
}
Backhouse answered 23/9, 2014 at 6:34 Comment(2)
As he says this lets you copy ALL the directory structure. The accepted answer doesn't. This is the best answer :)Barnabas
How to get and pass arg_assetDir??Exam
G
14

This is my Kotlin solution with auto-closable streams to copy in internal app storage:

val copiedFile = File(context.filesDir, "copied_file.txt")
context.assets.open("original_file.txt").use { input ->
    copiedFile.outputStream().use { output ->
        input.copyTo(output, 1024)
    }
}
Guenevere answered 12/3, 2021 at 15:38 Comment(0)
S
10

try this below code

private void copyAssets() {
    AssetManager assetManager = getAssets();
    String[] files = null;
    try {
        files = assetManager.list("");
    } catch (IOException e) {
        Log.e("tag", "Failed to get asset file list.", e);
    }
    for(String filename : files) {
        InputStream in = null;
        OutputStream out = null;
        try {
          in = assetManager.open(filename);
          File outFile = new File(getExternalFilesDir(null), filename);
          out = new FileOutputStream(outFile);
          copyFile(in, out);
          in.close();
          in = null;
          out.flush();
          out.close();
          out = null;
        } catch(IOException e) {
            Log.e("tag", "Failed to copy asset file: " + filename, e);
        }       
    }
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
    byte[] buffer = new byte[1024];
    int read;
    while((read = in.read(buffer)) != -1){
      out.write(buffer, 0, read);
    }
}
Supination answered 7/10, 2013 at 7:10 Comment(9)
Copy of the same answer !! #4447977Anett
Can you please explain on how to specify the directory where it should be copied? Thank you.Stylolite
File outFile = new File(getExternalFilesDir(null), filename); at this line you have to change as your required pathSupination
File outFile = new File(getExternalFilesDir(null), "/MYFolder/Bhlabhla");Indiscerptible
File outFile = new File(Environment.getExternalStorageDirectory()+"/yourfolder", filename); like this waySupination
No, this copies the data to the EXTERNAL storage.Deerdre
Down voted since its copy from some one else's answer instead of providing link or creditScabious
This code uses getExternalFilesDir() which will copy files to the sdcard associated with this app. This folder will be removed when the app is uninstalled.Sufferance
When using FileOutputStream, flush() is useless, because the implemention of flush() in OutputStream is empty.Sandysandye
H
7

My small solution on Kotlin, for copy data from assets to INTERNAL STORAGE

fun copy() {
    val bufferSize = 1024
    val assetManager = context.assets
    val assetFiles = assetManager.list("")

    assetFiles.forEach {
        val inputStream = assetManager.open(it)
        val outputStream = FileOutputStream(File(context.filesDir, it))

        try {
            inputStream.copyTo(outputStream, bufferSize)
        } finally {
            inputStream.close()
            outputStream.flush()
            outputStream.close()
        }
    }
}
Hiatt answered 7/10, 2013 at 7:1 Comment(2)
When using FileOutputStream, flush() is useless, because the implemention of flush() in OutputStream is empty. And you can also use Stream.use{} to omit the call of closeSandysandye
Only works for files, not folders.Piscator
T
1
public void addFilesToSystem(String sysName, String intFil, Context c){
             //sysName is the name of the file we have in the android os
             //intFil is the name of the internal file



             file = new File(path, sysName + ".txt");

             if(!file.exists()){
                 path.mkdirs();

                 try {

                     AssetManager am = c.getAssets();

                     InputStream is = am.open(intFil);
                     OutputStream os = new FileOutputStream(file);
                     byte[] data = new byte[is.available()];
                     is.read(data);
                     os.write(data);
                     is.close();
                     os.close();

                     Toast t = Toast.makeText(c, "Making file: " + file.getName() + ". One time action", Toast.LENGTH_LONG);
                     t.show();

                     //Update files for the user to use
                     MediaScannerConnection.scanFile(c,
                             new String[] {file.toString()},
                             null, 
                             new MediaScannerConnection.OnScanCompletedListener() {

                         public void onScanCompleted(String path, Uri uri) {
                             // TODO Auto-generated method stub

                         }
                     });



                 }  catch (IOException e) {
                     Toast t = Toast.makeText(c, "Error: " + e.toString() + ". One time action", Toast.LENGTH_LONG);
                     t.show();
                     e.printStackTrace();
                 }

             }
         }

To add a file, call the addFilesToSystem("this_file_is_in_the_public_system", "this_file_is_in_the_assets_folder", context/this context is if you do not have the method in the Activity/

Hope it helps

Toothless answered 7/6, 2015 at 14:4 Comment(0)
I
0

You can use the Envrionment#getDataDirectory method for that. It'll give the path of the data directory of the internal storage memory. This is generally where all the app related data is stored.

Alternately, if you want to store in the root directory, you can use the Environment#getRootDirectory method for that.

Indelible answered 7/10, 2013 at 7:9 Comment(0)
D
0

If you need to copy any file from assets to the internal storage and do it only once:

public void writeFileToStorage() {
        Logger.d(TAG, ">> writeFileToStorage");

        AssetManager assetManager = mContext.getAssets();
        if (new File(getFilePath()).exists()) {
            Logger.d(TAG, "File exists, do nothing");
            Logger.d(TAG, "<< writeFileToStorage");
            return;
        }

        try (InputStream input = assetManager.open(FILE_NAME);
             OutputStream output = new FileOutputStream(getFilePath())) {

            Logger.d(TAG, "File does not exist, write it");

            byte[] buffer = new byte[input.available()];
            int length;
            while ((length = input.read(buffer)) != -1) {
                output.write(buffer, 0, length);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
            Logger.e(TAG, "File is not found");
        } catch (IOException e) {
            e.printStackTrace();
            Logger.d(TAG, "Error while writing the file");
        }

        Logger.d(TAG, "<< writeFileToStorage");
    }

public String getFilePath() {
    String filePath = mContext.getFilesDir() + "/" + FILE_NAME;
    Logger.d(TAG, "File path: " + filePath);
    return filePath;
}
Doriedorin answered 16/11, 2018 at 14:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.