Copy directory from Assets to local directory

Solution 1:

As suggested by dmaxi in comment above, you can use his link, with this code:

    void displayFiles (AssetManager mgr, String path) {
        try {
            String list[] = mgr.list(path);
            if (list != null)
                for (int i=0; i<list.length; ++i)
                {
                    Log.v("Assets:", path +"/"+ list[i]);
                    displayFiles(mgr, path + "/" + list[i]);
                }
        } catch (IOException e) {
             Log.v("List error:", "can't list" + path);
        }
     }

I took it on this link. Maybe you can combine this code with precedent one.

EDIT: see also AssetManager.

private void copyFolder(String name) {
            // "Name" is the name of your folder!
    AssetManager assetManager = getAssets();
    String[] files = null;

    String state = Environment.getExternalStorageState();

    if (Environment.MEDIA_MOUNTED.equals(state)) {
        // We can read and write the media
        // Checking file on assets subfolder
        try {
            files = assetManager.list(name);
        } catch (IOException e) {
            Log.e("ERROR", "Failed to get asset file list.", e);
        }
        // Analyzing all file on assets subfolder
        for(String filename : files) {
            InputStream in = null;
            OutputStream out = null;
            // First: checking if there is already a target folder
            File folder = new File(Environment.getExternalStorageDirectory() + "/yourTargetFolder/" + name);
            boolean success = true;
            if (!folder.exists()) {
                success = folder.mkdir();
            }
            if (success) {
                // Moving all the files on external SD
                try {
                    in = assetManager.open(name + "/" +filename);
                    out = new FileOutputStream(Environment.getExternalStorageDirectory() + "/yourTargetFolder/" + name + "/" + filename);
                    Log.i("WEBVIEW", Environment.getExternalStorageDirectory() + "/yourTargetFolder/" + name + "/" + filename);
                    copyFile(in, out);
                    in.close();
                    in = null;
                    out.flush();
                    out.close();
                    out = null;
                } catch(IOException e) {
                    Log.e("ERROR", "Failed to copy asset file: " + filename, e);
                } finally {
                    // Edit 3 (after MMs comment)
                    in.close();
                    in = null;
                    out.flush();
                    out.close();
                    out = null;
                }
            }
            else {
                // Do something else on failure
            }       
        }
    } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
        // We can only read the media
    } else {
        // Something else is wrong. It may be one of many other states, but all we need
        // is to know is we can neither read nor write
    }
}

// Method used by copyAssets() on purpose to copy a file.
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);
    }
}

EDIT 2: i'have added an example above: this piece of code copy only a specific folder from assets, to sd card. Let me know if it works!

Solution 2:

Here is a recursive function to do this - copyAssetFolder.

public static boolean copyAssetFolder(Context context, String srcName, String dstName) {
    try {
        boolean result = true;
        String fileList[] = context.getAssets().list(srcName);
        if (fileList == null) return false;

        if (fileList.length == 0) {
            result = copyAssetFile(context, srcName, dstName);
        } else {
            File file = new File(dstName);
            result = file.mkdirs();
            for (String filename : fileList) {
                result &= copyAssetFolder(context, srcName + File.separator + filename, dstName + File.separator + filename);
            }
        }
        return result;
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
}

public static boolean copyAssetFile(Context context, String srcName, String dstName) {
    try {
        InputStream in = context.getAssets().open(srcName);
        File outFile = new File(dstName);
        OutputStream out = new FileOutputStream(outFile);
        byte[] buffer = new byte[1024];
        int read;
        while ((read = in.read(buffer)) != -1) {
            out.write(buffer, 0, read);
        }
        in.close();
        out.close();
        return true;
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
}

Or the same in Kotlin

fun AssetManager.copyAssetFolder(srcName: String, dstName: String): Boolean {
    return try {
        var result = true
        val fileList = this.list(srcName) ?: return false
        if (fileList.isEmpty()) {
            result = copyAssetFile(srcName, dstName)
        } else {
            val file = File(dstName)
            result = file.mkdirs()
            for (filename in fileList) {
                result = result and copyAssetFolder(
                    srcName + separator.toString() + filename,
                    dstName + separator.toString() + filename
                )
            }
        }
        result
    } catch (e: IOException) {
        e.printStackTrace()
        false
    }
}

fun AssetManager.copyAssetFile(srcName: String, dstName: String): Boolean {
    return try {
        val inStream = this.open(srcName)
        val outFile = File(dstName)
        val out: OutputStream = FileOutputStream(outFile)
        val buffer = ByteArray(1024)
        var read: Int
        while (inStream.read(buffer).also { read = it } != -1) {
            out.write(buffer, 0, read)
        }
        inStream.close()
        out.close()
        true
    } catch (e: IOException) {
        e.printStackTrace()
        false
    }
}