I have read a lot of topics about this error message but I can't resolve my problem.
I have an app on google play and I get some error reports from the users. When I am trying the app, everything works fine.
In the application, I am managing a big database with something like 30 tables. I am closing the database in my main activity onDestroy() and all the cursors are closed when the query is finished.
I really don't know why from time to time the users are getting this error message.
Here is the entire error log:
java.lang.IllegalStateException: database /data/data/mdpi.android/databases/LocalDatabase.db (conn# 0) already closed
at android.database.sqlite.SQLiteDatabase.verifyDbIsOpen(SQLiteDatabase.java:2213)
at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1565)
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1525)
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1605)
at mdpi.android.database.LocalDatabase.getHistoryLastSuccessfullUpdate(LocalDatabase.java:661)
at mdpi.android.Journals$7.onItemClick(Journals.java:723)
at android.widget.AdapterView.performItemClick(AdapterView.java:292)
at android.widget.Gallery.onSingleTapUp(Gallery.java:960)
at android.view.GestureDetector.onTouchEvent(GestureDetector.java:1310)
at android.widget.Gallery.onTouchEvent(Gallery.java:937)
at android.view.View.dispatchTouchEvent(View.java:5724)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1964)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1725)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1970)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1739)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1970)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1739)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1970)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1739)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1970)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1739)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1970)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1739)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1970)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1739)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2071)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1405)
at android.app.Activity.dispatchTouchEvent(Activity.java:2426)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2019)
at android.view.View.dispatchPointerEvent(View.java:5904)
at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3155)
at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2670)
at android.view.ViewRootImpl.processInputEvents(ViewRootImpl.java:1000)
at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2679)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4517)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:993)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:760)
at dalvik.system.NativeStart.main(Native Method)
And another one:
java.lang.RuntimeException: Unable to start activity ComponentInfo{mdpi.android/mdpi.android.UserInformations}: java.lang.IllegalStateException: database /data/data/mdpi.android/databases/LocalDatabase.db (conn# 0) already closed
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2202)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2237)
at android.app.ActivityThread.access$600(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1262)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:4974)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalStateException: database /data/data/mdpi.android/databases/LocalDatabase.db (conn# 0) already closed
at android.database.sqlite.SQLiteDatabase.verifyDbIsOpen(SQLiteDatabase.java:2194)
at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1536)
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1496)
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1576)
at mdpi.android.database.LocalDatabase.getUserInformations(LocalDatabase.java:357)
at mdpi.android.UserInformations.onCreate(UserInformations.java:122)
at android.app.Activity.performCreate(Activity.java:4538)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1071)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2158)
... 11 more
EDIT: One new error.
Today, I got a new error related to the database access:
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:278)
at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
Caused by: java.lang.NullPointerException
at android.database.sqlite.SQLiteStatement.releaseAndUnlock(SQLiteStatement.java:290)
at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:115)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1718)
at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1591)
at mdpi.android.database.LocalDatabase.insertCountry(LocalDatabase.java:143)
at mdpi.android.database.CountryTable.EnterCountry(CountryTable.java:21)
at mdpi.android.UserInformations$insertCountryAsync.doInBackground(UserInformations.java:270)
at mdpi.android.UserInformations$insertCountryAsync.doInBackground(UserInformations.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:264)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
... 4 more
onDestroy()
will only be called when the activity is finished/destroyed/removed from stack. When you are moving out of the activity onStop()
will be called. If you need to keep your current design, just call close in onStop()
. NOTE: onStop of the current activity will be called after onCreate/onRestart of the new/next activity.
If you have one single DB you can use an SQLiteOpenHelper class as mentioned by pawelieba Also you can have the sqlite db reference in the Application class, and you can just use the reference in all activities, like
((MyApplication)getApplication()).db
Just open the DB in onCreate()
of the Application class and close it in onTerminate()
.
You can also take a look at other SO answers for this error. It has been asked a lot of times before.
java.lang.illegalstateexception database not open android
Android java.lang.IllegalStateException database already closed
Android insert the data SQLite error Caused by java.lang.IllegalStateException: database not open
SQLite database has native interface which is accessible through SQLiteDatabase
- this class takes care for synchronizing access to the native SQLite from different threads.SQLiteDatabase
is cached in SQLiteOpenHelper
which takes care for providing instance of SQLiteDatabase
, it's singleton pattern.
From my experience, you ought to have one instance of SQLiteOpenHelper
and get cached SQLiteDatabase
from it. Then you don't need to take care for closing/opening SQLiteDatabase
.
One instance of SQLiteOpenHelper
for the application is necessary to have single instance of SQLiteDatabase
in the app. It will solve problems with multi-threaded access to the native database.
In short: singleton of SQLiteOpenHelper
from which you get database for each query.
I'm using Roboguice to deal with the ugly singleton pattern.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With