Update prepopulated Room database - android

Imagine I deliver a prepopulated database with my application version 1.
The prepopulated database includes a table "my_items" with the column item:
item
------
apple
For application version 2 I deliver an updated prepopulated database, so table "my_items" includes
item
------
apple
milk
How would one make sure that the new prepopulated data is transfered to the database of the app in a non-destructive way? (user is allowed to insert new items to "my_items" by himself and I need to keep his input). I read the Room migrations documentation, but it seems like the prepopulated data is only read on a destructive migration, which is not what I want, as the items entered by the user himself shall remain available.

Room's built in migration processing does not support the merging of existing data into a new prepopulated database.
An approach that should work is to give the prepackaged database file for each app version a unique name, e.g. my_items1.db, my_items2.db, etc. In app version 2, create the main database from prepackaged database file my_items2.db. Then open the database for the previous version as a separate Room database instance, query it to find the items added by the user, and insert those into the new main database with appropriate default values for new fields. This merge processing could be triggered by the onCreate() callback for the main database. The merge processing should be done in a transaction. If it completes successfully, you can close and delete the database for the previous version. In the event of failure, you'll need to notify the user and implement some sort of mitigation processing.

Related

android room the reinstall app migration is not running

when I created a migration, I inserted some data, but the newly installed app did not perform the migration.
do I need to insert/update data on the onCreate call every time I migrate?
Migrations won't run if you install the app, as no Database exists so it is created.
Migrations are designed to handle new versions of the App being published and specifically new versions that also change the Room database version.
do I need to insert/update data on the onCreate call every time I migrate?
NO! onCreate will not run, it only runs once automatically for the lifetime of the database (unless you call it from the Migration).
For an App to be installed, it cannot exist and thus must be uninstalled, the uninstall deletes all the App's data including the databases.
You should be doing what is required in the Mirgation code and then it depends on what you do. e.g. :-
If adding a column for instance and you use the ALTER TABLE your_table ADD COLUMN the_new_column_definition then the existing data is preserved.
If adding a new table then there is no issue.
If however you wanted to change a column's definition (other than it's name) then you have to drop and recreate the table. What would typically be done would be to create the new table, populate it from the original table, rename or drop the original table and the rename the new table to be the name of the original table.
You may wish to have a look at SQLite ALTER TABLE

Handling database changes when app version number changes

I'm trying to figure out the best way to handle database upgrades and versioning.
At the moment I delete the database and log users out when I do a point release, which isn't a great experience.
Can anyone recommend any tips for doing this?
Your database version is independent of your app version. If your database schema doesn't change at all, you shouldn't need to do anything to your database during an update.
When your database schema changes, you should handle database updates in onUpgrade() of your SQLiteOpenHelper. This method is called when you try to access your database and you have updated your database version, as described in the Data Storage Options documentation.
If you are using a third party library to handle your databases, it should either handle the upgrade for you or provide similar functionality.
There is no universal strategy for upgrading your database here. What you do depends completely on what your schema looked like before the upgrade and what the new schema looks like. Depending on what changed, you might create new tables or columns, delete tables or columns, update rows in the database, or move data between tables. If you have a specific question about how to migrate your data, create a new question describing the new and old schemas.
The way we do it is that we run a routine every time the app starts that calls a stored proc on the server to get SQL that upgrades the database if it is necessary. (The sql can be quite involved: dropping tables and recreates them with new structures and inserting new values). We store the version of the database in the database itself and upgrades to the new version.
We don't use the onUpgrade() call.

Use ActiveAndroid on existing database-content

I developed an Android-App where I saved data in a SQLite database using the SQLiteOpenHelper.
I am wondering if I could update my app by using ActiveAndroid, but in a way that the user data previously stored in the database will be preserved.
Is that possible?
You would have to perform a data migration during runtime after the user upgrades to the newest version of the app. The process could be broken down into the following steps, I have also assigned database version values to each step.
The user has all of their data stored in a SQLite database and has not upgraded their app yet. [DB = SQlite v1]
On upgrade, when the user is upgrading to the next version of the
app read all data from the old SQLite database and store it into the
ActiveAndroid database. [DB = SQLite v1 and ActiveAndroid v1]
Once all of the data has been migrated to the new ActiveAndroid database then delete all tables of the SQLite database so that you don't use extra storage space that you do not need. [DB = SQLite v2 and ActiveAndroid v1]
In the next release you can then assume that user has had their data fully migrated and at this point it is finally safe to remove all code that was previously referencing the SQLite database. [DB = ActiveAndroid v2]

Adding additional columns to SQLite from previous Android app version

In my android app, I was using a standard SQLite database with a helper class that had 1 table with 3 columns. In the most recent update I had to add another column of to the table, but some users have reported crashes, which (judging by the stack trace) I think comes from the new version trying to read from a column that does not exist because the data is from the old version. How can I protect the users' data between updates short of a manual backup and restore?
Here is the link to the complete updated database class:
https://github.com/cjbrooks12/scripturememory/blob/working/src/com/caseybrooks/scripturememory/databases/VersesDatabase.java
SQLiteOpenHelper will handle the database versioning, you will just have to provide it with proper database version numbers and overridden callbacks. Looking at your code:
Your DB_VERSION is 1. When you change the database schema between released versions, you should increment this number. The version number is stored in the database file, and if the version provided in code is different from the one stored in file, onUpgrade() or onDowngrade() will be called accordingly. In your case, since the database file already exists, no onCreate() was called and since the version numbers matched, no upgrade was performed.
Your onUpgrade() drops the table and then recreates it. In some cases this might be ok, say, it's just a cached copy of data stored elsewhere, but usually as a user, I don't want an app upgrade to delete my data. Implement onUpgrade() so that it does the necessary schema modifications while preserving data. Some generic strategies for this:
If it's just adding some columns ALTER TABLE and put some suitable default values.
If it's more complex schema change, rename the old tables to temporary names, create new tables and then migrate data from the temp tables.
In any case, after onUpgrade() the database schema should be in the same shape it would be if onCreate() was called to create a new database, but with existing data preserved.

android sqlite on application update

I hava an android application which consists sqlite database in the assets folder.
In the DB I have several tables, which one of them is user data (which is updated over time by using the application - when the user installs the application this table is empty).
The other tables store data that I update.
The question is: when a user gets an updated version of my application (with sqlite database in the assets folder) from the market, I need to keep the data the user updated by using the application, but i do want to update the other tables (which consist my data).
What is the correct way to do it?
Thank You :)
Keep a version number for each change and implement the onUpgrade method for the possible combinations. See more in the javadoc for SQLiteOpenHelper
Since you said your tables are empty when the Database is first created, it shouldn't be necessary to add the Database from the /assets-folder.
Instead, you can use a SQLiteOpenHelper, which offers an onCreate()-method that can do the initial table-creation (an add some example data if necessary).
If you then update your app, you simply increase the Database-version and the onUpgrade()-method is called, where you can then perform the Database update.
See this other question: Run some code when user update my app
If your app comes with a huge Database and inserting entry's in the SQLiteOpenHelper isn't the right way to go, you can still check if the Database already exists and then do the updating (through the onUpgrade()-method) and keep the users data.

Categories

Resources