I don't exactly know how android updates the applications. As far as I've read around here it keeps the SQLite database. So, imagine this scenario: one application that uses SQLite database for persisting data. After a while I release v2 which contains some database changes and I need to update user data in database. How can I make this during the update process ?
See SQLiteOpenHelper#onUpgrade. Subclass the SQLiteOpenHelper class and do all the stuff to update the tables in the onUpgrade method.
As you will see, the constructor of SQLiteOpenHelper takes as last parameter the Database version:
version: number of the database (starting at 1); if the database is older, onUpgrade(SQLiteDatabase, int, int) will be used to upgrade the database
Related
My Android App use SQLite database as an asset.
I deliver a .db file in /assets directory to provide both read-only tables and read/write tables.
When the user uses the App, it's datas are stored in read/write tables.
Sometimes I need to modify the schema of the database by adding a column in a table for example.
So I need to deliver a new .db file in the release.
If i do this the problem is that the user loses his data.
Is there a way to export/import the user data when he updates the App on his devise ?
I didn't find anything about this issue on the Web.
The standard way of handling this is, assuming that you are using (extending) the SQLiteOpenHelper class, is to utilise the version number in conjunction with overriding the onUpgrade method to ALTER the schema of the existing database, thus retaining the existing data.
version int: number of the database (starting at 1); if the database is older, onUpgrade(SQLiteDatabase, int, int) will be used to upgrade the database; if the database is newer, onDowngrade(SQLiteDatabase, int, int) will be used to downgrade the database
The SQLiteOpenHelper (or if using SQliteAssetHelper which extends SQLiteOPenHelper), when opening the database (if it exists) compares the coded version number against the version number stored in the header of the database. If the coded version number is greater than the stored version number then the onUpgrade method is called which is passed three parameters,
the SQLiteDatabase
the old (stored) version number as an int
the new (coded) version number as an int
You would typically check old and new and have code that makes the changes (ALTER TABLE or an alternative if the limitations of the ALTER TABLE force to do something like rename the original table, CREATE the changed table with the correct name, copy the existing data from the original table to the new table and finally DROP the renamed original table )
If the App is installed for a new user then that is when the asset will be copied. Thus covering both scenarios.
If not using an extension of SQLiteOpenHelper, then you can mimic using the stored version number by reading 4 bytes at offset 60 and comparing this to a coded version or even by copying the asset and getting the asset's version number, which would be managed with whatever tool you use to maintain the asset (e.g. via the user_version PRAGMA)
SQLite Database Header
I have huge DB, written with SQLiteOpenHelper. Now we are starting to implement Room to our project. So, my question is: how to be with migration problem?
For example, I have version number 100 in MySQLiteOpenHelper. I'm trying to migrate one table (and there are many other tables in DB) to Room.
I've create MIGRATION_100_101 in
MyDatabase : RoomDatabase (#Database(version = 101) class. So, I need to increase version in MySQLiteOpenHelper to 101 and make sure, that MyDatabase with migrations will be called before MySQLiteOpenHelper?
Is there any other way to have both SQLiteOpenHelper and RoomDatabase in one app?
AFAIK Room manages a separate database by itself and there isn't a great way to maintain a custom sqliteopenhelper and a room database. What we did was that we migrated subsets of the tables at once from old sqlite to room (basically, tables that need to be joined together for whatever reason), and kept two separate databases until all of the tables were migrated.
Depending on your situation, might be more painless to do a one-time migration for everything.
The only solution, that allows us to do this is next. Let's imagine, that current DB version is X and we are planing to migrate to version X+1.
Create SQLiteOpenHelper object that will drop all tables, if the current DB version is X and recreates all NOT migrated tables for version X+1. We need to call getReadableDatabase/getWritableDatabase method so, table creation (methods onCreate/onUpgrade) takes place. This SQLiteOpenHelper object will be temporary.
Create RoomDatabase object for version X+2 with fallbackToDestructiveMigration. This will clear all migrated tables and recreates them. Also, we need to call getReadableDatabase/getWritableDatabase for creation take place. This RoomDatabase object is temporary too.
So, on this moment we have already created DB: part of the tables (that are not migrated) will be created by SQLiteOpenHelper, other - by RoomDatabase.
Create RoomDatabase object for version X+2 without fallbackToDestructiveMigration. And this object we are going to use in our application.
Create SQLiteOpenHelper object for version X+2, that will just use created DB (migration from X+1 to X+2 are not required at all, because tables was created by Room at step 2). And this object we are going to use in our application.
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.
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.
Hi I am new to android app development and have no idea of SQLite database.
Are The tables we create and the records we enter to the SQLite database tables happening run time. That means once create tables and insert data, do we have to do the same process again when exit and open the app again?(Only the database, tables and records remain until we open the particular app).
Thank you
Anything you do to the database is persistent. It will contain exactly the same data after your app shuts down and is later restarted.
The database and tables will remain after the app exits.
You can create a class that extends SQLiteOpenHelper to help.
Override the onCreate() and onUpgrade() methods there. onCreate() will get called only when your db doesn't exist yet. You can then execute sql to create the tables etc. onUpgrade will get called when you pass a new version number to the super() constructor.