One of my methods in my custom SQLiteOpenHelper class throws an "attempt to re-open already closed object" error whenever I try to invoke it after closing the database. I close my databases in onPause on my MainActivity, and then I make sure to check if they are open before invoking a method on the database.
This is the code for the database method, it is within an AsyncTask.
public void insertData(ArrayList<SavedWifiHotspot> hotspots, ArrayList<MarkerOptions> markers) {
Log.d("insert LocationsDB", "Data inserted");
final SQLiteDatabase db = this.getWritableDatabase();
new AsyncTask<ArrayList<SavedWifiHotspot>, Void, Void>() {
@Override
protected Void doInBackground(ArrayList<SavedWifiHotspot>... hotspots) {
Log.d("insert LocationsDB", "Hotspot inserted");
ContentValues hotspotValues = new ContentValues();
for(SavedWifiHotspot hotspot : hotspots[0]) {
hotspotValues.put("Ssid", hotspot.getSsid());
hotspotValues.put("Password", hotspot.getPassword());
hotspotValues.put("LocationName", hotspot.getHotspotLoc());
hotspotValues.put("Lat", hotspot.getLatitude());
hotspotValues.put("Lng", hotspot.getLongitude());
db.insert(HOTSPOT_TABLE_NAME, null, hotspotValues);
}
return null;
}
}.execute(hotspots);
new AsyncTask<ArrayList<MarkerOptions>, Void, Void>() {
@Override
protected Void doInBackground(ArrayList<MarkerOptions>... markers) {
ContentValues markerValues = new ContentValues();
for(MarkerOptions marker: markers[0]) {
markerValues.put("LocationName", marker.getTitle());
markerValues.put("Lat", marker.getPosition().latitude);
markerValues.put("Lng", marker.getPosition().longitude);
db.insert(LOCATION_TABLE_NAME, null, markerValues);
}
return null;
}
}.execute(markers);
}
This is the code used to call the method:
public void updateLocDB() {
if(!db.isOpen()) {
db = locDB.getReadableDatabase();
}
if(!wifiHotspots.isEmpty() && !markers.isEmpty()) {
locDB.clearData();
locDB.insertData(wifiHotspots, markers);
}
}
Logcat output:
FATAL EXCEPTION: AsyncTask #1
Process: com1032.cw2.fm00232.fm00232_assignment2, PID: 368
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.IllegalStateException: attempt to re-open an
already-closed object: SQLiteDatabase:/data/data/com1032.cw2.fm00232.fm00232_assignment2/databases/locationsDB
at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1659)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1605)
at com1032.cw2.fm00232.fm00232_assignment2.LocationsDB$1.doInBackground(LocationsDB.java:89)
at com1032.cw2.fm00232.fm00232_assignment2.LocationsDB$1.doInBackground(LocationsDB.java:75)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
I've been searching for a few hours, and can't find anything that helps me fix this problem. Any help would be appreciated.
clearData code:
public void clearData() {
Log.d("clear LocationsDB", "Tables cleared");
db = this.getReadableDatabase();
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
String dropHSTable = "DROP TABLE IF EXISTS "
+ HOTSPOT_TABLE_NAME + ";";
String dropLocTable = "DROP TABLE IF EXISTS "
+ LOCATION_TABLE_NAME + ";";
db.execSQL(dropHSTable);
db.execSQL(dropLocTable);
createTables(db);
return null;
}
}.execute();
}
As per my understanding you are executing two asynchronous task at same time. And creating/opening a SQLite DB connection in both tasks. Which creates the problem.
As, it is not possible to create two connections of SQLite DB. Because SQLite is ThreadSafe, only one thread can perform read/write operation at a single time.
You can not perform read and write operations concurrently on SQLite until you do not use WAL(Write Ahead Logging). Follow this for more info Concurrency in SQLite database