Android handle app updates and database changes - android

I have basically finished developing an android app that makes use of SQLite databases that I copy to the user data area on the device eg /data/data/com.company.app/databases/users.db
I am unsure how the marketplace app update procedure takes place and am also unsure as to how I could test it.
I currently check whether the database exists on the device and copy it if it doesn't (generally only occurs on first ever launch). What happens if I have a new version of the database in my updated app? Will an marketplace update wipe user data so that it will copy my new database in on next launch?
What happens in the future if I make database changes/add records/etc and package this with the new app? Will this database not overwrite the old database?
Otherwise, to avoid copying and overriding the databases from the app bundle on every launch is there a way to check the size and date of the database files and only copy if the database in the bundle is newer?
If anyone needs clarification please ask.

I am doing something similar. What I did is set the database version, and then when I check if the database exists, I also to make sure it's the correct version. If it's not, I save user favorites from the database, wipe and recopy my db, and then put back user favorites.
This is my on upgrade
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion == 2) {
System.out.println("Performing upgrade!");
openDataBase();
// save the old favorites
Cursor mCursor = getFavorites();
ArrayList<Stop> favs = allCursorToStops(mCursor);
mCursor.close();
deleteRecreate(db);
openDataBase();
for (int i = 0; i < favs.size(); i++)
setFavorite(favs.get(i));
close();
} else {
deleteRecreate(db);
}
}
Here is where I check existence/if need to upgrade etc
boolean dbExist = checkDataBase();
if(dbExist){
// check if we need to upgrade
openDataBase();
int cVersion = myDataBase.getVersion();
close();
if(cVersion != VERSION)
onUpgrade(myDataBase, myDataBase.getVersion(), VERSION);

Related

shared preference and database problem when we update old to new version

When we add new shared preference key value details for new version android app and When we add column to existing sqlite database in android will it automatically creates these all details when old user updates from play-store?
If you are installing the new version of existing application Shared Preferences will give no error but in SQLite, you need to change the version of DB also otherwise new changes will not reflect back until you re-install it again, but it will truncate all the existing data in SQLite. So it is better to change the version.
Version is mentioned inside the constructor of your Database class.
For example,
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, 6);
mContext = context;
}
In this the 4th paramter is version
Shared preferences persist until you completely un-install the application.
And as far as database is concerned, you can make changes in it. There is a concept known as "database migration".
If you are using Room, this might help,
https://developer.android.com/training/data-storage/room/migrating-db-versions
If you are using simple Sqlite without Room, you have to make changes in the onUpgrade() function,
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// add Column here
if (newVersion > oldVersion) {
db.execSQL("ALTER TABLE foo ADD COLUMN new_column INTEGER DEFAULT 0");
}
}

Manage database versioning on app Update [Android]

I have a local SQLite database on an Android app and I'm a bit confused on how to manage it when the app gets updated. I need to keep the data stored in the DB whenever I update the app but also I think i'm going to add columns and probably also tables. What's the best practice to do so?
My idea was to check the DB version and if it matches the old version call a method to add the new columns/tables and then upgrade the version, is it the correct approach or there's something else to consider?
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < 2) {
db.execSQL(DATABASE_ALTER_TEAM_1);
}
if (oldVersion < 3) {
db.execSQL(DATABASE_ALTER_TEAM_2);
}
if (oldVersion < 4) {
db.execSQL(DATABASE_ALTER_TEAM_3);
}
}
This is the best way of handling the onUpgrade(). Because users may not update all versions, In that cases this is the best approach.

Update specific table when onUpgrade with SQLite with provided database

Probably there is somewhere here answer to my question, but if it exist I can't find it.
Here is my problem:
I have provided database in assets folder. When I want to update my app because I put some more rows in specific table I increase db version, call this.getWritableDatabase(); and onUpgrade is called, to this point everything is ok.
But what next?
Here is my onUpgrade function:
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i2) {
if(i < i2) {
SQLiteDatabase db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null,SQLiteDatabase.OPEN_READWRITE);
db.execSQL("attach database ? as newdb", new String[]{DB_PATH + DB_NAME}); // I have to attach new version of db to the old one and then i can go on
db.execSQL("delete from GAME");
db.execSQL("INSERT INTO GAME SELECT * FROM newdb.GAME");
db.close();
}
This gives me an error that my db is locked - on the line:
db.execSQL("INSERT INTO GAME SELECT * FROM newdb.GAME");
I tried a lot of different scenarious but I just can't make it.
I'll be very glad if someone could help me make it works ;)
If your onUpgrade does not use its first parameter, it does something wrong.
db and newdb are the same database (both times opened with DB_PATH + DB_NAME).
You probably want to replace db with sqLiteDatabase.
onUpgrade means that you want to upgrade your database, not to copy some data from old one to new. this method gives you all you need to do upgrade - db instance to roll upgrade scripts for specific version. SQL is very powerful you can add/remove columns, delete tables and so on, so I don't see a reason to make another file.

When to use internal storage vs. sqllite

I'm making a simple android app.
When first loaded, the app will show users a list of items (A)
The users will be able to add more items to this list
Each item can be clicked on which will show another list (B)
The users will be able to add more items to the second list as well.
I've gotten the first point done by storing few items in list and presenting them in ListView. I am wondering how can users add new items to the list and how would I persist?
I've seen several tutorials on internal storage and sql lite. Which one would be best for my needs in this scenario?
I would really benefit from a sample app on github that kind of shows how to accomplish this.
You also know :
Internal Storage
Store private data on the device memory.
By default, files saved to the internal storage are private to your application and other applications cannot access them (nor can the user). When the user uninstalls your application, these files are removed.
People always use internal storage when they want to read/write the large file via InputStream/OutputStream.
SQLite Databases
Store structured data in a private database.
Please notice structured data, it will be good for you to access the Sqlite database via name, so it will be fast.
P/s: If you need inflate data to the list item. You should use Sqlite since it fast and easily to access the data via name.
It really depends on how you want to use the data. SQLite is easy to use on Android and runs fast. I'm using it for a fairly large database in my app.
I also suggest putting it in internal storage. That way, it is protected from other apps spying on the user's data (unless he "roots" his phone). One caveat on using internal storage is that it's hard to see your data. To get to the db you either need to run Android on an emulator (where you will have the privilege to see all files) or copy the db (by writing some code to copy a file) to external storage. Or simply temporarily put the db in external storage while you are debugging.
I don't have any github references for you, but can give you a quick outline. Subclass SQLiteOpenHelper and add methods for your CRUD actions.
public class DbHelper extends SQLiteOpenHelper
{
private static final int DB_VERSION = 1;
#Override
public void onCreate(SQLiteDatabase db)
{
String[] ddl = {"... all the tables you need to create..."};
db.beginTransaction();
try
{
for (int i = 0, limit = ddl.length; i < limit; i++)
db.execSQL (ddl [i]);
db.setTransactionSuccessful();
}
finally
{
db.endTransaction();
}
}
#Override
public void onUpgrade (SQLiteDatabase db, int oldVersion, int newVersion)
{
db.beginTransaction();
try
{
for ( ; oldVersion < newVersion; oldVersion++)
{
if (oldVersion == 1)
onUpgrade1to2 (db);
else if (oldVersion == 2)
...
}
db.setTransactionSuccessful();
}
finally
{
db.endTransaction();
}
}
public void insertItem (SQLiteDatabase db, Item item) // Item is one of your objects
{
ContentValues values = new ContentValues();
// id
values.put ("id", item.id);
values.put ("subject", item.subject);
...
db.insertOrThrow ("Items", null, values);
}
... and so on ...
}
Let me know if you need info on how to query, update, and delete...

Upgrading Sqlite database in android?

I have an android application which is using Sqlite as database.It has following tables:
Hotels
Locations
Favorites
I am keeping my raw database file in assests folder and when user installs my app i just copies this database to /data/data/package_name/databases directory.Initially Favorites table is empty and it gets populated after user start liking hotels.My problem is that I want to launch my updated version of app with some bug fixes and some new hotels added to the database, so I need to update database of existing users with new hotels and locations without affecting the favorites table.Now if I keep my old approach and update the Database Version Number then application will remove the old database and use the new database but all data in favorites table will be lost.I don't want it to happen.Now problem is how do I update Hotels and Locations table without loosing data in Favorites table.
I know this question was asked long ago, but I had a similar issue and wanted to share my solution, seems to do the trick for me. I'm a novice so feel free to give input-
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//code to keep table data
List<obj> objList = new ArrayList<obj>();
String selectQuery = "SELECT score,list_name,quiz_length FROM obj_table";
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
obj o = new obj();
o.final_score = cursor.getInt(0);
o.quiz_name = cursor.getString(1);
o.quiz_length = cursor.getInt(2);
objList.add(o);
} while (cursor.moveToNext());
}
//done storing data, now upgrade DB from asset file
try {
//my db file is upgraded here
copyDataBase();
} catch (IOException e) {
}
//now insert our saved table data
for (Score obj_rec: objList){
ContentValues values = new ContentValues();
values.put("score", obj_rec.final_score);
values.put("list_name", obj_rec.quiz_name);
values.put("quiz_length", obj_rec.quiz_length);
db.insert("obj_table", null, values);
}
}
Before updating write the contents of you previous table to a file and save it on the sdcard.
Then you may update your database with new version.
And after doing that copy back the data from the backup file(from sdcard) to the updated database. After the successful copying of the backup, delete the file from the sdcard.
Usualy upgrade a database has to be done with SQLiteOpenHelper class. I would advise You to do some tests at Your own device before publish it. You have to increment Your Database Version and call "ALTER TABLE" method from sqlite. This has been discussed in many threads here, the clearest one I think is this one:
Difficulty in upgrading SQlite table
and here is even a article with some solution:
http://joshhendo.blogspot.de/2012/03/android-sqlite-database-upgrade.html
However, a safe way would be to save the old database in a tempfolder, that the user can get back the old one if anything is running into chaos.

Categories

Resources