середу, 12 грудня 2012 р.

Android. Problem in database access from service

Few months ago I worked on my first android application. I use AlarmManager for work in background and call from it my intents receiver. Here the code:

public static final int FIRST_RUN = 5000; // 5 seconds
public static final int INTERVAL = 30000; // 30 sec
private AlarmManager alarmManager = null;
....
Intent intent = new Intent(this, FingerNotesServiceReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
this.alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
this.alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + FIRST_RUN, INTERVAL,
pendingIntent);
FingerNotesServiceReceiver - this is my receiver class. It extends BroadcastReceiver class. Everything looks fine, but there are one problem. If you try to open connection to sqlite database file with write permissions from your receiver you will catch the error described below:

android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here


Sqlite don't allow you to create more than one write connections to db file. To prevent this in main process of application you can use static instance of SQLiteOpenHelper. But receiver still throws this error. This happens, because onReceive functions calls on separate process. When you try to gain access to database from receiver - application creates new static SQLiteOpenHelper object. Because existing object is staying in main process. To solve this I was add ContentProvider into application with needed functionality. Receiver interact with database through provider and code looks like I send queries to sqlite directly. As a result I got this scheme for application modules:




You can check my app on google play: FingerNotes