RSS Feed
Feb 14

On Upgrading your Android App Database

Posted on Friday, February 14, 2014 in Coding

GnuCash Android has come a long way since it’s first release and in that time, lot of changes have been made to the database schema. Android has a special mechanism for this in the onUpgrade() method which is called when the database version number changes. Up until version 1.2.7, GnuCash had this method implemented as follows:

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    if (oldVersion < newVersion){
        Log.i(TAG, "Upgrading database to version " + newVersion);
        if (oldVersion == 1 && newVersion == 2){
            //execute upgrade queries
        }
        if (oldVersion == 2 && newVersion == 3){
            //execute database upgrade queries
        }
    }
}

Can you spot the problem? Go ahead, take your time, I’ll wait. Most of it is the common boilerplate you’d expect: checking that the database operation is actually an upgrade, logging, etc.
But then come the important lines…let’s take another look:

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    if (oldVersion < newVersion){
        Log.i(TAG, "Upgrading database to version " + newVersion);
        if (oldVersion == 1 &amp;&amp; newVersion == 2){
            //execute upgrade queries
        }
        if (oldVersion == 2 && newVersion == 3){
            //execute database upgrade queries
        }
    }
}

Whenever a user skips an upgrade and then tries to upgrade at a later version, then none of the if statements will ever be true. Hence no database upgrade will be performed. This can lead to all manner of headaches for the user due to an inconsistent database schema. Mea maxima culpa!

It has been possible for this error to go undetected for this long because, I guess, most users accept the updates they are proposed or even allow the Play Store to automatically upgrade the apps. But for the small percentage of users who skip an upgrade, well, that would be the beginning of trouble. The typical way to solve this would be to uninstall and reinstall the application, which is not ideal.

While this was going on, Navneet Karnani created a patch which was meant to add another feature to the app, but which included a fix for the database issue.
The database upgrade code should look like this:

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    if (oldVersion < newVersion){
        Log.i(TAG, "Upgrading database to version " + newVersion);
        if (oldVersion == 1 && newVersion >= 2){
            //execute upgrade queries
            oldVersion = 2;
        }
        if (oldVersion == 2 && newVersion >= 3){
            //execute database upgrade queries
            oldVersion = 3;
        }
    }
}

There is a small but very significant difference in the code.
First, we check whether the new database version is greater than or less than what we expect. Also, and very crucially, we update the oldVersion variable to the next version after performing the upgrades to the old version. This ensures that if we are upgrading over several database versions, then all the upgrade steps for the intermediate versions will also be performed.

It is also possible to implement the database upgrade method as switch statements. I’ll leave that as an exercise to you.

The next version of GnuCash Android (v1.3.1) is currently available in the Google Play Store and includes these changes which should improve stability.

Feb 10

GnuCash Android v1.3.0 released

Posted on Monday, February 10, 2014 in Coding, GnuCash

Just a public service announcement to the effect that version 1.3.0 of GnuCash for Android has been released to the Google Play Store.
This version includes numerous changes, including, but not limited to the following:

  • Mark favorite accounts and quickly access them
  • Display different tabs for recent, favorite and all accounts
  • Add, view and delete recurring transactions (daily, weekly, monthly)
  • Mark accounts as placeholder accounts (cannot contain transactions)
  • Set a default transfer account for each account
  • Color code accounts and themed account views
  • Create default GnuCash account structure from within app
  • Numerous bug fixes and improvements

For the full change log, visit the GitHub repository

Thanks to all who contributed in this release and the translators who dutifully put up with me bugging them for string updates.

Work on the next version will commence soon and I am excited for what is coming next.

Enjoy the release!

P.S. If you don’t see it in the Play Store yet, give it some time 😉