我从资产复制的sqlite数据库不包含任何表,但如果我使用硬编码的路径,它不会在其他设备上工作 &g



它通过使用硬编码路径工作。我走错路了吗?这是获取路径

的代码
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//databases/questions.dbquestions.db代替data/data//databases/questions.db: -

您可以使用以下方法修复路径名问题:-

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());
}

相关内容

最新更新