E / SQLiteLog: (1) нет такой таблицы: машины на Android 9 пирог - PullRequest
0 голосов
/ 10 марта 2020

Почему копирование базы данных не работает для Android 9? Моя реализация основана на этом примере ( видео ). Все отлично работает на Android версиях от 4.1 до 10, но НЕ на 9 P ie.

Вот что я сделал:

fun importToApp(fileNameOnSD: String) {
        val sd = File(sdFolder)
        if (sd.canWrite()) {
            val currentDB = File(Environment.getDataDirectory(), dataTemp)
            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()
    }

    private fun copyData() {
        db.delete(TABLE, null, null)
        val dbBackup = context.openOrCreateDatabase(DB_TEMP, Context.MODE_PRIVATE, null)
        val cursor = dbBackup.query(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(dataTemp)
        utilities.toast(context.resources.getString(R.string.db_suc_imported), 0)
    } 

Я также называю метод ( как здесь предлагается ):

override fun onOpen(db: SQLiteDatabase) {
        super.onOpen(db)
        if (Build.VERSION.SDK_INT == 28)
            db.disableWriteAheadLogging()
    }

Вот кратер sh, вызванный в Android P ie:

E/SQLiteLog: (1) no such table: Cars 
D/AndroidRuntime: Shutting down VM


    --------- beginning of crash
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.easyapps.cryptnote, PID: 3174
    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:144)
        at com.easyapps.cryptnote.ListDatabase.importToApp(CarsDatabase.kt:137)
        at com.easyapps.cryptnote.ImportActivity$importDB$$inlined$apply$lambda$1.onClick(CarsActivity.kt:273)
        at android.view.View.performClick(View.java:6597)
        at android.view.View.performClickInternal(View.java:6574)
        at android.view.View.access$3100(View.java:778)
        at android.view.View$PerformClick.run(View.java:25885)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        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)
I/Process: Sending signal. PID: 3174 SIG: 9

Эта строка val cursor = dbBackup.query(true, TABLE, null, null, null, null, null, null, null) вылетает приложение. До сих пор я тестировал на двух разных реальных Android устройствах, один с Android Lollipop (Moto) и один с Android P ie (Samsung A40). Другие версии были виртуальными. Самое интересное, что он работает на Samsung с Android P ie, но не на виртуальном устройстве с Android P ie. Тем не менее, я предполагаю, что это устройство Samsung является исключением, мне нужно запустить на всех Android устройствах, неважно, реальных или виртуальных.

1 Ответ

0 голосов
/ 11 марта 2020

Итак, я исправил проблему, используя первый ответ . Я добавил внутренний класс

class TempDataBase(private val context: Context, dbName: String, version: Int) : SQLiteOpenHelper(
        context,
        dbName, null,
        version
    ) {
        override fun onCreate(db: SQLiteDatabase) {
            db.execSQL("CREATE TABLE $TABLE ($ID INTEGER PRIMARY KEY AUTOINCREMENT, $TITLE TEXT, $NOTE TEXT, $DATE TEXT);")
        }

        override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
            db.execSQL("DROP TABLE IF EXISTS $TABLE")
            onCreate(db)
        }

        override fun onConfigure(db: SQLiteDatabase) {
            db.disableWriteAheadLogging()
            super.onConfigure(db)
        }
    }

и вызвал его в моем методе copyData():

private fun copyData() {
        db.delete(TABLE, null, null)
        val dbBackup = if (Build.VERSION.SDK_INT == Build.VERSION_CODES.P) {
            SQLiteDatabase.openDatabase(TempDataBase(context, DB_TEMP, 1).readableDatabase.path, null, SQLiteDatabase.OPEN_READWRITE)
        }
        else
            context.openOrCreateDatabase(DB_TEMP, Context.MODE_PRIVATE, null)
        val cursor = dbBackup.query(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()
        db.close()
        context.deleteDatabase(dataTemp)
        utilities.toast(context.resources.getString(R.string.db_suc_imported), 0)
    }

По сути, Android P ищет базу данных и обнаруживает, что она не существует в то время как другие версии на самом деле не требуют, чтобы временная база данных действительно существовала. Мой внутренний класс создает временную базу данных в качестве буфера для копирования данных, используемых Android 9.

Кто еще ищет решение, пожалуйста, оставьте комментарий для получения дополнительной информации, и я отвечу как можно скорее.

...