Не существует единого номера версии, вместо этого номер версии может иметь несколько значений.
Предполагается, что вы говорите о user_version , который использует Android SDK SQLiteOpenHelper.
Существует также application_id , который, например, user_version, может использоваться в качестве пользовательской переменной.
Вы уже встретили SQLite_Version, поэтому его можно сбрасывать со счетов.
Существует также data_version, вряд ли это будет номер версии, так как он предназначен для использования в качестве индикации, если файл базы данных был изменен в реальном времени.
Существует также схема_версии,вы, вероятно, НЕ хотите использовать это как Предупреждение. Неправильное использование этой прагмы может привести к повреждению базы данных.
user_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-го параметра для constrcutor 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 с другим значением.В противном случае вам, вероятно, придется скопировать файл, вероятно, с другим именем, из папки ресурсов, открыть его как базу данных SQLite и получить версию user_version с использованием приведенного выше SQL-кода, а затем сравнить его с другим значением, закрыв файл базы данных.Удаление файла, если не нужно, в противном случае удалить предыдущий файл базы данных, а затем переименовать скопированный файл.
Пример
Ниже приведен рабочий пример (обратите внимание, что я редко использую Kotlin, и это имеетбыл преобразован с использованием AS studio из java).
Используется класс, а именно SQLAssetVersionCheck , который извлекает номер версии из файла, а не открывает файл как базу данных SQLite.
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 , так как он ищет в папке assets (не подкаталог базы данных).
Второе использование находит файл testdb в качестве подкаталога database (третий параметр полного конструктора), находя в assets / database/ папка, т.е. assets / 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")
}
}
Результат (журнал): -
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), как раньше.