The Room persistence data library, part of the collection of Android Architecture Components libraries, has made life easier for many developers by simplifying development and maintenance of databases in Android applications. However, sometimes, we need data to be available as soon as we open an app or for an app to be independent of internet connection. In addition, there is no simple and straightforward solution to populate the database with pre-packaged data in the application’s own APK or with data downloaded from a server.
For this purpose, data from another database is usually copied. This requires a lot of effort, as there is concern about bank access, schema validation, thread synchronization, and file locking and reading. Another possibility is populating the database with a data description file such as XML, JSON or CSV, which, within the application, is converted into objects. This option is also costly, since it requires the implementation of an entire service that makes this conversion.
That is no longer the case. Starting with version 2.2 of Room, you can populate your database with data from a .db file. To do this, we can use the RoomDatabase.Builder#createFromAsset() and RoomDatabase.Builder#createFromFile() methods, depending on what is the location of your pre-packaged database. In this article, we will show you how to use these methods, as well as some tips for working with pre-packaged databases.
In this Gist, you will find the original code for booting a sample database without using the new methods provided by Room. The file will be modified so that the boot is made from a pre-packaged database.
First of all, you should understand the difference between the two new methods:
If the file containing the pre-packaged database is within the assets/ directory, that is, if it is already embedded in the application, use createFromAsset(), using the path to the file within assets/ as a parameter. So, considering that we have the path assets/databases/foobar.db, the database startup becomes:
Now, if the file is not embedded in the application and is, for example, downloaded from a server, use createFromAsset (), passing a File object as a parameter. The method should be started like this:
With these commands, starting your database is very fast and simple. But there are some points that need special attention, as they can complicate what was meant to be simple, and the documentation can be very unclear, sometimes even incomplete.
Files in .db format are different from .sqlite files.
The file that will be uploaded with the application or that will be downloaded is not the creation script or population of the database. A .db file is the export of an existing database, with its definitions and data described. Therefore, it is necessary that the database to be imported is created beforehand. We recommend using SQLite Browser to execute data entry and table creation queries and to export the .db file.
If the pre-packaged file is wrong, Room will throw a RuntimeException: “Cannot copy database file”. Also, don’t forget that Room copies the file instead of just opening it, so the file must have reading permission.
Databases must follow the same schema
SQL (Structured Query Language) must follow the same representation of Room database models, since it validates the structure of the database not only in one migration, but also in the creation based on another database. For this to be done in a very simple way, it is enough that the exportSchema parameter of the Room is true.
Thus, when the application is compiled, a schema folder will be generated within the project’s app folder. Inside this folder, a JSON file with the schema of your Room database will be created. This file contains all the queries for creating the tables.
If the pre-packaged SQL database is not reflecting the same model representation, Room throws a SqliteException exception: “Database file is corrupt”.
In this Gist, you will find the .sqlite file used to create the external database, the .db file that is pre-packaged in the application and the complete schema that represents the application’s Room database structure.
Thus, it has become much simpler to create applications with 100% off-line data or data imported from an external database, taking advantage of the data integrity protection provided by Room.