package com.navinfo.omqs.db; import android.content.Context; import android.os.AsyncTask; import android.util.Log; import androidx.annotation.NonNull; import androidx.room.Database; import androidx.room.Room; import androidx.room.RoomDatabase; import androidx.sqlite.db.SupportSQLiteDatabase; import com.navinfo.collect.library.data.dao.impl.INiLocationDao; import com.navinfo.collect.library.data.entity.NiLocation; import com.tencent.wcdb.database.SQLiteCipherSpec; import com.tencent.wcdb.database.SQLiteDatabase; import com.tencent.wcdb.repair.BackupKit; import com.tencent.wcdb.repair.RecoverKit; import com.tencent.wcdb.room.db.WCDBDatabase; import com.tencent.wcdb.room.db.WCDBOpenHelperFactory; @Database(entities = { NiLocation.class},version = 1, exportSchema = false) public abstract class TraceDataBase extends RoomDatabase { // marking the instance as volatile to ensure atomic access to the variable /** * 数据库单例对象 */ private static volatile TraceDataBase INSTANCE; /** * 地图坐标库类 */ public abstract INiLocationDao getNiLocationDao(); /** * 数据库秘钥 */ private final static String DB_PASSWORD = "123456"; public static TraceDataBase getDatabase(final Context context, final String name) { if (INSTANCE == null) { synchronized (TraceDataBase.class) { if (INSTANCE == null) { // [WCDB] To use Room library with WCDB, pass a WCDBOpenHelper factory object // to the database builder with .openHelperFactory(...). In the factory object, // you can specify passphrase and cipher options to open or create encrypted // database, as well as optimization options like asynchronous checkpoint. SQLiteCipherSpec cipherSpec = new SQLiteCipherSpec() .setPageSize(1024) .setSQLCipherVersion(3); WCDBOpenHelperFactory factory = new WCDBOpenHelperFactory() .passphrase(DB_PASSWORD.getBytes()) // passphrase to the database, remove this line for plain-text .cipherSpec(cipherSpec) // cipher to use, remove for default settings .writeAheadLoggingEnabled(true) // enable WAL mode, remove if not needed .asyncCheckpointEnabled(true); // enable asynchronous checkpoint, remove if not needed INSTANCE = Room.databaseBuilder(context.getApplicationContext(), TraceDataBase.class, name) // [WCDB] Specify open helper to use WCDB database implementation instead // of the Android framework. .openHelperFactory(factory) // Wipes and rebuilds instead of migrating if no Migration object. // Migration is not part of this codelab. .fallbackToDestructiveMigration() .addCallback(sRoomDatabaseCallback) .build(); } } } return INSTANCE; } /** * Override the onOpen method to populate the database. * For this sample, we clear the database every time it is created or opened. *

* If you want to populate the database only when the database is created for the 1st time, * override RoomDatabase.Callback()#onCreate */ private static Callback sRoomDatabaseCallback = new Callback() { @Override public void onOpen(@NonNull SupportSQLiteDatabase db) { super.onOpen(db); // If you want to keep the data through app restarts, // comment out the following line. new PopulateDbAsync(INSTANCE).execute(); } }; /** * Populate the database in the background. * If you want to start with more words, just add them. */ private static class PopulateDbAsync extends AsyncTask { PopulateDbAsync(TraceDataBase db) { } @Override protected Void doInBackground(final Void... params) { // Start the app with a clean database every time. // Not needed if you only populate on creation. //mDao.deleteAll(); Log.e("qj", "doInBackground"); return null; } } /** * 数据恢复 */ protected boolean recoverData(){ if(INSTANCE!=null){ SQLiteDatabase sqlite = ((WCDBDatabase) INSTANCE.getOpenHelper().getWritableDatabase()).getInnerDatabase(); RecoverKit recover = new RecoverKit( sqlite, // 要恢复到的目标 DB sqlite.getPath() + "-backup", // 备份文件 DB_PASSWORD.getBytes() // 加密备份文件的密钥,非 DB 密钥 ); int result = recover.run(false); // fatal 参数传 false 表示遇到错误忽略并继续, // 若传 true 遇到错误则中止并返回 FAILED switch (result) { case RecoverKit.RESULT_OK: /* 成功 */ Log.e("qj","sRoomDatabaseCallback==RecoverKit成功"); return true; case RecoverKit.RESULT_CANCELED: /* 取消操作 */ Log.e("qj","sRoomDatabaseCallback==RecoverKit取消操作"); break; case RecoverKit.RESULT_FAILED: /* 失败 */ Log.e("qj","sRoomDatabaseCallback==RecoverKit失败"); break; } recover.release(); } return false; } /** * 备份数据 */ protected boolean backup() { Log.e("qj", "sRoomDatabaseCallback===backup==start"); if (INSTANCE != null) { //备份文件 SQLiteDatabase sqlite = ((WCDBDatabase) INSTANCE.getOpenHelper().getWritableDatabase()).getInnerDatabase(); BackupKit backup = new BackupKit( sqlite, // 要备份的 DB sqlite.getPath() + "-backup", // 备份文件 "123456".getBytes(), // 加密备份文件的密钥,非 DB 密钥 0, null); int result = backup.run(); switch (result) { case BackupKit.RESULT_OK: /* 成功 */ Log.e("qj", "sRoomDatabaseCallback==成功"); return true; case BackupKit.RESULT_CANCELED: /* 取消操作 */ Log.e("qj", "sRoomDatabaseCallback==取消操作"); break; case BackupKit.RESULT_FAILED: /* 失败 */ Log.e("qj", "sRoomDatabaseCallback==失败"); break; } backup.release(); } Log.e("qj", "sRoomDatabaseCallback===backup==end"); return false; } protected void release() { INSTANCE = null; } }