How to use Room Persistence Library with pre-populated database?

I'd like to use Room with a pre-populated database, but I can't understand how to tell Room where to find my database.

I've now put it in src/main/assets/databases and when I create the instance for the Room database I create it this way:

Room.databaseBuilder(
    getApplicationContext(),
    AppDatabase.class,
    "justintrain.db"
)
.allowMainThreadQueries()
.build();

This way tho, I think it's creating a new database every time, or anyways, it's not using the pre-populated one.

How can I make it to find my database?


This is how I solved it, and how you can ship your application with a pre-populated database (up to Room v. alpha5)

  • put your SQLite DB database_name.db into the assets/databases folder

  • take the files from this repo and put them in a package called i.e. sqlAsset

  • in your AppDatabase class, modify your Room's DB creation code accordingly:

    Room.databaseBuilder(context.getApplicationContext(), 
                         AppDatabase.class, 
                         "database_name.db")
    .openHelperFactory(new AssetSQLiteOpenHelperFactory())
    .allowMainThreadQueries()
    .build();
    

Note that you have to use "database_name.db" and not getDatabasePath() or other methods: it just needs the name of the file.


UPDATE (Nov 7th 2019)

Room now supports using a pre-packaged database out of the box, since version 2.2.0

https://developer.android.com/jetpack/androidx/releases/room#2.2.0

Solution before version 2.2.0: Simple solution without any other external libraries.

Room relies on the existing Android framework code to create or open a database. If you look into the source code of FrameworkSQLiteOpenHelper (Room's version of SQLiteOpenHelper) it internally calls SQLiteOpenHelper.getReadableDatabase() and other methods wherever needed.

So, the simplest solution is to just copy the DB file from assets directory to mContext.getDatabasePath("my-database.sqlite") before creating the DB with Room.

In your case, the code looks something like this -

private final String DB_NAME = "my-database.sqlite";

private MyDatabase buildDatabase(Context context) {
    final File dbFile = context.getDatabasePath(DB_NAME);

    if(!dbFile.exists()) {
        copyDatabaseFile(dbFile.getAbsolutePath());
    }

    return Room.databaseBuilder(context.getApplicationContext(),
        MyDatabase.class, DB_NAME)
        .build();
}

private void copyDatabaseFile(String destinationPath) {
    // code to copy the file from assets/database directory to destinationPath
}

This link has the code needed to copy the DB - link with code


I was having the same problem so I created a library which does exactly that. the accepted answer work but I think it's easier to use a library.

AppDatabase db = RoomAsset
    .databaseBuilder(context.getApplicationContext(), AppDatabase.class, "database_name.db")
    .build(); 

Add it to your root build.gradle at the end of repositories:

allprojects {
    repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}

Add the dependency

dependencies {
    // ... other dependencies
    implementation 'com.github.humazed:RoomAsset:v1.0'
}

you can find the library here: https://github.com/humazed/RoomAsset