它通过使用硬编码路径工作。我走错路了吗?这是获取路径
的代码public class DatabaseAssets extends SQLiteOpenHelper {
private static String dbName = "questions.db";
Context context;
File dbFile;
public DatabaseAssets(Context context) {
super(context, "questions.db", null, 1);
this.context = context;
File DB_PATH = context.getDatabasePath(dbName);
String db = DB_PATH.getAbsolutePath();
dbFile= new File(db + "questions.db");
}
这是我的gettwritabledatabase和getReadableDatabase代码。
@Override
public synchronized SQLiteDatabase getWritableDatabase() {
if(!dbFile.exists()){
SQLiteDatabase db = super.getWritableDatabase();
copyDataBase(db.getPath());
}
return super.getWritableDatabase();
}
@Override
public synchronized SQLiteDatabase getReadableDatabase() {
if(!dbFile.exists()){
SQLiteDatabase db = super.getReadableDatabase();
copyDataBase(db.getPath());
}
return super.getReadableDatabase();
}
这是我的复制代码,但我不认为这是问题所在。
private void copyDataBase(String dbPath){
try{
InputStream assestDB = context.getAssets().open("databases/"+"questions.db");
OutputStream appDB = new FileOutputStream(dbPath,false);
byte[] buffer = new byte[1024];
int length;
while ((length = assestDB.read(buffer)) > 0) {
appDB.write(buffer, 0, length);
}
appDB.flush();
appDB.close();
assestDB.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
我相信你的问题是因为你正在使用SQLiteDatabase db = super.getReadableDatabase();
或getWritableDatabase(不管哪个),而且你正在将数据库名称附加到数据库名称(因此路径将是data/data/
您可以使用以下方法修复路径名问题:-
public DatabaseAssets(Context context) {
super(context, "questions.db", null, 1);
this.context = context;
File DB_PATH = context.getDatabasePath(dbName);
String db = DB_PATH.getAbsolutePath();
//dbFile = new File(db + "questions.db");
// path will be data/data/<the_package_name>/database/questions.dbquestions.db
dbFile = new File(db);
}
或:-
public DatabaseAssets(Context context) {
super(context,dbName,null,1);
this.context = context;
dbFile = context.getDatabasePath(dbName);
}
关于第一个提到的问题,获得一个可写或可读的数据库在历史上被用来规避一个问题,即资产的副本将失败(由于数据库目录不存在时,一个应用程序安装)。这样做的目的是创建一个数据库,然后覆盖它来创建数据库目录。
在以后的Android版本中,默认模式现在是WAL (Write-Ahead Logging),以前是Journal。使用WAL时,对数据库的更改被写入WAL文件。复制资产将只复制数据库,而不是WAL文件。数据库打开检测到一个问题(WAL部分与数据库不一致),过于友好的Android API创建一个新的空数据库,而不是失败。
为了避免这个问题,你可以创建丢失的目录(这实际上是更有效的)。所以不是:-
if(!dbFile.exists()){
SQLiteDatabase db = super.getWritableDatabase();
copyDataBase(db.getPath());
}
使用: -
if(!dbFile.exists()){
if (!dbFile.getParentFile().exists) {
dbfile.mkdirs()
}
copyDataBase(dbFile.getPath());
}