清除存储后应用程序崩溃,错误代码为 14 SQLITE_CANTOPEN:无法打开数据库



清除应用程序存储和缓存后,开始出现未知错误(代码 14 SQLITE_CANTOPEN):无法打开数据库。在清除存储之前,模拟器和设备都正常工作。

我尝试从模拟器中删除应用程序,擦除模拟器并清理项目,但在打开 MainActivity 时仍然崩溃。为了解决问题,我将写入权限放在AndroidManifest中,但仍然出现相同的错误。

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

而不是做

this.baza_putanja = "/data/data/" + context.getPackageName() + "/" + "databases/";

我做了

baza_putanja = context.getDatabasePath(baza_ime).getPath();

困扰我的是,如果我尝试使用不包含数据库名称的路径打开数据库 -为什么它在清除应用程序存储和缓存之前工作?

BazaPodatakaHelper.java

private String baza_putanja = null;
private static final String baza_ime = "eng_dictionary.db";
private SQLiteDatabase econDictionary;
private final Context mContext;
public BazaPodatakaHelper(Context context) {
super(context, baza_ime, null, 1);
this.mContext = context;
this.baza_putanja = "/data/data/" + context.getPackageName() + "/" + "databases/";
Log.e("Putanja 1", baza_putanja);
}
public void kreirajBazuPodataka() throws IOException {
boolean bazaPodatakaPostoji = provjeriBazuPodataka();
if ( !bazaPodatakaPostoji ) {
this.getReadableDatabase();
try {
kopirajBazuPodataka();
} catch (IOException e) {
throw new Error("Greška prilikom kopiranja baze podataka");
}
}
}
public boolean provjeriBazuPodataka() {
SQLiteDatabase provjera;
try {
String putanja = baza_putanja + baza_ime;
provjera = SQLiteDatabase.openDatabase(putanja, null, SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e) {
throw new Error("Greška prilikom provjeravanja baze podataka");
}
if (provjera != null) {
provjera.close();
}
return provjera != null;
}

错误日志:

2019-07-17 20:39:30.482 7885-7885/com.benjaminkljn.econdictionary E/Putanja 1: /data/data/com.benjaminkljn.econdictionary/assets/ 2019-07-17 20:39:30.485 7885-7885/com.benjaminkljn.econdictionary E/SQLiteLog: (14) cannot open file at line 36683 of [c255889bd9] 2019-07-17 20:39:30.485 7885-7885/com.benjaminkljn.econdictionary E/SQLiteLog: (14) os_unix.c:36683: (2) open(/data/data/com.benjaminkljn.econdictionary/assets/eng_dictionary.db)
-  2019-07-17 20:39:30.491 7885-7885/com.benjaminkljn.econdictionary E/SQLiteDatabase: Failed to open database '/data/data/com.benjaminkljn.econdictionary/assets/eng_dictionary.db'.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14 SQLITE_CANTOPEN): Could not open database

消息是说

/data/data/com.benjaminkljn.econdictionary/assets/eng_dictionary.db

上面的代码不包含路径中的资产,因此您的问题可能基于此。

通常,特别是,如果使用context.getDatabasePath(your_database),则尝试打开

/data/data/com.benjaminkljn.econdictionary/databases/eng_dictionary.db
  • 数据库文件夹而不是资产

此外,在您的评论中,您提到:-

>I've deleted and re-imported database

通常,导入数据库(至少对于应用程序而言)会将要导入的数据库(包含在应用程序中)复制到assets文件夹。

因此,可能是您尝试从您认为是资产文件夹的地方打开数据库,但不能直接使用包含/导入的资产文件夹,因为资产由AssetsManager管理。

您可能可以使用设备资源管理器在/data/data/com.benjaminkljn.econdictionary 中创建资产文件夹,然后将数据库复制到该文件夹中,然后打开就可以工作了。

如果您之前这样做过,那么在删除/卸载应用程序后,如果数据库尚未手动复制到 assets 文件夹中(因此已创建 assets 文件夹),则会导致您遇到的问题。

安装应用程序时,将创建/data/
  • data/com.benjaminkljn.econdictionary 文件夹,但不会创建子文件夹数据库,而不是名为assets的子文件夹,清除应用程序的存储会有效地返回到这一点。

但是,手动复制数据库仅适用于特定的应用程序。如果您发布了应用程序,它将不起作用,因为您将无法访问手动复制文件。

要在应用程序中使用预先存在的数据库,那么推荐的方法是:-

  1. 创建应用程序或应用程序的一部分
  2. 在 main/src/中创建assets文件夹(与 res/java 文件夹和 android.manaifest 所在的位置相同)。
    1. 注意:如果使用 SQLiteAssetHelper,请在assets文件夹中创建数据库文件夹。
  3. 将数据库复制到资产
  4. 然后,应用程序应在尝试使用数据库之前,将数据库从资产文件夹复制到访问数据库的位置,使用 AssetManager 访问数据库。
    1. 通常,此位置为/data/data/the_package_name/databases/your_database
    2. 确定位置的可靠/推荐方法是使用 context.getDatabasePath(your_database)。
    3. 请注意,新应用程序的数据库文件夹将不存在,必须创建(SQLiteAssethelper将执行此操作)。

SQliteAssethelper简化了这一点。

相关内容

  • 没有找到相关文章

最新更新