I have a bound service running multiple threads that read and write to an SQLite database. I create an instance of my database helper and get a connection to the database in the onCreate of my service, which should execute on the main thread. As it's a bound service there should only ever be one instance of the service in memory. However i still get
exceptions occasionally when the service tries to open the database or when one of the threads tries to execute a statement.
Service code:
#Override
public void onCreate() {
super.onCreate();
MyDatabaseHelper helper = new MyDatabaseHelper(this);
database = helper.getWritableDatabase();
}
Exceptions:
java.lang.RuntimeException: Unable to create service uk.co.example.service.MyService:
android.database.sqlite.SQLiteException: unable to open database file
at android.app.ActivityThread.handleCreateService(ActivityThread.java:1959)
at android.app.ActivityThread.access$2500(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:989)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3691)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.database.sqlite.SQLiteException: unable to open database file
at android.database.sqlite.SQLiteDatabase.dbopen(Native Method)
at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1960)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:887)
at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:965)
at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:958)
at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:585)
at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:203)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:118)
at uk.co.example.service.MyService.onCreate(MyService.java:69)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:1949)
... 10 more
android.database.sqlite.SQLiteException: error code 5: database is locked
at android.database.sqlite.SQLiteStatement.native_execute(Native Method)
at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:61)
at uk.co.example.a.a.a.a(MyTable.java:147)
at uk.co.example.service.b.a.m.run(MySaveTask.java:84)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
at java.lang.Thread.run(Thread.java:1019)
Any ideas what could be causing this?
Thanks
David
Sqlite now supports a new journal mode called Writing-Ahead Logging, which is suitable for concurrent access to sqlite. you may want to take a look at http://www.sqlite.org/wal.html.
Related
I'm using this famous database helper and want to copy a database to a device.
I have already filled and pushed the database to emulator through adb, and it works fine on emulator, but the app has difficulty copying the db to devices.
I have also created an assets folder and put the database there at ~/Shiny/app/src/main/assets/database/shiny.db.
Here is my main activity:
Here is my app's specific variables in the DataBaseHelper helper class:
public class DataBaseHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "shiny.db";
private static String DB_PATH = "/data/data/com.shinyapp.shiny/databases/";
private SQLiteDatabase myDataBase;
private Context myContext;
And here is the onCreate method that calls the DataBaseHelper:
but I get this error:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Get a support ActionBar corresponding to this toolbar
ActionBar ab = getSupportActionBar();
// Enable the Up button
ab.setDisplayHomeAsUpEnabled(true);
myDB = new DataBaseHelper(this);
try {
myDB.createDataBase();
} catch (IOException e) {
throw new Error("Unable to create database");
}
try {
myDB.openDataBase();
}catch(SQLException sqle){
throw new Error("Unable to open database");
}
But I get this error:
FATAL EXCEPTION: main
java.lang.Error: Error copying database
at com.shinyapp.shiny.DataBaseHelper.createDataBase(DataBaseHelper.java:61)
at com.shinyapp.shiny.MainActivity.onCreate(MainActivity.java:52)
at android.app.Activity.performCreate(Activity.java:4465)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1053)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1934)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1995)
at android.app.ActivityThread.access$600(ActivityThread.java:128)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1161)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4514)
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:790)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
at dalvik.system.NativeStart.main(Native Method)
I'm wondering what could be wrong here and how can I fix it?
UPDATE: here the error log that I get when I modified error handling to log the error instead of just throwing errors:
05-27 16:13:08.196 23913-23913/com.shinyshop.shiny E/SqliteDatabaseCpp: sqlite3_open_v2("/data/data/com.shinyshop.shiny/databases/shiny.db", &handle, 1, NULL) failed
05-27 16:13:08.204 23913-23913/com.shinyshop.shiny E/SQLiteDatabase: Failed to open the database. closing it.
android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file
app at android.database.sqlite.SQLiteDatabase.dbopen(Native Method)
app at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1124)
app at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1075)
app at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1051)
app at com.shinyshop.shiny.DataBaseHelper.checkDataBase(DataBaseHelper.java:78)
app at com.shinyshop.shiny.DataBaseHelper.createDataBase(DataBaseHelper.java:45)
app at com.shinyshop.shiny.MainActivity.onCreate(MainActivity.java:49)
app at android.app.Activity.performCreate(Activity.java:4465)
app at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1053)
app at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1934)
app at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1995)
app at android.app.ActivityThread.access$600(ActivityThread.java:128)
app at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1161)
app at android.os.Handler.dispatchMessage(Handler.java:99)
app at android.os.Looper.loop(Looper.java:137)
app at android.app.ActivityThread.main(ActivityThread.java:4514)
app at java.lang.reflect.Method.invokeNative(Native Method)
app at java.lang.reflect.Method.invoke(Method.java:511)
app at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
app at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
app at dalvik.system.NativeStart.main(Native Method)
05-27 16:13:08.360 23913-23913/com.shinyshop.shiny E/Creating DB ERROR: exception
app java.io.FileNotFoundException: shiny.db
app at android.content.res.AssetManager.openAsset(Native Method)
app at android.content.res.AssetManager.open(AssetManager.java:315)
app at android.content.res.AssetManager.open(AssetManager.java:289)
app at com.shinyshop.shiny.DataBaseHelper.copyDataBase(DataBaseHelper.java:103)
app at com.shinyshop.shiny.DataBaseHelper.createDataBase(DataBaseHelper.java:57)
app at com.shinyshop.shiny.MainActivity.onCreate(MainActivity.java:49)
app at android.app.Activity.performCreate(Activity.java:4465)
app at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1053)
app at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1934)
app at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1995)
app at android.app.ActivityThread.access$600(ActivityThread.java:128)
app at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1161)
app at android.os.Handler.dispatchMessage(Handler.java:99)
app at android.os.Looper.loop(Looper.java:137)
app at android.app.ActivityThread.main(ActivityThread.java:4514)
app at java.lang.reflect.Method.invokeNative(Native Method)
app at java.lang.reflect.Method.invoke(Method.java:511)
app at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
app at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
app at dalvik.system.NativeStart.main(Native Method)
The sample code that you are using is old and awful.
That being said, your problem is that the sample code is expecting your database to be in ~/Shiny/app/src/main/assets/shiny.db, not ~/Shiny/app/src/main/assets/database/shiny.db. If you want the asset in ~/Shiny/app/src/main/assets/database/shiny.db, you would need to modify the AssetManager code to add the database/ part to the value that you pass to open().
In my android app I am using AsyncTask. It was working perfectly but from last 2 days my app crashed when I called .execute() of AsyncTask. The error is:
FATAL EXCEPTION: main
java.lang.NullPointerException
at android.os.AsyncTask.execute(AsyncTask.java:378)
at com.riksof.a320.remote.RemoteObject.update(RemoteObject.java:117)
at com.fitmo.controller.activity.FitmoEditActivityDetailController.updateActivityDate(FitmoEditActivityDetailController.java:64)
at com.fitmo.controller.activity.FitmoEditActivityDetailController.access$0(FitmoEditActivityDetailController.java:51)
at com.fitmo.controller.activity.FitmoEditActivityDetailController$1.onClick(FitmoEditActivityDetailController.java:45)
at android.view.View.performClick(View.java:2532)
at android.view.View$PerformClick.run(View.java:9293)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:143)
at android.app.ActivityThread.main(ActivityThread.java:4263)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)
When I saw the code inside AsyncTask.java, I found this code inside AsyncTask constructor:
switch (mStatus)
So I debug the AsyncTask status by calling getStatus() method of AsyncTask before calling execute() and the value is null here as well. What can be the reason for this any ideas ?
I am not getting this every time. Some times it works properly sometimes it doesn't.
Did you remove the AsyncTask myTask = new AsyncTask() by accident?
I have written an Android application that uses SQLite database which is saved in assets folder.
This database has 4 tables: "table1", "table2" and "table3" and "android_metadata" . The application works fine on most devices, but some crashes have been reported. So I used acra (Application Crash Report for Android, http://code.google.com/p/acra/ ) to collect the log.
I am sure that the database has "table2" table, however the log says there is no such table. I really wonder why it works fine on some devices, but crashes on some others ?
The model of phone is Samsung GT-I9001GT, Android 2.3.3 . Some HTC desire HD had this problem too.
Please help me resolve it. Thanks.
(The database file size is 33KB)
Log
java.lang.RuntimeException: Unable to start activity ComponentInfo{english.idiom/english.idiom.Category2Activity}: android.database.sqlite.SQLiteException: no such table: table2: , while compiling: SELECT subject,table2_id FROM table2 WHERE table1_id=8
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1651)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
at android.app.ActivityThread.access$1500(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3687)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.database.sqlite.SQLiteException: no such table: table2: , while compiling: SELECT subject,table2_id FROM table2 WHERE table1_id=8
at android.database.sqlite.SQLiteCompiledSql.native_compile(Native Method)
at android.database.sqlite.SQLiteCompiledSql.compile(SQLiteCompiledSql.java:92)
at android.database.sqlite.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:65)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:83)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:49)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:42)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1356)
at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1324)
at english.idiom.Category2Activity.getContents(Category2Activity.java:176)
at english.idiom.Category2Activity.Initialize(Category2Activity.java:138)
at english.idiom.Category2Activity.onCreate(Category2Activity.java:70)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615)
... 11 more
android.database.sqlite.SQLiteException: no such table: table2: , while compiling: SELECT subject,table2_id FROM table2 WHERE table1_id=8
at android.database.sqlite.SQLiteCompiledSql.native_compile(Native Method)
at android.database.sqlite.SQLiteCompiledSql.compile(SQLiteCompiledSql.java:92)
at android.database.sqlite.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:65)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:83)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:49)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:42)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1356)
at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1324)
at english.idiom.Category2Activity.getContents(Category2Activity.java:176)
at english.idiom.Category2Activity.Initialize(Category2Activity.java:138)
at english.idiom.Category2Activity.onCreate(Category2Activity.java:70)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
at android.app.ActivityThread.access$1500(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3687)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
at dalvik.system.NativeStart.main(Native Method)
You really have to check the devices you're willing to support. See
/data/
and check if you have the corresponding table. I've been there, and some devices really differ in terms of package naming, etc.
You can use an app something like, aSQLiteManager to browse schemas.
Other useful sources:
Debugging sqlite database on the device
Android: Where are database files stored?
My question is: do you have other SQL errors in ACRA logs? Particularly, about database corruption?
In my question: Better SQLite corruption detection I presented the quick analysis of SQLite behavior when DB file was randomly modified. When "SELECT *" was failing, sometimes SQLite claimed that it was because the table didn't exist. When I loaded the modified DB file into editor, all tables were missing - so, random modification of the DB file may actually erase all your tables.
I am getting crash reports from sporadic SQLiteExceptions in my application. I am not directly interacting with SQLite databases at all. I have tracked the code down to the usage of the WebView widget. The exceptions differ in cause, but a couple of examples are as follows...
android.database.sqlite.SQLiteException: database is locked: BEGIN EXCLUSIVE;
at android.database.sqlite.SQLiteDatabase.native_execSQL(Native Method)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1768)
at android.database.sqlite.SQLiteDatabase.beginTransactionWithListener(SQLiteDatabase.java:558)
at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:512)
at android.webkit.WebViewDatabase.startCacheTransaction(WebViewDatabase.java:603)
at android.webkit.CacheManager.enableTransaction(CacheManager.java:251)
at android.webkit.WebViewWorker.handleMessage(WebViewWorker.java:214)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:143)
at android.os.HandlerThread.run(HandlerThread.java:60)
Another example...
java.lang.RuntimeException: Unable to create application com.example.MyApplication: android.database.sqlite.SQLiteException: near "VALUES": syntax error: , while compiling: INSERT INTO cache (VALUES (
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:3828)
at android.app.ActivityThread.access$2200(ActivityThread.java:132)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1082)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:150)
at android.app.ActivityThread.main(ActivityThread.java:4293)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.database.sqlite.SQLiteException: near "VALUES": syntax error: , while compiling: INSERT INTO cache (VALUES (
at android.database.sqlite.SQLiteCompiledSql.native_compile(Native Method)
at android.database.sqlite.SQLiteCompiledSql.compile(SQLiteCompiledSql.java:92)
at android.database.sqlite.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:65)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:83)
at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:41)
at android.database.sqlite.SQLiteDatabase.compileStatement(SQLiteDatabase.java:1231)
at android.database.DatabaseUtils$InsertHelper.getStatement(DatabaseUtils.java:858)
at android.database.DatabaseUtils$InsertHelper.getColumnIndex(DatabaseUtils.java:904)
at android.webkit.WebViewDatabase.getInstance(WebViewDatabase.java:397)
at android.webkit.WebView.<init>(WebView.java:1077)
at android.webkit.WebView.<init>(WebView.java:1054)
at android.webkit.WebView.<init>(WebView.java:1044)
at android.webkit.WebView.<init>(WebView.java:1035)
at com.example.MyApplication.getWebView(MyApplication.java:223)
at com.example.MyApplication.loadUrlInWebView(MyApplication.java:249)
at com.example.MyApplication.onCreate(MyApplication.java:169)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:984)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:3825)
... 10 more
Why might these crashes be occurring? Has anyone else had this problem?
Note: The platform in the error reports are each listed as OTHER, so maybe this is only happening in an emulator or unofficial build of the OS.
This is probably related to the webview DOM storage. See WebSettings.setDatabaseEnabled and WebSettings.setDatabasePath.
http://developer.android.com/reference/android/webkit/WebSettings.html#setDatabaseEnabled(boolean)
http://developer.android.com/reference/android/webkit/WebSettings.html#setDatabasePath(java.lang.String)
A common complaint is that the DOM storage does not work, and that is usually fixed with code like this:
mWebView.getSettings().setDomStorageEnabled(true);
mWebView.getSettings().setDatabaseEnabled(true);
mWebView.getSettings().setDatabasePath("/data/data/packagename/databases/");
I never heard of crash problems with this, but it may be worth investigating what happens when you disable DOM storage and when you specify a proper database path (as shown above using your app's packagename).
This thread may also be helpful:
Android - Making Webview DomStorage persistant after app closed
hi my application contains SQLite .My application some time getting the following error
java.lang.RuntimeException: Unable to destroy activity {com.fitzsoftware.grocessaryList/com.fitzsoftware.grocessaryList.GrocessaryList}: android.database.sqlite.SQLiteException: unable to close due to unfinalised statements
at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3655)
at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3673)
at android.app.ActivityThread.access$2900(ActivityThread.java:125)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4627)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.database.sqlite.SQLiteException: unable to close due to unfinalised statements
at android.database.sqlite.SQLiteDatabase.dbclose(Native Method)
at android.database.sqlite.SQLiteDatabase.onAllReferencesReleased(SQLiteDatabase.java:320)
at android.database.sqlite.SQLiteDatabase.close(SQLiteDatabase.java:881)
at com.fitzsoftware.grocessaryList.GrocessaryList.onDestroy(GrocessaryList.java:103)
at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3642)
I am closing the db in Destroy() using DataClass.dh.db.close();
Why this Error occured.Give me the solutions for this.Thanks in advance.
I'm late to the party, but I just saw this. In my case, I had created a Cursor object from a database query, then accidentally closed the database before I closed the cursor. Check whether this is what's happening.
As well Gareth Lloyd's answer, from what I've read of other threads, another cause of this exception is not closing Cursor objects, i.e. attempting to close your SQLiteDatabase instance before closing Cursor objects that have been obtained from querying your SQLiteDatabase instance.