假设你已经将数据库复制到资源文件夹中并且该数据库包含表格,那么我认为你的问题在于你实例化了DBHelper的一个实例,然后通过隐式或显式调用getWritableDatabase或getReadableDatabase打开了数据库,然后使用onCreate方法启动复制。
如果是这样,那么get????ableDatabase会创建一个空数据库,复制会覆盖它,但在以后的版本Android 9+中,-shm和-wal文件保持原样,当打开数据库时,由于-shm和-wal文件与原始空数据库不匹配,检测到数据损坏,因此创建了一个新的空数据库,因为SDK代码试图提供可用的数据库。
有三种解决方法。
从Android 9+开始,默认情况下使用
WAL(写前日志记录),这是创建和使用-shm和-wal文件的方法。
通过覆盖SQLiteOpenHelper类的onConfigure方法使用disableWriteAheadLogging方法。这将使用旧的日志模式。
确保不调用getWritableDatabase/getReadableDatabase。这可以通过确保在实例化DBHelper实例时完成复制来实现。
确保删除-wal和-shm文件(如果它们在复制时存在)。
仅使用第一种方法可能只是推迟了必然发生的事情,不建议使用,因为它没有利用WAL模式的好处。
以下版本的DBHelper包含了第二个修复措施,并作为预防措施采取了第三个修复措施:
public class DBHelper extends SQLiteOpenHelper {
public static final String DB_NAME = "myDBName";
public static String DB_PATH;
Context context;
public DBHelper(Context context) {
super(context, DB_NAME, null, 2);
this.context = context;
DB_PATH = context.getDatabasePath(DB_NAME).getAbsolutePath();
if (!checkDataBase()) {
copyDataBase();
}
this.getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
private void createDataBase() {
boolean dbExist = checkDataBase();
if (!dbExist) {
copyDataBase();
}
}
private boolean checkDataBase() {
System.out.println("DB_PATH : " + DB_PATH);
File dbFile = new File(DB_PATH);
if (dbFile.exists()) return true;
if (!new File(dbFile.getParent()).exists()) {
new File(dbFile.getParent()).mkdirs();
}
return false;
}
private void copyDataBase() {
Log.i("Database",
"New database is being copied to device!");
byte[] buffer = new byte[1024];
File dbDirectory = new File(new File(DB_PATH).getParent());
File dbwal = new File(dbDirectory.getPath() + File.separator + DB_NAME + "-wal");
if (dbwal.exists()) {
dbwal.delete();
}
File dbshm = new File(dbDirectory.getPath() + File.separator + DB_NAME + "-shm");
if (dbshm.exists()) {
dbshm.delete();
}
OutputStream myOutput;
int length;
InputStream myInput;
try {
myInput = context.getAssets().open(DB_NAME);
myOutput = new FileOutputStream(DB_PATH);
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myOutput.close();
myOutput.flush();
myInput.close();
Log.i("Database",
"New database has been copied to device!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
这已在Android 5和Android 10上进行了测试,使用以下来自活动的代码(以及其他用于转储模式的代码(请注意,显然不是您的数据库,而是可用的数据库)):-
DBHelper mDBHlpr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDBHlpr = new DBHelper(this);
根据日志的结果:
2019-05-07 06:20:53.148 I/System.out: DB_PATH : /data/user/0/soa.usingyourownsqlitedatabaseblog/databases/myDBName
2019-05-07 06:20:53.148 I/Database: New database is being copied to device!
2019-05-07 06:20:53.149 I/Database: New database has been copied to device!
2019-05-07 06:20:53.168 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@e3fe34f
2019-05-07 06:20:53.169 I/System.out: 0 {
2019-05-07 06:20:53.169 I/System.out: type=table
2019-05-07 06:20:53.169 I/System.out: name=Categories
2019-05-07 06:20:53.169 I/System.out: tbl_name=Categories
2019-05-07 06:20:53.169 I/System.out: rootpage=2
2019-05-07 06:20:53.169 I/System.out: sql=CREATE TABLE "Categories" (
2019-05-07 06:20:53.169 I/System.out: "not_id" integer NOT NULL,
2019-05-07 06:20:53.169 I/System.out: "CategoryLabel" TEXT,
2019-05-07 06:20:53.169 I/System.out: "Colour" integer,
2019-05-07 06:20:53.169 I/System.out: PRIMARY KEY ("not_id")
2019-05-07 06:20:53.169 I/System.out: )
2019-05-07 06:20:53.170 I/System.out: }
2019-05-07 06:20:53.170 I/System.out: 1 {
2019-05-07 06:20:53.170 I/System.out: type=table
2019-05-07 06:20:53.170 I/System.out: name=Content
2019-05-07 06:20:53.170 I/System.out: tbl_name=Content
2019-05-07 06:20:53.170 I/System.out: rootpage=3
2019-05-07 06:20:53.170 I/System.out: sql=CREATE TABLE "Content" (
2019-05-07 06:20:53.170 I/System.out: "again_not_id" INTEGER NOT NULL,
2019-05-07 06:20:53.170 I/System.out: "Text" TEXT,
2019-05-07 06:20:53.170 I/System.out: "Source" VARCHAR,
2019-05-07 06:20:53.170 I/System.out: "Category" integer,
2019-05-07 06:20:53.170 I/System.out: "VerseOrder" integer,
2019-05-07 06:20:53.170 I/System.out: PRIMARY KEY ("again_not_id")
2019-05-07 06:20:53.170 I/System.out: )
2019-05-07 06:20:53.170 I/System.out: }
2019-05-07 06:20:53.171 I/System.out: 2 {
2019-05-07 06:20:53.171 I/System.out: type=table
2019-05-07 06:20:53.171 I/System.out: name=android_metadata
2019-05-07 06:20:53.171 I/System.out: tbl_name=android_metadata
2019-05-07 06:20:53.171 I/System.out: rootpage=4
2019-05-07 06:20:53.171 I/System.out: sql=CREATE TABLE android_metadata (locale TEXT)
2019-05-07 06:20:53.171 I/System.out: }
2019-05-07 06:20:53.171 I/System.out: <<<<<
File dbwal = new File(dbDirectory.getPath() + File.separator + DB_NAME + "-wal"); if (dbwal.exists()) { dbwal.delete(); } File dbshm = new File(dbDirectory.getPath() + File.separator + DB_NAME + "-shm"); if (dbshm.exists()) { dbshm.delete(); }
- u2tall