Question

I want to copy the files and folders of my assets folder on a specified folder on sd-card. Here's my code:

private void copyFiles() {

    AssetManager assetManager = getAssets();
    InputStream in = null;
    OutputStream out = null;

    try
    {
        String files[] = assetManager.list("Files");

        for (String fileName : files)
        {
            Log.d("File name =>", fileName);

            in = assetManager.open("Files/" + fileName);

            out = new FileOutputStream(Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyApp/Files/" + fileName);

            copyFile(in, out);

            out.flush();
        }

        in.close();
        out.close();
    }
    catch (IOException e) { e.printStackTrace(); }
}

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);
}

The problem is this method does not copy sub-folders items of the assets on sd-card. In fact on the first occurrence it catches IO exception. here's my assets folder structure:

enter image description here

Here is the LogCat error message:

01-12 20:13:51.692: W/System.err(12798): java.io.FileNotFoundException: Files/01
01-12 20:13:51.742: W/System.err(12798):    at android.content.res.AssetManager.openAsset(Native Method)
01-12 20:13:51.742: W/System.err(12798):    at android.content.res.AssetManager.open(AssetManager.java:325)
01-12 20:13:51.742: W/System.err(12798):    at android.content.res.AssetManager.open(AssetManager.java:299)
01-12 20:13:51.742: W/System.err(12798):    at com.handydic.view.WelcomeScreen.copyDefaultTheme(WelcomeScreen.java:105)
01-12 20:13:51.742: W/System.err(12798):    at com.handydic.view.WelcomeScreen.setup(WelcomeScreen.java:70)
01-12 20:13:51.742: W/System.err(12798):    at com.handydic.view.WelcomeScreen.onCreate(WelcomeScreen.java:38)
01-12 20:13:51.742: W/System.err(12798):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1072)
01-12 20:13:51.742: W/System.err(12798):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1836)
01-12 20:13:51.742: I/RosieUtility(12838): enable self killer: mEnabled=0
01-12 20:13:51.742: W/System.err(12798):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1893)
01-12 20:13:51.742: W/System.err(12798):    at android.app.ActivityThread.access$1500(ActivityThread.java:135)
01-12 20:13:51.752: W/System.err(12798):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1054)
01-12 20:13:51.752: W/System.err(12798):    at android.os.Handler.dispatchMessage(Handler.java:99)
01-12 20:13:51.752: W/System.err(12798):    at android.os.Looper.loop(Looper.java:150)
01-12 20:13:51.752: W/System.err(12798):    at android.app.ActivityThread.main(ActivityThread.java:4385)
01-12 20:13:51.752: W/System.err(12798):    at java.lang.reflect.Method.invokeNative(Native Method)
01-12 20:13:51.752: W/System.err(12798):    at java.lang.reflect.Method.invoke(Method.java:507)
01-12 20:13:51.752: W/System.err(12798):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849)
01-12 20:13:51.752: W/System.err(12798):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
01-12 20:13:51.762: W/System.err(12798):    at dalvik.system.NativeStart.main(Native Method)

The forth line in LogCat output "copyDefaultTheme()" indicates line 105 which is where I have written "in = assetManager.open("Files/" + fileName);"

Any idea what to do? Thanks.

Was it helpful?

Solution

As you see, I've edited my code and instead of Log.e(...) I've written "e.printStackTrace();"

You should have left it as Log.e(). Your problem with your previous edit was that you failed to copy and paste the whole stack trace. That is important, because the first line of the exception tells you what you did wrong:

java.io.FileNotFoundException: Files/01

Calling assetManager.list("Files") should return a two-element array, with the strings "01" and "02", representing the two subdirectories in Files/. You then need to recursively descend into those to find the files, plus create corresponding directories in your output.

You can find sample code for this on StackOverflow, in this blog post, in this GitHub Gist, and in lots of other pages found via a Web search for android copy assets recursively.

Also, a better location than Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyApp/Files/" is getExternalFilesDir(), a method available on any Context, such as your Activity. This not only already gives you an app-specific directory on external storage, but it is one that will be automatically deleted when the user uninstalls your app.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top