Android: copy database from asset folder, but only get an empty file

11,663

Solution 1

I wouldn't copy any database form the assets-folder. If you need some standard entry's in your Database, you can add them using INSERTs in your onCreate()-method.


Update: Since this is getting down-voted for being wrong (which is kinda right) and I can't delete it, here is a little update.

I'd say it depends upon how many standard entries you want to add to your database. If it's just one or two, shipping a packed DB might not be worth it.

Anyways, some apps come with rather large databases (for example, a recipe collection). You can obviously not add all these in code.

  • For small test-entries, I'd still prefer simply adding them in onCreate().
  • For bigger databases, you should pre-populate them and ship em along with your app.

For the later to work, you'll need to copy the database file from assets/ to your app-folder. There is a nice library to handle that for you: android-sqlite-asset-helper

Solution 2

Why wouldn't you copy from assets? It's perfectly normal to do so. But you can't do it in the onCreate, at that point an empty database is already created. You need to do it prior. I usually do it in an override of getWriteableDatabase, something like

public synchronized SQLiteDatabase getWritableDatabase() {
    SQLiteDatabase db = null;

    if (!doesDatabaseExist()) {
        try {
            copyDatabase();
            db = super.getWritableDatabase();
        } catch(Exception ex) {
            Log.e("Database Log", getDatabasePath() + " failed to copy correctly. " + ex.getLocalizedMessage());
        }
    }
    else {
        db = super.getWritableDatabase();
    }

    return db;
}

Solution 3

I don't know if it is still usefull but here is the solution for others that get here to see the awnser. The code you used, works for most phones, some older phones have different behaviour with the getReadableDatabase() function. Your problem therefore is not in the copyDataBase function but in the createDataBase function.

in createDataBase() there is the following check;

this.getReadableDatabase();

This checks if there is already a database with the provided name and if not creates an empty database such that it can be overwritten with the one in the assets folder. On newer devices this works flawlessly but there are some devices on which this doesn't work. Mainly older devices. I do not know exactly why, but it seems like the getReadableDatabase() function not only gets the database but also opens it. If you then copy the database from the assets folder over it, it still has the pointer to an empty database and you will get table does not exist errors.

So in order to make it work on all devices you should modify it to the following lines:

SQLiteDatabase db = this.getReadableDatabase();
if (db.isOpen()){
    db.close();
}

Even if the database is opened in the check, it is closed thereafter and it will not give you any more trouble.

Share:
11,663
4af2e9eb6
Author by

4af2e9eb6

true | false

Updated on July 07, 2022

Comments

  • 4af2e9eb6
    4af2e9eb6 almost 2 years

    guys, I have the problem when copying database from local assets folder to /data/data/package_name/databases directory. As I use the http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/ tutorial to do it, I can only get an empty file.

    I quoted the part of copyDataBase() method and there is no difference. Every time the app start, it will create the directory and empty database. So is there any way to make the copyDataBase() work?

    Thank you very much!!

  • 4af2e9eb6
    4af2e9eb6 about 13 years
    Thank you! It's just 2 hours job. :)
  • Horst Dehmer
    Horst Dehmer almost 13 years
    Why not copy a db file from assets? In my case it's a R/O database with 19 tables and 35k lines worth of insert statements. I see no reason why I would initialize such a database on the device. Is there something I'm missing?
  • Horst Dehmer
    Horst Dehmer almost 13 years
    Works for me (Android 2.3.3). Clean and solid.
  • Alexey
    Alexey almost 13 years
    I had to change it a little: if (!doesDatabaseExist()) { try { SQLiteDatabase db = super.getReadableDatabase(); db.close(); } catch (Exception ignore) {} copyFromAssets(); return super.getReadableDatabase(); } Otherwise it was crashing with FileNotFoundException, probably because database directory didnt exist. (Android 2.2)
  • Chameron
    Chameron over 12 years
    Is there any way that don't need to copy to data folder ? Could we read directly from assets folder ?
  • OldSchool4664
    OldSchool4664 about 11 years
    The key is the call to createEmptyDatabase(). Without this, the call to "new FileOutputStream()" fails, even though it is supposed to create the file if it does not exist.