Sunday 9 September 2012

My first Android app

I just finished writing my first Android app Screensaver Photo Frame:
During this project I hit a few gotchas which I wanted to share. Below I listed the most critical things to remember while starting developing for Android.

1. Exceptions = Force close

Whenever the application throws an exception, it will cause Android to force close the application. So to avoid frustration for the users, catch any potential exception and handle them properly.

2. Database locking issues

As you might already noticed, multi-threading is critical for any Android application. The issue with multi-threading and built in database is however that you are destined to run into SQLiteDatabaseLockedException by following most getting started guides.
The trick is to use SQLiteOpenHelper as a singleton and let SQLite manage the synchronization.
In the cut-down example below, two threads can call addSomething() simultaneously and SQLite will handle the synchronization within itself preventing lock exception.
DBAdapter:
public class DBAdapter {
    private static SQLiteDatabase db = null;
    public static synchronized DBAdapter getInstance(Context ctx)
    {
        if (db == null ) {
            DatabaseHelper DBHelper = new DatabaseHelper(ctx);
            db = DBHelper.getWritableDatabase();
        }
        return new DBAdapter();
    }
    public void addSomething(String something) {
        ContentValues initialValues = new ContentValues();
        initialValues.put(KEY_SOMETHING, something);
        db.insertWithOnConflict(DATABASE_SOMETHING_TABLE, null, initialValues,
                SQLiteDatabase.CONFLICT_REPLACE);
    }
    private static class DatabaseHelper extends SQLiteOpenHelper
    {
        ...
    }
}
Activity:
public class MainActivity extends Activity {
    private DBAdapter database;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        database = DBAdapter.getInstance(getApplicationContext());
        database.addSomething("something");
    }
}


3. Multi-row SQL execution

Since Android 4-ish it is not possible to run queries separated by semi-colon anymore.
So instead of executing SQL as:
db.execSQL("CREATE TABLE A ...; CREATE TABLE B ...;");
Split it up into multiple executions:
db.execSQL("CREATE TABLE A ...;");
db.execSQL("CREATE TABLE B ...;");