作者:你的拥吻像情歌一样凄美_207 | 来源:互联网 | 2022-12-16 14:32
我有一个数据库保存在我的应用程序资产文件夹中,并在应用程序首次打开时使用以下代码复制数据库.
inputStream = mContext.getAssets().open(Utils.getDatabaseName());
if(inputStream != null) {
int mFileLength = inputStream.available();
String filePath = mContext.getDatabasePath(Utils.getDatabaseName()).getAbsolutePath();
// Save the downloaded file
output = new FileOutputStream(filePath);
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = inputStream.read(data)) != -1) {
total += count;
if(mFileLength != -1) {
// Publish the progress
publishProgress((int) (total * 100 / mFileLength));
}
output.write(data, 0, count);
}
return true;
}
上面的代码运行没有问题,但是当你尝试查询数据库时,你会得到一个SQLite:没有这样的表异常.
此问题仅发生在Android P中,所有早期版本的Android都能正常工作.
这是Android P的已知问题还是有些变化?
1> Ramon Canale..:
有一个类似的问题,并解决了这个添加到我的SQLiteOpenHelper
@Override
public void onOpen(SQLiteDatabase db) {
super.onOpen(db);
db.disableWriteAheadLogging();
}
显然Android P将PRAGMA Log设置为不同.仍然不知道是否会产生副作用,但似乎有效!
很好的答案,但对于挑剔,"onConfigure"是一个更好的地方.`onConfigure`的javadoc特别提到它是`enableWriteAheadLogging`这样的地方.在我的测试中,两个地方都在努力解决Android 9上的问题.
2> 小智..:
通过在createDataBase()方法中的this.getReadableDatabase()之后添加'this.close()',我解决了Android P的问题,如下所示.
private void createDataBase() throws IOException {
this.getReadableDatabase();
this.close();
try {
copyDataBase();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
我遇到了确切的问题,解决方案也起作用,但是我对该问题感到好奇,为什么以及如何解决Android P中的问题?
3> rmtheis..:
这个问题似乎导致Android P上的崩溃比以前的版本更频繁,但它不是Android P本身的错误.
问题是,您为其分配值的行将String filePath
打开与从资产复制文件时保持打开的数据库的连接.
要解决此问题,请替换该行
String filePath = mContext.getDatabasePath(Utils.getDatabaseName()).getAbsolutePath();
使用代码获取文件路径值,然后关闭数据库:
MySQLiteOpenHelper helper = new MySQLiteOpenHelper();
SQLiteDatabase database = helper.getReadableDatabase();
String filePath = database.getPath();
database.close();
并且还添加了一个内部帮助器类:
class MySQLiteOpenHelper extends SQLiteOpenHelper {
MySQLiteOpenHelper(Context context, String databaseName) {
super(context, databaseName, null, 2);
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
道歉,你是对的.我忽略了我之前调用过这个(相当无意义的)代码:`openOrCreateDatabase(Utils.getDatabaseName(),MODE_PRIVATE,null);`这保持了与数据库的开放连接并导致了问题.我已经删除了该代码,一切正常.谢谢您的帮助!
4> KGBird..:
我遇到了类似的问题.我正在复制数据库,但不是来自资产.我发现问题与我的数据库文件完全没有关系.它也与处于打开,未关闭,刷新或同步的文件有关.我的代码通常会覆盖现有的未打开的数据库.Android Pie与Android的先前版本不同之处在于,当Android Pie创建SQLite数据库时,它默认将journal_mode设置为WAL(预写日志记录).我从未使用过WAL模式,SQLite文档说默认情况下journal_mode应该是DELETE.问题是如果我覆盖现有的数据库文件,我们称之为my.db,预写日志my.db-wal仍然存在,并且有效地"覆盖"新复制的my.db文件中的内容.当我打开我的数据库时,sqlite_master表通常只包含一行android_metadata.我所期待的所有表都丢失了.我的解决方案是在打开数据库后简单地将journal_mode设置回DELETE,尤其是在使用Android Pie创建新数据库时.
PRAGMA journal_mode = DELETE;
也许WAL更好,并且可能有一些方法可以关闭数据库,以便预写日志不会妨碍但是我并不真正需要WAL并且不需要它用于所有以前版本的Android.