SQLite
 sql >> база данни >  >> RDS >> SQLite

Как да прочетете номера на версията от файл с база данни в Android, който е поставен в папка с активи

Няма един номер на версията, вместо това номерът на версията може да бъде няколко стойности.

Предполагам, че говорите за user_version който използва SQLiteOpenHelper SDK за Android.

Има и application_id , който подобно на user_version може да се използва като потребителска променлива.

Вече сте се сблъсквали с SQLite_Version, така че това може да бъде намалено.

Има и data_version, малко вероятно това е номерът на версията, тъй като е предназначен да се използва като индикация дали файлът на базата данни е променен в реално време.

Има и schema_version, вероятно НЕ искате да го използвате като Предупреждение:Злоупотребата с тази прагма може да доведе до повреда на базата данни.

потребителска_версия

Както вече казахме, вероятно говорите за user_version . Първото нещо, което трябва да се отбележи, е, че това е променлива/поле, контролирана от потребителя, достъпно за потребителска употреба. SQlite не използва и не променя user_version но позволява да се променя и използва.

Освен това SQLite мениджърите (като DB Browser, Navicat и т.н.) няма да променят автоматично номера на версията. По този начин ще трябва умишлено да промените user_version, за да бъде наличен, преди да копирате файла на базата данни в папката с активи (отбелязвайки, че ако го направите и използвате подклас на SQLiteOpenHelper че onUpgrade и onDowngrade методи могат да бъдат извикани).

Ако user_version не е специално променена и базата данни е била достъпна само от инструмента SQLite Manager, тогава нейната user_version ще бъде 0. Ако файлът на базата данни е отворен чрез копиране на файла на базата данни от приложение за Android, което използва подклас на SQLiteOpenHelper, той ще има user_version от 1 или повече (в зависимост от последната стойност, използвана като 4-ти параметър към конструктора на SQLiteOpenHelper). Разбира се, ако user_version се промени програмно, тогава такава промяна също ще бъде отразена, ако файлът бъде копиран в инструмент SQlite Manager.

Преди да копирате файла, user_version обикновено се променя в инструмента SQlite Manager на подходяща стойност.

Можете да промените user_version използвайки SQL PRAGMA user_version = 5; Можете да извлечете user_version използвайки или PRAGMA user_version или SELECT * FROM pragma_user_version;

Ако трябва да проверите версията, преди да отворите базата данни, тогава можете да прочетете 4-те байта при отместване 60 и да конвертирате 4-те байта в цяло число, за да проверите user_version спрямо друга стойност. В противен случай вероятно ще трябва да копирате файла, вероятно използвайки различно име, от папката с активи, да го отворите като SQLiteDatabase и да извлечете user_version с помощта на SQL по-горе и след това да го проверите спрямо другата стойност, затваряйки файла на базата данни. Изтриването на файла, ако не е необходимо, в противен случай изтриване на предишния файл на базата данни и след това преименуване на копирания файл.

Пример

Следва работещ пример (отбелязвайки, че рядко използвам Kotlin и това е преобразувано с помощта на AS studio от java).

Това използва клас, а именно SQLAssetVersionCheck който извлича номера на версията от файла, вместо да отваря файла като SQLiteDatabase.

SQLAssetVersionCheck.kt :-

class SQLAssetVersionCheck
/**
 * Full SQLAssetVersionCheck Constructor - sub directories can be specified
 * @param context           Assets are part of package so use the context to get the asset file
 * @param dbName            The database name (i.e. the file name)
 * @param subDirectories    The sub-directories as per the heirarchial order
 * @param dbVersion         The database version to check against
 */
(context: Context, val databaseName: String, subDirectories: Array<String>?, dbVersion: Int) {
    val assetPath: String
    var databaseVersion: Int = 0
        private set
    var result: Int = 0
        private set


    init {
        assetPath = applySubDirectories(databaseName, subDirectories)
        Log.d("SQLAVC", "Looking for Asset $assetPath")
        var stage = 0
        try {
            val `is` = context.assets.open(assetPath)
            stage++
            // Get the first 64 bytes of the header
            val v = ByteArray(64)
            `is`.read(v, 0, 64)
            // only interested in the 4 bytes from offset 60 so get them
            val v2 = ByteArray(4)
            for (i in 60..63) {
                v2[i - 60] = v[i]
            }
            stage++
            // Done with the InputStream so close it
            `is`.close()
            // Extarct the stored DBVersion
            databaseVersion = ByteBuffer.wrap(v2).int
            if (databaseVersion < dbVersion) {
                result = ASSETVERSIONLOW

            }
            if (databaseVersion > dbVersion) {
                result = ASSETVERSIONHIGH
            }
            if (databaseVersion == dbVersion) {
                result = ASSETVERSIONMATCH
            }

        } catch (e: IOException) {
            e.printStackTrace()
            when (stage) {
                0 -> result = ASSETNOTFOUND
                1 -> result = ASSETIOERROR
            }
        }

    }

    constructor(context: Context, dbName: String, dbVersion: Int) : this(context, dbName, null, dbVersion) {}

    private fun applySubDirectories(dbname: String, subDirectories: Array<String>?): String {
        val base = StringBuffer("")
        var firstdirectory = true
        if (subDirectories != null) {
            for (d in subDirectories) {
                if (!firstdirectory) {
                    base.append(File.separatorChar)
                }
                firstdirectory = false
                base.append(d)
            }
        }
        if (base.length > 0) {
            base.append(File.separatorChar)
        }
        base.append(dbname)
        return base.toString()
    }

    companion object {

        val ASSETNOTFOUND = -2
        val ASSETIOERROR = -3
        val ASSETVERSIONMATCH = 0
        val ASSETVERSIONHIGH = 1
        val ASSETVERSIONLOW = -1
    }
}

И ето дейност, която използва горния клас два пъти, за да се опита да провери версията в testdb файл.

  • Първото използване не намира файла на базата данни testdb както се търси вактиви папка (не поддиректорията на базата данни).

  • Второто използване намира testdb файл като поддиректория бази данни е посочен (3-ти параметър на пълния конструктор), намиращ се в активи/бази от данни/ папка, т.е. assets/databases/testdb :-

MainActivity.kt :-

class MainActivity : AppCompatActivity() {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val db_version_to_check_against = 100

        var mAVC1 = SQLAssetVersionCheck(this, "testdb", 100)

        var result = ""
        when (mAVC1.result) {
            SQLAssetVersionCheck.ASSETIOERROR -> result = "IO ERROR detected - check the Log"
            SQLAssetVersionCheck.ASSETNOTFOUND -> result = "The Asset, for Database " + mAVC1.databaseName + " was not located at  " + mAVC1.assetPath
            SQLAssetVersionCheck.ASSETVERSIONHIGH -> result = "The Asset was located and the version number being " +
                    mAVC1.databaseVersion.toString() +
                    " was higher than the version to be checked which was " +
                    db_version_to_check_against.toString()
            SQLAssetVersionCheck.ASSETVERSIONLOW -> result = "The Asset was located and the version number being " +
                    mAVC1.databaseVersion.toString() +
                    " was lower than the version to be checked which was " +
                    db_version_to_check_against.toString()
            SQLAssetVersionCheck.ASSETVERSIONMATCH -> result = "The Asset version and the version to be check ed are the same."
        }
        Log.d("ASSETVERSIONCHECK", "The result of the version check was - $result")

        var mAVC2 = SQLAssetVersionCheck(this, "testdb", arrayOf("databases"), db_version_to_check_against)
        result = ""
        when (mAVC2.result) {
            SQLAssetVersionCheck.ASSETIOERROR -> result = "IO ERROR detected - check the Log"
            SQLAssetVersionCheck.ASSETNOTFOUND -> result = "The Asset, for Database " + mAVC2.databaseName + " was not located at  " + mAVC2.assetPath
            SQLAssetVersionCheck.ASSETVERSIONHIGH -> result = "The Asset was located and the version number being " +
                    mAVC2.databaseVersion.toString() +
                    " was higher than the version to be checked which was " +
                    db_version_to_check_against.toString()
            SQLAssetVersionCheck.ASSETVERSIONLOW -> result = "The Asset was located and the version number being " +
                    mAVC2.databaseVersion.toString() +
                    " was lower than the version to be checked which was " +
                    db_version_to_check_against.toString()
            SQLAssetVersionCheck.ASSETVERSIONMATCH -> result = "The Asset version and the version to be check ed are the same."
        }
        Log.d("ASSETVERSIONCHECK", "The result of the version check was - $result")
    }
}

Резултат (регистрационен файл) :-

2019-02-19 13:11:34.473 19058-19058/com.example.so54741423assetdbversioning D/SQLAVC: Looking for Asset testdb
2019-02-19 13:11:34.473 19058-19058/com.example.so54741423assetdbversioning W/System.err: java.io.FileNotFoundException: testdb
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.content.res.AssetManager.nativeOpenAsset(Native Method)
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.content.res.AssetManager.open(AssetManager.java:744)
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.content.res.AssetManager.open(AssetManager.java:721)
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at com.example.so54741423assetdbversioning.SQLAssetVersionCheck.<init>(SQLAssetVersionCheck.kt:31)
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at com.example.so54741423assetdbversioning.SQLAssetVersionCheck.<init>(SQLAssetVersionCheck.kt:67)
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at com.example.so54741423assetdbversioning.MainActivity.onCreate(MainActivity.kt:17)
2019-02-19 13:11:34.474 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.Activity.performCreate(Activity.java:7136)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.Activity.performCreate(Activity.java:7127)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:106)
2019-02-19 13:11:34.475 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.os.Looper.loop(Looper.java:193)
2019-02-19 13:11:34.476 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6669)
2019-02-19 13:11:34.476 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
2019-02-19 13:11:34.476 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
2019-02-19 13:11:34.476 19058-19058/com.example.so54741423assetdbversioning W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2019-02-19 13:11:34.476 19058-19058/com.example.so54741423assetdbversioning D/ASSETVERSIONCHECK: The result of the version check was - The Asset, for Database testdb was not located at  testdb




2019-02-19 13:11:34.476 19058-19058/com.example.so54741423assetdbversioning D/SQLAVC: Looking for Asset databases/testdb
2019-02-19 13:11:34.477 19058-19058/com.example.so54741423assetdbversioning D/ASSETVERSIONCHECK: The result of the version check was - The Asset was located and the version number being 5 was lower than the version to be checked which was 100
  • Първият опит не намира файла (показва се изключението, което е уловено) и показва реда Резултатът от проверката на версията беше - Активът, за база данни testdb не беше разположен в testdb да се покаже.

  • Вторият опит работи и води до Резултатът от проверката на версията беше - Активът беше открит и номерът на версията, който беше 5, беше по-нисък от версията за проверка, която беше 100

  • Празнината на празните редове беше добавена, за да се раздели втория опит от първия.

Допълнително

След като използвате инструмента SQLite Manager (Navicat) и използвате :-

PRAGMA user_version = 101;

След това копирате файла (след затваряне на връзката в Navicat) в папката с активи (така че имам два файла testdb), резултатът е:-

2019-02-19 13:50:09.874 19253-19253/com.example.so54741423assetdbversioning D/SQLAVC: Looking for Asset testdb
2019-02-19 13:50:09.874 19253-19253/com.example.so54741423assetdbversioning D/ASSETVERSIONCHECK: The result of the version check was - The Asset was located and the version number being 101 was higher than the version to be checked which was 100
2019-02-19 13:50:09.874 19253-19253/com.example.so54741423assetdbversioning D/SQLAVC: Looking for Asset databases/testdb
2019-02-19 13:50:09.874 19253-19253/com.example.so54741423assetdbversioning D/ASSETVERSIONCHECK: The result of the version check was - The Asset was located and the version number being 5 was lower than the version to be checked which was 100
  • т.е. новият файл има user_version като 101 и така първият намира файла, вторият намира файла (user_version 5) както преди.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да вмъкнете изображение в библиотеката за постоянство на стаята?

  2. Android SQLite LIKE escape заместващ знак

  3. Как да тествате методи, които се занимават с база данни SQLite в android?

  4. SQLite JSON_ARRAY_LENGTH()

  5. Заместващи символи на Android SQLite