0

I've looked and tried a dozen of responses on the same question, and I'm having no luck.

I an fairly new to Android development, but coming from a Java / C# background I'm pretty sure, what I'm trying to do, is no rocket science.

Unfortunately I cannot root the device I'm using so please no comments around rooting, I just need, as the title suggests, to copy a file from the /assets/ folder to the /data/data/ directory on my device.

Herewith the piece of code I'm using:

private void copyDatabase(File dbFile) throws IOException {
    InputStream is = context.getAssets().open(DB_NAME);
    OutputStream os = new FileOutputStream(dbFile);

    byte[] buffer = new byte[1024];
    while (is.read(buffer) > 0) {
        os.write(buffer);
    }

    os.flush();
    os.close();
    is.close();
} 

This really is not brainer, I have a static field called DB_NAME which points to the assets folder. Debugging this line, proves that the required file is identified and output to memory successful.

The line that fails is the next one: ... new FileOutputStream(dbFile); which I pass in from another method.

dbFile is constructed as follows:

File dbFile = context.getDatabasePath(DB_NAME);

Again, nothing fancy. This grabs the databases path for the current context (application) and appends the name of the database to that, so for argument sake, we have,

/data/data/co.za.simple.sqlite/database/sqlitedb.db

The error message is that the file or directory does not exist, which is fine, on first load for any normal user who will be downloading the application, now, the default behaviour for FileOutputStream(string), as I understand it is that it will create it if it does not exist.

As stated, first runs, this file does not exist, yet, it's giving me an error saying the file or directory cannot be found. This makes me believe that the actual error is that the app does not have the permissions to write to the /data/ directory, so I've added the only permissions I see in the list, that applies to writing to storage:

android.permission.WRITE_EXTERNAL_STORAGE

Yet this has absolutely no effect.

As stated, I cannot root this device and nor will I want to at this point.

I've gone through countless blogs, youtube views and even threads on here in regards to the exact same issue and none of those solutions apply.

Am I missing anything?

eldarerathis
  • 35,455
  • 10
  • 90
  • 93
JadedEric
  • 1,943
  • 2
  • 26
  • 49
  • Check out this post http://stackoverflow.com/questions/22903540/android-copy-files-from-assets-to-data-data-folder – Fareya Nov 20 '14 at 22:45

1 Answers1

0

new FileOutputStream(stuff) expects that the directory to put the file in exist. It will create the file if it doesn't exist but it won't create the path. The result of a missing path is a FileNotFoundException.

Any running app should have an existing /data/data/[packagename]/ directory. But any subdirectory is optional. Most methods of context will create the directory for you once you request them. getDatabasePath for some reason doesn't.

Adding

dbFile.getParentFile().mkdirs();

before creating the stream should fix the problem. You can also remove the permission if you don't use it. Your private directory does not require any.

Alternatively using https://github.com/jgilfelt/android-sqlite-asset-helper could fix it as well and maybe even more corner cases.

zapl
  • 63,179
  • 10
  • 123
  • 154