SQLite
 sql >> Teknologi Basis Data >  >> RDS >> SQLite

Cara membaca nomor versi dari file database di Android yang ditempatkan di folder aset

Tidak ada nomor versi tunggal, sebaliknya nomor versi bisa menjadi beberapa nilai.

Kira-kira Anda berbicara tentang user_version yang digunakan Android SDK SQLiteOpenHelper.

Ada juga application_id , yang seperti versi_pengguna dapat digunakan sebagai variabel pengguna.

Anda telah menemukan SQLite_Version, sehingga dapat didiskon.

Ada juga data_version, ini sepertinya bukan nomor versi, karena ini dimaksudkan untuk digunakan sebagai indikasi jika file database telah dimodifikasi secara real time.

Ada juga schema_version, Anda mungkin TIDAK ingin menggunakan ini sebagai Peringatan:Penyalahgunaan pragma ini dapat mengakibatkan kerusakan database.

versi_pengguna

Seperti yang dikatakan sebelumnya, Anda mungkin berbicara tentang user_version . Hal pertama yang perlu diperhatikan adalah bahwa ini adalah variabel/bidang yang dikendalikan pengguna yang tersedia untuk penggunaan khusus. SQLite tidak menggunakan atau mengubah user_version tetapi mengizinkannya untuk diubah dan digunakan.

Selanjutnya Manajer SQLite (seperti DB Browser, Navicat dll) tidak akan secara otomatis mengubah nomor versi. Karena itu, Anda harus dengan sengaja mengubah versi_pengguna agar tersedia sebelum menyalin file database ke folder aset (perhatikan bahwa jika melakukannya dan Anda menggunakan subkelas SQLiteOpenHelper bahwa onUpgrade dan onDowngrade metode dapat dipanggil).

Jika versi_pengguna tidak diubah secara spesifik dan basis data hanya diakses oleh alat SQLite Manager, maka versi_pengguna akan menjadi 0. Jika file basis data dibuka dengan menyalin file basis data dari Aplikasi Android yang menggunakan subkelas SQLiteOpenHelper, maka akan ada user_version dari 1 atau lebih (bergantung pada nilai terakhir yang digunakan sebagai parameter ke-4 untuk konstrkutor SQLiteOpenHelper). Tentu saja jika versi_pengguna diubah secara terprogram, maka perubahan seperti itu juga akan terlihat jika file disalin ke alat Manajer SQLite.

Sebelum menyalin file, versi_pengguna biasanya akan diubah dalam alat Manajer SQLite ke nilai yang sesuai.

Anda dapat mengubah versi_pengguna menggunakan SQL PRAGMA user_version = 5; Anda dapat mengambil user_version menggunakan PRAGMA user_version atau SELECT * FROM pragma_user_version;

Jika Anda perlu memeriksa versi sebelum membuka database, maka Anda dapat membaca 4 byte pada offset 60 dan mengonversi 4 byte menjadi bilangan bulat, untuk memeriksa versi_pengguna dengan nilai lain. Jika tidak, Anda mungkin harus menyalin file, kemungkinan menggunakan nama yang berbeda, dari folder aset, membukanya sebagai SQLiteDatabase dan mengambil versi_pengguna menggunakan SQL di atas dan kemudian memeriksanya dengan nilai lain, menutup file database. Menghapus file jika tidak diperlukan, jika tidak menghapus file database sebelumnya dan kemudian mengganti nama file yang disalin.

Contoh

Berikut ini adalah contoh kerja (perhatikan bahwa saya jarang menggunakan Kotlin dan ini telah dikonversi menggunakan AS studio dari java).

Ini menggunakan kelas, yaitu SQLAssetVersionCheck yang mengekstrak nomor versi dari file daripada membuka file sebagai 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
    }
}

Dan inilah Aktivitas yang menggunakan kelas di atas dua kali untuk mencoba memeriksa versi di testdb berkas.

  • Penggunaan pertama tidak menemukan file database testdb seperti yang terlihat di aset folder (bukan sub-direktori database).

  • Penggunaan kedua menemukan testdb file sebagai sub-direktori database ditentukan (parameter ke-3 dari konstruktor lengkap), ditemukan di assets/databases/ folder yaitu aset/database/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")
    }
}

Hasil (log) :-

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
  • Upaya pertama tidak menemukan file (pengecualian yang tertangkap ditampilkan) dan menampilkan baris Hasil pemeriksaan versi adalah - Aset, untuk Database testdb tidak terletak di testdb untuk ditampilkan.

  • Upaya kedua berhasil dan menghasilkan Hasil pemeriksaan versi adalah - Aset ditemukan dan nomor versi 5 lebih rendah dari versi yang akan diperiksa yaitu 100

  • Kesenjangan baris kosong ditambahkan untuk memisahkan upaya kedua dari yang pertama.

Tambahan

Setelah menggunakan alat SQLite Manager (Navicat) dan menggunakan :-

PRAGMA user_version = 101;

Kemudian copy file tersebut (setelah menutup koneksi di Navicat) ke folder assets (jadi saya punya dua file testdb) maka hasilnya :-

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
  • yaitu file baru memiliki user_version sebagai 101 dan yang pertama menemukan file tersebut, yang kedua menemukan file (user_version 5) seperti sebelumnya.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana cara memberi nilai cepat pada posisi nol pemintal?

  2. Menjalankan Total-Order Berdasarkan Tanggal di SQLite

  3. java.util.MissingFormatArgumentException:Penentu format:s

  4. Android:SQLite menyimpan larik string?

  5. onCreate() dari RoomDatabase.Callback() tidak dipanggil setelah panggilan berhasil ke .build()