我认为您的问题(初始问题,请阅读完整答案)可能正在使用处理程序。当然,测试可用代码会导致意想不到的结果(数据库始终报告为存在,因此永远不要从资产中复制数据库,如果数据库存在则永远不会调用 onUpgrade(我的猜测是数据库已经打开由于隐式打开,因此没有尝试进行打开处理))。
改用:-
try {
CopyAndCreateDataBase();
} catch (IOException e) {
e.printStackTrace();
}
/*
new Handler().post(new Runnable() {
@Override
public void run() {
// If u want to Copy Database from Assets.
try {
CopyAndCreateDataBase();
} catch (IOException e) {
e.printStackTrace();
}
}
});
*/
产生预期的结果,例如:-
07-04 06:55:38.836 4365-4365/aso.so56873021recopydb D/DBEXISTS: The database /data/user/0/aso.so56873021recopydb/databases/DB.db was found.
07-04 06:55:38.836 4365-4365/aso.so56873021recopydb D/DB STATUS:: Database Already Exists!!!!!!!!!
07-04 06:55:38.838 4365-4365/aso.so56873021recopydb D/Database Versions:: old:1
new:2
- 请注意,在测试代码以确定问题时添加了 DBEXISTS 消息。
测试在活动中使用了以下代码:-
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DataBaseHelper mDBHlpr = DataBaseHelper.getInstance(this);
Cursor csr = mDBHlpr.getWritableDatabase().query("sqlite_master",null,null,null,null,null,null);
DatabaseUtils.dumpCursor(csr);
}
}
第 2 部分 - 升级
简而言之,即使您可以调用 onUpgrade 在修复上一个问题后增加版本,因为当调用 onUpgrade 时数据库已经打开并复制新数据库将有效地撤消,因为旧数据库将覆盖新复制的数据库,因此更改会丢失。
相反,我建议在实例化数据库助手之前检查、复制和覆盖数据库,例如在 getInstance 方法中。
因此,我建议使用以下数据库助手(请参阅 cmets 了解所做的更改):-
public class DataBaseHelper extends SQLiteOpenHelper {
private static Context mContext;
//private static String DB_PATH = "/data/data/<app Package>/databases/"; //NOT NEEDED Contexts getDatabasePath used instead
private static final String DBNAME = "DB.db";
private static DataBaseHelper sInstance;
private static final int version = 2;
public static synchronized DataBaseHelper getInstance(Context context) {
// Use the application context, which will ensure that you
// don't accidentally leak an Activity's context.
checkDB(context.getApplicationContext(),DBNAME,version); //<<<<<<<<<< do the stuff before DatabaseHelper instantiation
if (sInstance == null) {
sInstance = new DataBaseHelper(context.getApplicationContext());
}
return sInstance;
}
private DataBaseHelper(Context context) {
super(context, DBNAME, null, version);
mContext = context;
}
// Copy the database from assets
//<<<<<<<<<< CHANGED TO USE getDatabasepath requiring Context to be passed
private static void copyDataBase(Context context) throws IOException {
InputStream mInput = context.getAssets().open(DBNAME);
String outFileName = context.getDatabasePath(DBNAME).toString();
OutputStream mOutput = new FileOutputStream(outFileName);
Log.d("DBCOPY","DB Copy inititaed"); //<<<<<<<<<< ADDED FOR TESTING
byte[] mBuffer = new byte[1024];
int mLength;
int bytescopied = 0;
while ((mLength = mInput.read(mBuffer)) > 0) {
mOutput.write(mBuffer, 0, mLength);
bytescopied = bytescopied + mLength;
}
Log.d("DBCOPY", "Database copied. " + String.valueOf(bytescopied) + " bytes copied." ); //<<<<<<<<<< ADDED FOR TESTING
Log.d("DB STATUS:", "Daatabase Created ----------------"); //FOR DB TESTING PURPOSES
mOutput.flush();
mOutput.close();
mInput.close();
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
//<<<<<<<<<< ONLY USE ME FOR SCHEMA CHANGES !!!!NOT!!!! new DB copy
Log.d("Database Versions:", "old:"+i+"\nnew:"+i1);
}
//<<<<<<<<<< NEW
private static void checkDB(Context context, String dbname, int version) {
int dbversion;
// Note uses the Contexts getDatabasePath
File dbfile = new File(context.getDatabasePath(dbname).toString());
if (!dbfile.exists()) {
//<<<<<<<<<< create the databases directory (or whatever it is the future)
if (!dbfile.getParentFile().exists()) {
dbfile.getParentFile().mkdirs();
}
//<<<<<<<<<< Now do the copy of the initial DB
//<<<<<<<<<< Note new install will copy the latest DB
try {
copyDataBase(context);
} catch (IOException e) {
e.printStackTrace();
throw new Error("Error copying initial Database.");
}
}
// If the database file does exist then retrieve the version
else {
SQLiteDatabase db = SQLiteDatabase.openDatabase(context.getDatabasePath(dbname).toString(),null,SQLiteDatabase.OPEN_READWRITE);
dbversion = db.getVersion();
Log.d("DBVERSION","The stored database version is " + String.valueOf(dbversion));
db.close();
//<<<<<<<<<< if the database's version is less than the coded version then copy the DB
//<<<<<<<<<< NOTE!!!! always assumes new version = new copy
//<<<<<<<<<< IF NOt WANTED THEN DO SPECIFIC VERSION CHECKING
if (dbversion < version) {
//<<<<<<<<<<<< EXAMPLE skip copy on version 10 >>>>>>>>>>
//<TODO> Remove example check if not needed
if (dbversion < version && version == 10) {
return;
}
//<<<<<<<<<< For Android 9+ delete the -wal and -shm files if copying database
if (new File(context.getDatabasePath(dbname).toString() + "-wal").exists()) {
new File(context.getDatabasePath(dbname).toString() + "-wal").delete();
}
if (new File(context.getDatabasePath(dbname).toString() + "-shm").exists()) {
new File(context.getDatabasePath(dbname).toString() + "-shm").delete();
}
try {
copyDataBase(context);
} catch (IOException e) {
e.printStackTrace();
throw new Error("Error copying upgraded database");
}
}
}
}
}
测试
以上内容已经过测试。测试基于两个数据库(完全不同),在活动中使用以下内容:-
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DataBaseHelper mDBHlpr = DataBaseHelper.getInstance(this);
Cursor csr = mDBHlpr.getWritableDatabase().query("sqlite_master",null,null,null,null,null,null);
DatabaseUtils.dumpCursor(csr);
}
}
以下是资产文件夹:-
- 被 OLDDB.db 复制到 DB.db 的原始数据库。 NEWDB.db 将是后续的新数据库。
在两个设备 API 23 和 API 28(Oreo so Pie+ 和 WAL)上进行了测试。
第一阶段
首先使用上述文件运行应用程序,并将版本设置为 1。导致日志包含:-
07-04 10:20:32.120 8154-8154/aso.so56873021recopydb D/DBCOPY: DB Copy inititaed
07-04 10:20:32.120 8154-8154/aso.so56873021recopydb D/DBCOPY: Database copied. 36864 bytes copied.
07-04 10:20:32.120 8154-8154/aso.so56873021recopydb D/DB STATUS:: Daatabase Created ----------------
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@6e2c433
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: 0 {
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: type=table
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: name=android_metadata
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: tbl_name=android_metadata
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: rootpage=3
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: sql=CREATE TABLE android_metadata (locale TEXT)
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: }
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: 1 {
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: type=table
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: name=room_master_table
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: tbl_name=room_master_table
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: rootpage=4
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: sql=CREATE TABLE room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: }
..........
- 36K 复制
- 笔记表room_master_table
API 28 设备上的类似结果:-
2019-07-04 10:22:33.082 4532-4532/aso.so56873021recopydb D/DBCOPY: DB Copy inititaed
2019-07-04 10:22:33.083 4532-4532/aso.so56873021recopydb D/DBCOPY: Database copied. 36864 bytes copied.
2019-07-04 10:22:33.083 4532-4532/aso.so56873021recopydb D/DB STATUS:: Daatabase Created ----------------
2019-07-04 10:22:33.088 4532-4532/aso.so56873021recopydb I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@2f7f7bc
2019-07-04 10:22:33.089 4532-4532/aso.so56873021recopydb I/System.out: 0 {
第二阶段
应用程序再次运行,没有更改结果(即没有数据库副本):-
07-04 10:24:13.642 8244-8244/? D/DBVERSION: The stored database version is 1
07-04 10:24:13.644 8244-8244/? I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@8c743f0
在 API 28 设备上:-
2019-07-04 10:26:24.531 4620-4620/? D/DBVERSION: The stored database version is 1
2019-07-04 10:26:24.536 4620-4620/? I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@877f345
第三阶段
资产文件夹中的文件更改为:-
应用重新运行无需更改版本:-
没有复制和原始数据:-
07-04 10:30:01.838 8369-8369/? D/DBVERSION: The stored database version is 1
07-04 10:30:01.840 8369-8369/? I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@8c743f0
07-04 10:30:01.840 8369-8369/? I/System.out: 0 {
07-04 10:30:01.840 8369-8369/? I/System.out: type=table
07-04 10:30:01.840 8369-8369/? I/System.out: name=android_metadata
07-04 10:30:01.840 8369-8369/? I/System.out: tbl_name=android_metadata
07-04 10:30:01.840 8369-8369/? I/System.out: rootpage=3
07-04 10:30:01.840 8369-8369/? I/System.out: sql=CREATE TABLE android_metadata (locale TEXT)
07-04 10:30:01.840 8369-8369/? I/System.out: }
07-04 10:30:01.840 8369-8369/? I/System.out: 1 {
07-04 10:30:01.840 8369-8369/? I/System.out: type=table
07-04 10:30:01.840 8369-8369/? I/System.out: name=room_master_table
在 API 28 上:-
2019-07-04 10:31:11.591 4757-4757/aso.so56873021recopydb D/DBVERSION: The stored database version is 1
2019-07-04 10:31:11.596 4757-4757/aso.so56873021recopydb I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@877f345
2019-07-04 10:31:11.596 4757-4757/aso.so56873021recopydb I/System.out: 0 {
2019-07-04 10:31:11.596 4757-4757/aso.so56873021recopydb I/System.out: type=table
2019-07-04 10:31:11.596 4757-4757/aso.so56873021recopydb I/System.out: name=android_metadata
2019-07-04 10:31:11.596 4757-4757/aso.so56873021recopydb I/System.out: tbl_name=android_metadata
2019-07-04 10:31:11.597 4757-4757/aso.so56873021recopydb I/System.out: rootpage=3
2019-07-04 10:31:11.597 4757-4757/aso.so56873021recopydb I/System.out: sql=CREATE TABLE android_metadata (locale TEXT)
2019-07-04 10:31:11.597 4757-4757/aso.so56873021recopydb I/System.out: }
2019-07-04 10:31:11.597 4757-4757/aso.so56873021recopydb I/System.out: 1 {
2019-07-04 10:31:11.597 4757-4757/aso.so56873021recopydb I/System.out: type=table
2019-07-04 10:31:11.597 4757-4757/aso.so56873021recopydb I/System.out: name=room_master_table
第 4 阶段
version increased from 1 to 2 :-
07-04 10:38:42.679 8857-8857/? D/DBVERSION: The stored database version is 1
07-04 10:38:42.679 8857-8857/? D/DBCOPY: DB Copy inititaed
07-04 10:38:42.680 8857-8857/? D/DBCOPY: Database copied. 77824 bytes copied.
07-04 10:38:42.680 8857-8857/? D/DB STATUS:: Daatabase Created ----------------
07-04 10:38:42.683 8857-8857/? D/Database Versions:: old:1
new:2
07-04 10:38:42.688 8857-8857/? I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@f2b3d69
07-04 10:38:42.688 8857-8857/? I/System.out: 0 {
07-04 10:38:42.688 8857-8857/? I/System.out: type=table
07-04 10:38:42.688 8857-8857/? I/System.out: name=android_metadata
07-04 10:38:42.688 8857-8857/? I/System.out: tbl_name=android_metadata
07-04 10:38:42.688 8857-8857/? I/System.out: rootpage=3
07-04 10:38:42.689 8857-8857/? I/System.out: sql=CREATE TABLE android_metadata (locale TEXT)
07-04 10:38:42.689 8857-8857/? I/System.out: }
07-04 10:38:42.689 8857-8857/? I/System.out: 1 {
07-04 10:38:42.689 8857-8857/? I/System.out: type=table
07-04 10:38:42.689 8857-8857/? I/System.out: name=shops
07-04 10:38:42.689 8857-8857/? I/System.out: tbl_name=shops
07-04 10:38:42.689 8857-8857/? I/System.out: rootpage=4
07-04 10:38:42.689 8857-8857/? I/System.out: sql=CREATE TABLE shops (_id INTEGER PRIMARY KEY , shoporder INTEGER DEFAULT 1000 , shopname TEXT , shopstreet TEXT , shopcity TEXT , shopstate TEXT , shopnotes TEXT )
07-04 10:38:42.689 8857-8857/? I/System.out: }
........
在 API 28 上:-
2019-07-04 10:40:31.799 5010-5010/aso.so56873021recopydb D/DBVERSION: The stored database version is 1
2019-07-04 10:40:31.800 5010-5010/aso.so56873021recopydb D/DBCOPY: DB Copy inititaed
2019-07-04 10:40:31.802 5010-5010/aso.so56873021recopydb D/DBCOPY: Database copied. 77824 bytes copied.
2019-07-04 10:40:31.802 5010-5010/aso.so56873021recopydb D/DB STATUS:: Daatabase Created ----------------
2019-07-04 10:40:31.826 5010-5010/aso.so56873021recopydb D/Database Versions:: old:1
new:2
...........
第五阶段
应用程序再次运行(即已完成后复制):-
07-04 10:41:53.653 8947-8947/? D/DBVERSION: The stored database version is 2
07-04 10:41:53.655 8947-8947/? I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@8c743f0
07-04 10:41:53.655 8947-8947/? I/System.out: 0 {
07-04 10:41:53.655 8947-8947/? I/System.out: type=table
07-04 10:41:53.655 8947-8947/? I/System.out: name=android_metadata
07-04 10:41:53.655 8947-8947/? I/System.out: tbl_name=android_metadata
07-04 10:41:53.655 8947-8947/? I/System.out: rootpage=3
07-04 10:41:53.655 8947-8947/? I/System.out: sql=CREATE TABLE android_metadata (locale TEXT)
07-04 10:41:53.655 8947-8947/? I/System.out: }
07-04 10:41:53.655 8947-8947/? I/System.out: 1 {
07-04 10:41:53.655 8947-8947/? I/System.out: type=table
07-04 10:41:53.655 8947-8947/? I/System.out: name=shops
07-04 10:41:53.655 8947-8947/? I/System.out: tbl_name=shops
在 API 28 上:-
2019-07-04 10:42:41.296 5098-5098/aso.so56873021recopydb D/DBVERSION: The stored database version is 2
2019-07-04 10:42:41.306 5098-5098/aso.so56873021recopydb I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@877f345
2019-07-04 10:42:41.307 5098-5098/aso.so56873021recopydb I/System.out: 0 {
2019-07-04 10:42:41.308 5098-5098/aso.so56873021recopydb I/System.out: type=table
2019-07-04 10:42:41.308 5098-5098/aso.so56873021recopydb I/System.out: name=android_metadata
2019-07-04 10:42:41.308 5098-5098/aso.so56873021recopydb I/System.out: tbl_name=android_metadata
2019-07-04 10:42:41.308 5098-5098/aso.so56873021recopydb I/System.out: rootpage=3
2019-07-04 10:42:41.308 5098-5098/aso.so56873021recopydb I/System.out: sql=CREATE TABLE android_metadata (locale TEXT)
2019-07-04 10:42:41.308 5098-5098/aso.so56873021recopydb I/System.out: }
2019-07-04 10:42:41.308 5098-5098/aso.so56873021recopydb I/System.out: 1 {
2019-07-04 10:42:41.308 5098-5098/aso.so56873021recopydb I/System.out: type=table
2019-07-04 10:42:41.308 5098-5098/aso.so56873021recopydb I/System.out: name=shops
2019-07-04 10:42:41.309 5098-5098/aso.so56873021recopydb I/System.out: tbl_name=shops