清除应用程序存储和缓存后,开始出现未知错误(代码 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的子文件夹,清除应用程序的存储会有效地返回到这一点。
但是,手动复制数据库仅适用于特定的应用程序。如果您发布了应用程序,它将不起作用,因为您将无法访问手动复制文件。
要在应用程序中使用预先存在的数据库,那么推荐的方法是:-
- 创建应用程序或应用程序的一部分
- 在 main/src/中创建assets文件夹(与 res/java 文件夹和 android.manaifest 所在的位置相同)。
- 注意:如果使用 SQLiteAssetHelper,请在assets文件夹中创建数据库文件夹。
- 将数据库复制到资产中
- 然后,应用程序应在尝试使用数据库之前,将数据库从资产文件夹复制到访问数据库的位置,使用 AssetManager 访问数据库。
- 通常,此位置为/data/data/the_package_name/databases/your_database
- 确定位置的可靠/推荐方法是使用 context.getDatabasePath(your_database)。
- 请注意,新应用程序的数据库文件夹将不存在,必须创建(SQLiteAssethelper将执行此操作)。
SQliteAssethelper简化了这一点。