'I can't load a ready database in my room database although I put it in Assets folder
Room.databaseBuilder(getApplicationContext(), UserDatabase.class,"users_db")
.createFromAsset("users.db")
.build();
UserDatabase db = Room.databaseBuilder(getApplicationContext(),
UserDatabase.class,"users_db").allowMainThreadQueries()
.fallbackToDestructiveMigration()
.addMigrations()
.build();
Even I tried to add as a file to prepopulate as "createFromFile" with the following code
Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
.createFromFile(new File("mypath"))
.build();
Solution 1:[1]
If the above is the only code then unless you try to access the database, the database will not be created. That is just getting an instance of the built database just creates an instance that is ready to open the database.
So if you have, for example :-
UserDatabase db = Room.databaseBuilder(getApplicationContext(),
UserDatabase.class,"users_db").allowMainThreadQueries()
.createFromAsset("users.db")
.build();
Then it is not until, for example, you did
SupportSQLiteDatabase accessedDatabase = db.getOpenHelper().getWritableDatabase();
That an attempt to open the database (in the case of no database existing, then an attempt to create the database, and in the case of createFromAsset the create database will then attempt the copy from the asset).
Typically you would not get a SupportSQliteDatabase but would simply try to access the database via the Dao's ( i.e. the methods in the interfaces or abstract classes that are annotated with @Dao).
Demonstration
Consider the following :-
An existing database from an external source (Navicat in the example) :-
- just a single table and therefore @Entity annotated class will be required.
- as can be seen it has 3 users.
- IMPORTANT the schema MUST adhere to what Room expects, which has limitations
The database is copied to the assets folder as users.db :-
An @Entity annotated class User (so the table name will be User) :-
@Entity
class User {
@PrimaryKey
Long id = null;
String username;
}
- 2 columns
- id which is the Primary Key and as the type is Long then the column type must be INTEGER
- username, as it's a String then column type MUST be TEXT, as there is no @NonNUll annotation then NOT NULL should not be coded (if it were then the schema room expects would not be as above)
An @Dao annotated class UserDao :-
@Dao
interface UserDao {
@Insert
long insert(User user);
@Query("SELECT * FROM user")
List<User> getAllUsers();
}
An @Database annotated class UserDatabase :-
@Database(entities = {User.class}, version = 1,exportSchema = false)
abstract class UserDatabase extends RoomDatabase {
abstract UserDao getUserDao();
private static volatile UserDatabase instance = null;
static UserDatabase getInstance(Context context) {
if (instance == null) {
instance = Room.databaseBuilder(context,UserDatabase.class,"users_db")
.allowMainThreadQueries()
.createFromAsset("users.db")
.build();
}
return instance;
}
}
- note the getInstance() method (see the activity code that follows)
Putting it all together in an activity
First a shortened version that does not access the database but just gets an instance of the UserDatabase :-
public class MainActivity extends AppCompatActivity {
UserDatabase db;
UserDao dao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = Room.databaseBuilder(this,UserDatabase.class,"users_db")
.allowMainThreadQueries()
.createFromAsset("users.db")
.build();
dao = db.getUserDao(); //<<<<< WILL NOT OPEN THE DATABASE
}
}
When the above is run AppInspection shows nothing.
However, using :-
public class MainActivity extends AppCompatActivity {
UserDatabase db;
UserDao dao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = Room.databaseBuilder(this,UserDatabase.class,"users_db")
.allowMainThreadQueries()
.createFromAsset("users.db")
.build();
dao = db.getUserDao(); //<<<<< WILL NOT OPEN THE DATABASE
//db.getOpenHelper().getWritableDatabase(); //<<<<< Force an open of the database
//<<<<< WILl OPEN THE DATABASE
for(User u: dao.getAllUsers()) {
Log.d("USERINFO","UserName is" + u.username + " ID is " + u.id);
}
}
/*
Example of using the singleton (not called)
*/
void unusedFromExample() {
UserDatabase db = UserDatabase.getInstance(this);
UserDao dao = db.getUserDao();
/// etc
}
}
and the log includes (as expected) :-
D/USERINFO: UserName isuser1 ID is 1
D/USERINFO: UserName isuser2 ID is 2
D/USERINFO: UserName isuser3 ID is 2000
And AppInspection shows the database and that it has ben copied.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |



