Я играю с SQLite в своем приложении и пытаюсь импортировать резервную копию базы данных в приложение. Все отлично работает для Oreo и ниже SDK версий (до SDK 16), но не для Android P и выше. Моя база данных:
private val dbTemp = DB_NAME + "_tmp"
private val dbBackup = context.openOrCreateDatabase(dbTemp, Context.MODE_PRIVATE, null)
override fun onCreate(db: SQLiteDatabase) {
db.execSQL("CREATE TABLE $TABLE ($ID INTEGER PRIMARY KEY AUTOINCREMENT, $TITLE TEXT, $CAR TEXT, $DATE TEXT);")
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("DROP TABLE IF EXISTS $TABLE")
onCreate(db)
}
Я копирую резервную копию базы данных, заменяя текущую базу следующим образом:
private fun copyData() {
db.delete(TABLE, null, null)
val cursor = dbBackup.query( // <- here occurs the problem!
true,
TABLE,
null,
null,
null,
null,
null,
null,
null
)
cursor.moveToFirst()
while (!cursor.isAfterLast) {
db.insert(TABLE, null, modelToValues(cursorToModel(cursor)))
cursor.moveToNext()
}
cursor.close()
context.deleteDatabase(dataTmp)
}
Это брошенная проблема:
Process: com.example.cars, PID: 18674
android.database.sqlite.SQLiteException: no such table: Cars (code 1 SQLITE_ERROR): , while compiling: SELECT DISTINCT * FROM Cars
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:903)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:514)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:46)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1408)
at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1255)
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1126)
at com.easyapps.cryptnote.ListDatabase.copyData(CarsDatabase.kt:163)
at com.easyapps.cryptnote.ListDatabase.importToApp(CarsDatabase.kt:155)
at com.example.cars.BackupActivity$onCreate$3$$special$$inlined$apply$lambda$2.onClick(BackupActivity.kt:104)
at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:172)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Я пытался объединить решения из этих ссылок ссылка и ссылка , но безуспешно. Для получения дополнительной информации мое решение для резервного копирования и импорта баз данных основано на демонстрационном проекте , который слишком стар, но, тем не менее, я мог бы использовать его для своего проекта в Kotlin.
Метод резервного копирования:
fun exportToSD() {
createFolderOnSD()
val data = Environment.getDataDirectory()
val backupDbPath = File(sdFolder, "/(${utilities.getDate("dd_MM_yyyy_HH_mm")}) " + DB_NAME)
try {
val source = FileInputStream(File(data, currentDbPath)).channel
val destination = FileOutputStream(backupDbPath).channel
destination.transferFrom(source, 0, source.size())
source.close()
destination.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
Метод импорта в приложение:
fun importToApp(fileNameOnSD: String) {
val sd = File(sdFolder)
if (sd.canWrite()) {
val currentDB = File(Environment.getDataDirectory(), dataTmp)
val backupDB = File(sd, fileNameOnSD)
if (currentDB.exists()) {
try {
val src = FileInputStream(backupDB).channel
val dst = FileOutputStream(currentDB).channel
dst.transferFrom(src, 0, src.size())
src.close()
dst.close()
} catch (e: FileNotFoundException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
}
}
copyData()
}