Я считаю, что ваша проблема ( первоначальная проблема, пожалуйста, прочитайте весь ответ ), возможно, использует обработчик.Конечно, тестирование доступного кода приводит к непредвиденным результатам (база данных всегда указывается как существующая, поэтому никогда не копирует БД из активов, если база данных никогда не вызывает 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 .
Поэтому я бы предложил следующий помощник по базам данных (см. Комментарии о внесенных изменениях): -
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
Сначала приложение было запущено с файлами, как указано выше, и версией была установлена 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 {
Этап 2
Приложение было запущено снова без изменений результатов (т. е. без копии БД): -
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
Этап 3
Файлы в папке ресурсов изменены на: -
Повторный запуск приложения БЕЗ изменения версии : -
Нет Копирование и исходные данные: -
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: }
........
- Примечание 76K скопировано и таблица теперь в магазинах
А по 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
...........
Этап 5
Приложение запускается снова (т.е. пост-копия уже сделана): -
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