Neexistuje jediné číslo verze, místo toho může být číslo verze více hodnot.
Předpokládám, že mluvíte o user_version kterou používá Android SDK SQLiteOpenHelper.
Je zde také id_aplikace , kterou lze stejně jako user_version použít jako uživatelskou proměnnou.
S SQLite_Version jste se již setkali, takže to lze zlevnit.
Je zde také data_version, je nepravděpodobné, že to bude číslo verze, protože je zamýšleno k použití jako indikace, zda byl databázový soubor změněn v reálném čase.
Existuje také schema_version, pravděpodobně to NECHCETE používat jako Upozornění:Zneužití tohoto pragmatu může vést k poškození databáze.
uživatelská_verze
Jak již bylo řečeno, pravděpodobně mluvíte o user_version . První věc, kterou je třeba poznamenat, je, že se jedná o uživatelem ovládanou proměnnou/pole zpřístupněnou pro vlastní použití. SQlite nepoužívá ani nemění user_version ale umožňuje jeho změnu a použití.
Navíc správci SQLite (jako je DB Browser, Navicat atd.) by automaticky nezměnili číslo verze. Jako takový byste museli záměrně změnit user_version, aby byl dostupný před zkopírováním databázového souboru do složky aktiv (všimněte si, že pokud tak učiníte a používáte podtřídu SQLiteOpenHelper
že onUpgrade
a onDowngrade
mohou být volány metody).
Pokud se uživatelská_verze konkrétně nezměnila a k databázi přistupoval pouze nástroj SQLite Manager, pak její uživatelská verze bude 0. Pokud byl databázový soubor otevřen zkopírováním databázového souboru z aplikace pro Android, která využívá podtřídu SQLiteOpenHelper, bude mít user_version 1 nebo více (v závislosti na poslední hodnotě použité jako 4. parametr konstruktoru SQLiteOpenHelper). Samozřejmě pokud se user_version změní programově, pak by se taková změna projevila i v případě, že by byl soubor zkopírován do nástroje SQlite Manager.
Před zkopírováním souboru by se user_version obvykle změnil v nástroji SQlite Manager na vhodnou hodnotu.
Můžete změnit user_version pomocí SQL PRAGMA user_version = 5;
Můžete načíst user_version pomocí buď PRAGMA user_version
nebo SELECT * FROM pragma_user_version;
Pokud potřebujete zkontrolovat verzi před otevřením databáze, můžete přečíst 4 bajty s offsetem 60 a převést 4 bajty na celé číslo, abyste porovnali user_version s jinou hodnotou. V opačném případě byste pravděpodobně museli zkopírovat soubor, pravděpodobně s jiným názvem, ze složky aktiv, otevřít jej jako SQLiteDatabase a načíst user_version pomocí výše uvedeného SQL a poté jej porovnat s jinou hodnotou, čímž se soubor databáze zavře. Smazání souboru, pokud to není potřeba, jinak smazání předchozího databázového souboru a následné přejmenování zkopírovaného souboru.
Příklad
Následuje pracovní příklad (upozorňuji, že Kotlin používám jen zřídka a toto bylo převedeno pomocí AS studio z javy).
To používá třídu, konkrétně SQLAssetVersionCheck který ze souboru extrahuje číslo verze místo otevření souboru jako 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
}
}
A zde je aktivita, která používá výše uvedenou třídu dvakrát, aby se pokusila zkontrolovat verzi v testdb soubor.
-
Při prvním použití nebyl nalezen databázový soubor testdb jak to vypadá v aktivech složku (nikoli podadresář databází).
-
Druhé použití najde testdb soubor jako podadresář databáze je zadán (3. parametr úplného konstruktoru), který najdete v assets/databases/ složka, tj. 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")
}
}
Výsledek (protokol) :-
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
-
První pokus nenajde soubor (zobrazí se výjimka, která byla zachycena) a zobrazí řádek Výsledek kontroly verze byl - The Asset, for Database testdb was not found at testdb k zobrazení.
-
Druhý pokus funguje a má za následek Výsledek kontroly verze byl - Majetek byl nalezen a číslo verze 5 bylo nižší než verze ke kontrole, která byla 100
-
Mezera prázdných řádků byla přidána, aby se oddělil druhý pokus od prvního.
Další
Po použití nástroje SQLite Manager (Navicat) a pomocí :-
PRAGMA user_version = 101;
Poté zkopírujte soubor (po uzavření připojení v Navicat) do složky aktiv (takže mám dva soubory testdb), výsledek je :-
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
- tj. nový soubor má user_version jako 101, takže první najde soubor, druhý najde soubor (user_version 5) jako předtím.