Is there any documentation on how to best deal with database upgrades in android?
I am developing an application and have been testing it on my own telephone. All works fine, over the past few deploys I had to add some columns to my table and due to upgrade statements that are executed if the old database version is lesser then a certain database version.
However when I try to run the application on another phone, that gives errors due to the fact that there is no previous version and thus the column isn't added.
Is there any best practice or documentation on how to handle database upgrading and versioning? I tried googling around for specific questions, but much good didn't come out of that.
Here's the relevant code I am using at the moment:
private static final int DATABASE_VERSION = 11;
private static class LocalLoginDatabaseHelper extends SQLiteOpenHelper {
LocalLoginDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
Log.d(TAG,DATABASE_CREATE);
db.execSQL(DATABASE_CREATE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if(oldVersion < 11) {
Log.d(TAG + "Upgrade",DATABASE_ALTER);
db.execSQL(DATABASE_ALTER);
}
}
}
Thanks
Is there any documentation on how to best deal with database upgrades in android?
Use SQLiteOpenHelper, which will give you control when a schema change is detected, so you can upgrade the database.
UPDATE
However when I try to run the application on another phone, that gives errors due to the fact that there is no previous version and thus the column isn't added.
Your DATABASE_CREATE needs to have the column as well. For a new install (or after the user does Clear Data on your app), there is no existing database, and so onCreate(), not onUpgrade(), is called.
Shameless Plug: I know you have this issue resolved but I am working on an open source set of DSL's that makes it easy to create SqliteOpenHelper/ContentProvider/Contract API and manages upgrades through migrations http://robotoworks.com/mechanoid-plugin/mechanoid-db
Its still very early days and I am busy writing docs however its already useful to anyone working with sqlite in Android and the more people using it will make it better :)
Related
For SQLiteOpenHelper, if I add a new table inside onCreate do I have to do anything inside onUpgrade? I am adding a completely new table. I believe I have to change the version number but that onUpgrade should remain empty. Is that correct?
If you want existing installs of the app to add this new table, then yes, you must increase the version and provide a suitable onUpgrade() implementation, as well as adding the table in onCreate() (which you stated you have already done).
An empty onUpgrade() implementation is not sufficient; it has to actually do something. Some people drop all tables and just call onCreate() directly, but this obviously doesn't work well if you are trying to keep existing data. I usually use the fall-through switch idiom, so that if a user is more than one version behind (e.g. you publish a version 3 and a user is still on version 1) they will go through all the necessary upgrades sequentially:
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1:
db.execSQL("CREATE TABLE " + ...);
// no break statement, so case 2 will execute after this.
case 2:
// more execSQL(), etc
}
}
onCreate() will not be called if a user already has installed your app previously. So you need to create the new table in onUpgrade(), too. Be sure to increase the version number of your database.
I suggest putting the code to create the table in a helper method so that you can call it from both callback methods. This will reduce the chance of an error in case you need to change the code to create the table.
onUpgrade will only be called if you increase the version number.
To implement it you must recreate the tables with any changes you have made and copy over any existing data. There are many tutorials on this topic.
It is not necessary to implement if you are still learning, but if you don't and you make any changes to your schema you'll need to uninstall the app from the device or the changes won't be applied.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
Currently making an app for the very first time, its a massive learning curve for me and the results are satisfying.
So at the moment I have my design all set up, now I need to work on the database side of things.
I have found all the basics to creating tables and adding entries, however I'm a little unsure where I should be inserting this code.
My queries are:
=> Does the code for creating the database tables, inserting/editing/deleting data need to have its own class, separate classes or is it all be done in the class of the 'Form' I have created.
=> How do you connect to the DB so I can call the results, does this need its own class also for showing the entries or can this be done on my 'Entries' class.
Working with android studio, if anyone can give me a better understanding would be much appreciated.
=> Does the code for creating the database tables, inserting/editing/deleting data need to have its own class, separate classes or is it all be done in the class of the 'Form' I have created.
=> How do you connect to the DB so I can call the results, does this need its own class also for showing the entries or can this be done on my 'Entries' class.
I'll answer both of those at the same time:
You don't actually need to make all of the code for the database usage on a separate class, it can be done in the same Android extended class you are working on. Though I highly reccomend you to make a separate one to keep things organized and easier to find.
Basically all of your queries will be managed with a Cursor class, that works pretty much like an iterator, no secrets here.
I would suggest that you take a look at MVC Architecture to help you organize your code and make it as clean as an OxiCelan ad.
Its a pretty easy thing to do. You need to create a class that extends SQLiteOpenHelper. In the default constructor you need to pass a few values.
Take this for example:
public DBHandler (Context context, String name, SQLiteDatabase.CursorFactory factory, int version){
super(context, DATABASE_NAME, factory, DATABASE_VERSION);
}
Define a final field DATABASE_NAME and DATABASE_VERSION in the class.
Override onCreate and onUpgrade methods and you are good to go.
onUpgrade method:
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_ACCOUNT);
onCreate(db);
}
In the onCreate you need to give the query to create your table. Create the query as a string and just use execSQL on SQLiteDatabase object to execute that query.
I want to know if it is possible to add a table to my remote database after the app has been running on my device for a couple of weeks, and still work?
For instance, if I'm using a Android device and have a simple game with 3 levels using SQLite db. Now I want to add a 4th level to the game, without losing progress on the other 3 levels or having to re install the app to accommodate for db changes?
In simple words YES it's possible. You can change your database design with out losing any data. You can achieve by overriding the 'onUpgrade' method in your database class which extends SQLiteOpenHelper.
You need to change the database version number when you update your app. If the database version number is greater than the previous one then onUpgrade method get called.
#Override
public void onUpgrade(SQLiteDatabase db, int newVersionNumber, int oldVersionNumber) {
// Do your Changes here. You can Alter table, Drop column etc
}
Remote Database - Its not linked with app. So you can change what ever you want. It won't affect your app. But you need to handle it efficiently.
Hope it helps.
Yes. it is possible, you can upgrade it.
You must set old and new database version.
public void onUpgrade(SQLiteDatabase db, int newVersionNumber, int
oldVersionNumber)
Imagine the following scenario (I allow backup / restore from my app, I'm doing backup / restore white the entire file.db):
The user make backup of the database.
In the future I do an update on my application which has a new version of the database.
what would happen if the user restore the database with the old version?
How can I avoid this kind of problem?
It would be a good idea to use BackupHelper? I did a simulation of the worst scenario of my database and gave 20k, BackupHelper is recommended for less than 1mb, it would be a good idea to use it? I think my app will never exceed 100kb.
You access SQLite databases via a SQLiteOpenHelper, which provides three callbacks: onCreate(), onUpgrade() and onOpen().
The constructor declares a version parameter, and internally it compares the database version (which is stored in the file) with the supplied argument. If the requested version is newer than the file's, your onUpgrade(db, old, new) is called and you get a chance to alter tables, fill rows and so on.
The restore procedure should simply close all open cursors and helpers and copy the new file in.
May be this is not the best approach but you can do it as:
1- Store the DB Version in the database.
2- After restoring the database, check the DB Version and do the required changes accordingly. Like
void afterRestoration()
{
long dbVersion = get from db;
if(dbVersion == 1)
{
alter table1 add column1;
}
else
{
}
}
I have developed an android app that accesses local sqlite database inside the app.
I have a question of how to upgrade the app. In this case, say if an application source code changes OR the database data/structure changes, how do I package these changes?
do i have to repackage complete app and make it available as a new app version ? or can I just package only the changed files into a much smaller build size and push it to market ?
In general, how is the application upgrade/update process carried out ?
If you're extending SQLiteOpenHelper (you should be), its constructor takes a version parameter, which is an integer value you should define in a constant like DATABASE_VERSION somewhere.
Override the onUpgrade method and implement the logic for upgrading your schema and/or data.
When you increment the DATABASE_VERSION constant (in an app update for instance), any existing installs that have a lower version will fire the code in onUpgrade.
Change DATABASE_VERSION of your db and next time you will start the app
the db will be recreated.
For both, you basically just export a new version of your application from Eclipse, and upload the new APK through your market account.
Application version changes are handled by a tag in the manifest: android:versionCode. Each time you export a updated APK, you need to increment the version code. versionName is just the label that's displayed to users in the market, so can be whatever you like.
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.package"
android:installLocation="auto"
android:versionCode="17"
android:versionName="0.74">
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="12" />
<uses-permission
android:name="android.permission.INTERNET"></uses-permission>
...
As for the database, the easiest way to do it is to sub-class SQLiteOpenHelper. Then, in your sub-class you can have something like this:
private class DBHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "mydatabase.db";
private static final int DATABASE_VERSION = 45;
public DBHelper(Context context)
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
...
The SQLiteOpenHelper handles opening the database, and updates when the application launches. In the above example, the database version is 45. If you increment that, and upload a new APK to the market, an onUpgrade() method is called, which allows you to update users old databases to your new version.