【问题标题】:Open Database for ReadWirte not possible on specific device在特定设备上无法打开 ReadWirte 数据库
【发布时间】:2014-04-11 15:34:59
【问题描述】:

我只是尝试以 READWRITE 模式打开数据库。我收到以下错误:“不是错误(代码 0):无法以读/写模式打开数据库。”以相同的方式打开数据库时,但 READONLY 是有效的。在我的 3 台设备上,这不是在 READWRITE 中打开的问题,但有 2 位用户报告了以下错误。

数据库存在于用户文件系统中。我用 file.exists() 检查这个 -> 好的。 db 文件在用户设备上是可读写的。我用 file.canWrite() 检查这个 -> 好的。

dbfile 存储在:

存储路径:/mnt/extSdCard/mypath/mydb.db

09.03.2014 上的新信息:这似乎只是 KitKat 4.4.2 中的一个问题。由于用户已更新到 4.4.2,他们遇到了这个问题。

我的代码:

public void onCreate(Bundle savedInstanceState) {


connectWriter(); // throws exception below.

public void connectWriter() {
        chronica_connection_readwrite = SQLiteDatabase.openDatabase("MyPath", null, SQLiteDatabase.OPEN_READWRITE);
        //chronica_connection_read.enableWriteAheadLogging();
    }

异常报告:

java.lang.RuntimeException: Unable to start activity ComponentInfo{...}: android.database.sqlite.SQLiteException: not an error (code 0): Could not open the database in read/write mode.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2282)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2340)
at android.app.ActivityThread.access$800(ActivityThread.java:157)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1247)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5293)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.database.sqlite.SQLiteException: not an error (code 0): Could not open the database in read/write mode.
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:342)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:232)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:515)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:207)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:178)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:891)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:859)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:696)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:671)
at myclass.connectWriter(ChronicBrowser.java:14286)
at myclass.LoadModule(ChronicBrowser.java:10792)
at myclass.onCreate(ChronicBrowser.java:761)
at android.app.Activity.performCreate(Activity.java:5389)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2246)


************ DEVICE INFORMATION ***********
Brand: samsung
Device: hlte
Model: SM-N9005
Id: KOT49H
Product: hltexx

************ FIRMWARE ************
SDK: 19
Release: 4.4.2
Incremental: N9005XXUENB7 

【问题讨论】:

  • 你为什么不使用SQLiteOpenHelper?您不必直接处理数据库以在不同模式下打开。
  • 我真的很想使用我的连接作为mentoined。我的数据库不是由应用程序创建的,我没有版本控制。我的数据库将由我的应用程序下载。我想这应该可以在每台设备上打开读写连接。有什么提示吗?
  • 所有设备都运行相同的安卓版本吗?我建议使用 SQLiteOpenHelper,您始终可以在您的应用程序中维护版本号。我不认为这是不使用 SQLiteOpenHelper 的好借口。我还从外部源将 db 文件下载到我的应用程序中,但我正在使用 SQLiteOpenHelper 并在我的应用程序中维护版本。
  • 我会试试的,不过根据stackoverflow.com/questions/16373722/…的说法,不需要使用SQLiteOpenHelper来以读写模式打开数据库。我也喜欢使用“enableWriteAheadLogging”日志记录,我不知道 SQLiteOpenHelper 是如何支持的。
  • 另见stackoverflow.com/questions/6193279/…。 SQLiteDatabase.openDatabase 与 SQLiteOpenHelper.getReadableDatabase 在打开数据库方面似乎没有区别。

标签: android sqlite


【解决方案1】:

看起来这不是错误,而是“功能”。

Google's KitKat Blocks Some Access to Micro SD Cards

真的很伤心,但看起来是真的

【讨论】:

  • 在 Galaxy S4 升级到 4.4.2 后,我能够通过将数据库移动到内部存储来解决问题。我同意这很可悲,因为它现在耗尽了内部存储器,而 SD 卡上有很多。希望有另一种解决方法。
【解决方案2】:

首先我会说您确实应该将 SQLite 数据库存储在内部存储中,在那里您可以使用 ext4 日志来帮助进行数据恢复。内部存储也更多更好的安全性,因为您不必担心恶意应用添加触发器等最终在您的进程中运行。

话虽如此,从 KitKat 开始,您可以通过新的公共 API Context.getExternalFilesDirs()Context.getExternalCacheDirs() 写入辅助存储设备。这些方法也可以在 support-v4 库中的 ContextCompat 上找到。

另请注意,如果您只对使用Context 返回的目录感兴趣,则不再需要READ_WRITE_EXTERNAL_STORAGE 权限。今后,您将始终拥有对这些目录的读/写访问权限,而无需其他权限。

应用还可以通过终止其权限请求来继续在旧设备上运行,如下所示:

<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="18" />

【讨论】:

  • 那么,使用这些APIContext.getExternalFilesDirs(),帮助我们将SQLite db 存储在二级存储中?我认为这些是用于存储一些与我们的应用程序相关的文件而不是 sqlite db 的 API。如果我错了,请纠正我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-10
相关资源
最近更新 更多