Gra*_*and 29 sqlite android android-webview
我有一个只读数据库连接.有时,当使用SELECT查询从数据库中读取数据时,它会抛出一个SQLiteReadOnlyDatabaseException.
我这样打开连接:
return SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY);
Run Code Online (Sandbox Code Playgroud)
查询是:
Select * FROM BudgetVersions WHERE entityId = ?
Run Code Online (Sandbox Code Playgroud)
我使用数据库读取数据db.rawQuery(),如下所示:
String query = ...;
Cursor c = db.rawQuery(query, new String[]{ activeBudgetId });
try {
if (c.moveToFirst()) {
bv.versionName = c.getString(c.getColumnIndexOrThrow("versionName"));
return bv;
} else {
return null;
}
} finally {
c.close();
}
Run Code Online (Sandbox Code Playgroud)
很少,我在这样的调用中遇到了这样的崩溃c.moveToFirst():
Caused by: android.database.sqlite.SQLiteReadOnlyDatabaseException: attempt to write a readonly database (code 776)
at android.database.sqlite.SQLiteConnection.nativeExecuteForCursorWindow(Native Method)
at android.database.sqlite.SQLiteConnection.executeForCursorWindow(SQLiteConnection.java:845)
at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:836)
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:144)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133)
at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:197)
at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:237)
Run Code Online (Sandbox Code Playgroud)
作为一种解决方法,我可以尝试使用可写数据库连接,但我想知道崩溃发生的原因.
我正在阅读的表是一个标准的SQLite表:
CREATE TABLE BudgetVersions (
entityId VARCHAR PRIMARY KEY NOT NULL UNIQUE,
budgetId VARCHAR NOT NULL,
versionName VARCHAR NOT NULL,
dateFormat VARCHAR,
currencyFormat VARCHAR,
lastAccessedOn DATETIME,
isTombstone BOOL NOT NULL,
deviceKnowledge NUMERIC NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
我已经看到崩溃发生在KitKat仿真器和运行Lollipop的设备上.
有一个独立的可写连接打开到同一数据库在同一时间,一个拥有web视图.数据库正在由WebView中的Javascript代码更新,并使用此只读连接从本机Android/Java层读取.
我希望这可能是问题的最终原因,但我想详细了解为什么只读连接会干扰单独的可写连接.
我很清楚,一般的建议是使用单个连接到数据库,但由于可写连接是由拥有的WebView,我无法从Java代码轻松访问它.
Gra*_*and 17
通过将其更改为可写数据库连接来解决.线索在776错误代码的文档中:
(776)SQLITE_READONLY_ROLLBACK
SQLITE_READONLY_ROLLBACK错误代码是SQLITE_READONLY的扩展错误代码.SQLITE_READONLY_ROLLBACK错误代码表示无法打开数据库,因为它有一个需要回滚的热日志,但由于数据库是只读的而无法打开.
在开发过程中,我经常打断当前正在运行的应用程序以安装和运行新版本.这会导致当前正在运行的应用程序被系统强制停止.如果WebView中的Javascript代码在应用程序被破解时通过其单独的可写连接写入数据库,那么热门日志将被遗忘.
当新版本的应用程序启动时,将打开本机Java代码中的只读数据库连接.当此连接发现日志时,它会尝试回滚期刊.因为它是只读连接,所以它失败了.
(这与我在做出改变后立即在启动时观察到的崩溃相吻合.)
因此,正确的解决方法是使Java连接成为可写连接.此连接在正常操作期间从不尝试写入,但必须在通过WebView的可写连接从先前中断的写入中恢复时进行写入.