/* * Copyright 2024 ObjectBox Ltd. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.sw.dualscreen.objbox import android.content.Context import android.util.Log import io.objectbox.BoxStore import io.objectbox.BoxStoreBuilder import io.objectbox.android.Admin import io.objectbox.android.ObjectBoxLiveData import io.objectbox.exception.DbException import io.objectbox.exception.FileCorruptException import io.objectbox.sync.Sync import timber.log.Timber import java.io.File import java.util.Date import java.util.zip.GZIPOutputStream import kotlin.also import kotlin.io.copyTo import kotlin.io.inputStream import kotlin.io.outputStream import kotlin.io.use import kotlin.jvm.java import kotlin.jvm.javaClass /** * Singleton to keep BoxStore reference and provide current list of Notes Objects. * Inserts demo data if no Objects are stored. */ object ObjectBox { // 确保所有设备/版本使用相同的objectbox-models/default.json // 避免直接修改自动生成的MyObjectBox类 // 跨版本升级时使用boxStore.runInTx执行数据迁移 private const val TAG = "ObjectBox" lateinit var boxStore: BoxStore private set /** * If building the [boxStore] failed, contains the thrown error message. */ var dbExceptionMessage: String? = null private set fun init(context: Context) { // On Android make sure to pass a Context when building the Store. boxStore = try { MyObjectBox.builder() .androidContext(context.applicationContext) .build() } catch (e: DbException) { if (e.javaClass == DbException::class.java || e is FileCorruptException) { // Failed to build BoxStore due to database file issue, store message; // checked in NoteListActivity to notify user. dbExceptionMessage = e.toString() return } else { // Failed to build BoxStore due to developer error. throw e } } // if (BuildConfig.DEBUG) { val syncAvailable = if (Sync.isAvailable()) "available" else "unavailable" Timber.tag(TAG) .d("Using ObjectBox ${BoxStore.getVersion()} (${BoxStore.getVersionNative()}, sync $syncAvailable)") // Enable ObjectBox Admin on debug builds. // https://docs.objectbox.io/data-browser Admin(boxStore).start(context.applicationContext) // } } /** * If the database file is not in use, compresses (GZIP) and copies it to the given [target]. */ fun copyAndGzipDatabaseFileTo(target: File, context: Context): Boolean { if (BoxStore.isDatabaseOpen(context, null)) { // Do not copy if database file is still in use. // If it would be open, the copy will likely get corrupted // as BoxStore may currently write data to the file. Timber.tag(TAG).e("Database file is still in use, can not copy.") return false } // If a name was given when building BoxStore use that instead of the default below. val dbName = BoxStoreBuilder.DEFAULT_NAME File(context.filesDir, "objectbox/$dbName/data.mdb").inputStream().use { input -> target.parentFile?.mkdirs() GZIPOutputStream(target.outputStream()).use { output -> input.copyTo(output, DEFAULT_BUFFER_SIZE) } } return true } }