1

I'm developing an Android application that uses sqlite database from differens threads and process, such as Widget and services.

Using the singleton pattern to grant a connection, I randomly get this error: the app remains stuck in the getWriteableDatabase() method, and this warning appears in the log

W/SQLiteConnectionPool( 2021): The connection pool for database '/data/data/xyz' has been unable to grant a connection to thread xyz (xyz) with flags 0x1 for xyz seconds.
W/SQLiteConnectionPool( 2021): Connections: 0 active, 1 idle, 0 available.

This error happens usually after several hours the app is closed and I reopen it, but there isn't a formal way to reproduce this bug.

I tried to use both this approaches, but with no lucky:

class DB extends SQLiteOpenHelper {

    DB databaseHelper;
    SQLiteDatabase database;

    /**
     * Open a Database Helper.
     *
     * @param c the Context used to open the Database.
     * @return the Database Helper.
     */
    public static DB getInstance(final Context c) {
        if (databaseHelper == null) {
            databaseHelper = new DB(c.getApplicationContext());
        }
        return databaseHelper;
    }

    int active_connections;

    /**
     * @return the Database connection to use
     * @see closeReadableDataBase()
     */
    public synchronized SQLiteDatabase getDatabase() {
        if (database == null || !database.isOpen()) {
            if(database!=null) database.close();
            database = getWritableDatabase();
            active_connections=0;
            database.setLockingEnabled(false);
            TransitionHelper.execSQL(database, "PRAGMA read_uncommitted = true;");
            TransitionHelper.execSQL(database, "PRAGMA synchronous=OFF;");
        }
        active_connections++;
        return database;
    }

    /**
     * Closes the database connection.
     * @see openDatabaseForRead()
     */
    public synchronized void closeDatabase() {
        active_connections--;
        if(active_connections==0 && database!=null){
            database.close();
            database=null;
        }
    }
}

And:

class DB extends SQLiteOpenHelper {

    DB databaseHelper;
    SQLiteDatabase database;

    public static DB getInstance(final Context c) {
        if (databaseHelper == null) {
            databaseHelper = new DB(c.getApplicationContext());
        }
        return databaseHelper;
    }

    public synchronized SQLiteDatabase getDatabase() {
        if (database == null || !database.isOpen()) {
            if(database!=null) database.close();
            database = getWritableDatabase();
        }
        return database;
    }

    public synchronized void closeDatabase() {
        if(database!=null){
            database.close();
       }
    }
}
mipe34
  • 5,596
  • 3
  • 26
  • 38
Spotlight
  • 1,279
  • 1
  • 13
  • 28
  • i think you need a singleton design of db this link might help http://stackoverflow.com/questions/6905524/using-singleton-design-pattern-for-sqlitedatabase – DjHacktorReborn Mar 07 '13 at 19:50
  • Consider using a [content provider](http://developer.android.com/guide/topics/providers/content-providers.html). It will save your time a lot… –  Mar 07 '13 at 20:12
  • @DjHacktorReborn As you can see in the second code block, I use a singleton pattern – Spotlight Mar 08 '13 at 13:40

1 Answers1

1

If you find yourself using an SQL database from different processes, you should really consider encapsulating it in a content provider. In conjunction with a loader, a content provider facilitates access across processes, DataObservers, and so forth. There's even an API guide for creating them: Creating a Content Provider

Joe Malin
  • 8,621
  • 1
  • 23
  • 18
  • As per the docs, you don't need a content provider if all the activities form part of a single application (including services). – strange Nov 04 '13 at 23:04