sql >> Base de Datos >  >> RDS >> SQLite

Cómo leer el número de versión de un archivo de base de datos en Android que se encuentra en la carpeta de activos

No hay un solo número de versión, sino que el número de versión podría ser varios valores.

Supongo que está hablando de la versión_usuario que utiliza Android SDK SQLiteOpenHelper.

También está el application_id , que al igual que user_version se puede utilizar como una variable de usuario.

Ya ha encontrado SQLite_Version, por lo que se puede descontar.

También está data_version, es poco probable que sea el número de versión, ya que está diseñado para usarse como una indicación si el archivo de la base de datos se ha modificado en tiempo real.

También está el schema_version, probablemente NO desee utilizarlo como Advertencia:el uso indebido de este pragma puede provocar daños en la base de datos.

versión_usuario

Como se dijo anteriormente, probablemente esté hablando de la versión_usuario . Lo primero que se debe tener en cuenta es que se trata de una variable/campo controlado por el usuario disponible para uso personalizado. SQlite no usa ni cambia la versión_de_usuario pero permite cambiarlo y usarlo.

Además, los administradores de SQLite (como DB Browser, Navicat, etc.) no cambiarían automáticamente el número de versión. Como tal, tendría que cambiar intencionalmente la versión de usuario para que esté disponible antes de copiar el archivo de la base de datos en la carpeta de activos (tenga en cuenta que si lo hace y está utilizando una subclase de SQLiteOpenHelper que el onUpgrade y el onDowngrade se pueden llamar métodos).

Si la versión_usuario no se modifica específicamente y solo se accedió a la base de datos mediante la herramienta SQLite Manager, su versión_usuario será 0. Si el archivo de la base de datos se abrió copiando el archivo de la base de datos desde una aplicación de Android que utiliza una subclase de SQLiteOpenHelper, tendrá una versión de usuario de 1 o más (según el último valor utilizado como el cuarto parámetro para el constructor de SQLiteOpenHelper). Por supuesto, si la versión_usuario se cambia programáticamente, dicho cambio también se reflejaría si el archivo se copiara en una herramienta SQlite Manager.

Antes de copiar el archivo, la versión_usuario normalmente se cambiaría dentro de la herramienta SQlite Manager a un valor apropiado.

Puede cambiar la versión_usuario usando SQL PRAGMA user_version = 5; Puede recuperar la versión_usuario utilizando PRAGMA user_version o SELECT * FROM pragma_user_version;

Si necesita verificar la versión antes de abrir la base de datos, puede leer los 4 bytes en el desplazamiento 60 y convertir los 4 bytes en un número entero, para verificar la versión_usuario con otro valor. De lo contrario, probablemente tendría que copiar el archivo, probablemente con un nombre diferente, desde la carpeta de activos, abrirlo como SQLiteDatabase y recuperar la versión_usuario usando el SQL anterior y luego compararlo con el otro valor, cerrando el archivo de la base de datos. Eliminar el archivo si no es necesario, de lo contrario, eliminar el archivo de base de datos anterior y luego cambiar el nombre del archivo copiado.

Ejemplo

El siguiente es un ejemplo de trabajo (observando que rara vez uso Kotlin y esto se ha convertido usando AS Studio de Java).

Esto usa una clase, a saber, SQLAssetVersionCheck que extrae el número de versión del archivo en lugar de abrir el archivo como 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
    }
}

Y aquí hay una actividad que usa la clase anterior dos veces para intentar verificar la versión en testdb archivo.

  • El primer uso no encuentra el archivo de base de datos testdb como está buscando en activos carpeta (no el subdirectorio de bases de datos).

  • El segundo uso encuentra el testdb archivo como el subdirectorio bases de datos se especifica (tercer parámetro del constructor completo), encontrándolo en assets/databases/ carpeta, es decir, assets/databases/testdb :-

Actividad Principal.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")
    }
}

Resultado (registro) :-

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
  • El primer intento no encuentra el archivo (se muestra la excepción que se detectó) y muestra la línea El resultado de la verificación de la versión fue:el activo, para la base de datos testdb no se encuentra en testdb para ser mostrado.

  • El segundo intento funciona y da como resultado El resultado de la verificación de la versión fue:se localizó el recurso y el número de versión, que era 5, era inferior a la versión que se verificaría, que era 100

  • Se agregó el espacio de líneas en blanco para dividir el segundo intento del primero.

Adicional

Después de usar la herramienta SQLite Manager (Navicat) y usar :-

PRAGMA user_version = 101;

Luego, copiando el archivo (después de cerrar la conexión en Navicat) a la carpeta de activos (así que tengo dos archivos testdb), el resultado es:-

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
  • es decir, el nuevo archivo tiene la versión_usuario como 101, por lo que el primero encuentra el archivo, el segundo encuentra el archivo (versión_usuario 5) como antes.