continue room migration [2/?]

w: builds are still expected to fail

[skip ci]

Signed-off-by: androidacy-user <opensource@androidacy.com>
pull/89/head
androidacy-user 2 years ago
parent 74e3a746b3
commit c123c7b427

@ -22,7 +22,6 @@ import androidx.room.Room
import com.fox2code.foxcompat.app.FoxActivity
import com.fox2code.mmm.databinding.ActivitySetupBinding
import com.fox2code.mmm.utils.IntentHelper
import com.fox2code.mmm.utils.realm.ReposList
import com.fox2code.mmm.utils.room.ModuleListCacheDatabase
import com.fox2code.mmm.utils.room.ReposListDatabase
import com.fox2code.rosettax.LanguageActivity
@ -33,8 +32,6 @@ import com.google.android.material.checkbox.MaterialCheckBox
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.materialswitch.MaterialSwitch
import com.topjohnwu.superuser.internal.UiThreadHandler
import io.realm.Realm
import io.realm.RealmConfiguration
import org.apache.commons.io.FileUtils
import timber.log.Timber
import java.io.File
@ -43,7 +40,6 @@ import java.util.Objects
class SetupActivity : FoxActivity(), LanguageActivity {
private var cachedTheme = 0
private var realmDatabasesCreated = false
@SuppressLint("ApplySharedPref", "RestrictedApi")
override fun onCreate(savedInstanceState: Bundle?) {
@ -227,36 +223,19 @@ class SetupActivity : FoxActivity(), LanguageActivity {
(Objects.requireNonNull<Any>(view.findViewById(R.id.setup_app_analytics)) as MaterialSwitch).isChecked
)
Timber.d("Saving preferences")
// Set the repos in the ReposList realm db
val realmConfig = RealmConfiguration.Builder().name("ReposList.realm")
.encryptionKey(MainApplication.INSTANCE!!.key)
.directory(MainApplication.INSTANCE!!.getDataDirWithPath("realms"))
.schemaVersion(1).build()
val androidacyRepo = andRepoView.isChecked
val magiskAltRepo = magiskAltRepoView.isChecked
var realm = Realm.getInstance(realmConfig)
Timber.d("Realm instance: %s", realm)
if (realm.isInTransaction) {
realm.commitTransaction()
Timber.d("Committed last unfinished transaction")
}
// check if instance has been closed
if (realm.isClosed) {
Timber.d("Realm instance was closed, reopening")
realm = Realm.getInstance(realmConfig)
}
realm.executeTransactionAsync { r: Realm ->
Timber.d("Realm transaction started")
r.where(ReposList::class.java).equalTo("id", "androidacy_repo")
.findFirst()!!.isEnabled = androidacyRepo
r.where(ReposList::class.java).equalTo("id", "magisk_alt_repo")
.findFirst()!!.isEnabled = magiskAltRepo
Timber.d("Realm transaction committing")
// commit the changes
r.commitTransaction()
r.close()
Timber.d("Realm transaction committed")
}
// now basically do the same thing for room db
val db = Room.databaseBuilder(
applicationContext,
ReposListDatabase::class.java, "ReposList.db"
).build()
val androidacyRepoRoom = andRepoView.isChecked
val magiskAltRepoRoom = magiskAltRepoView.isChecked
val reposListDao = db.reposListDao()
val androidacyRepoRoomObj = reposListDao.getById("androidacy_repo")
val magiskAltRepoRoomObj = reposListDao.getById("magisk_alt_repo")
reposListDao.setEnabled(androidacyRepoRoomObj.id, androidacyRepoRoom)
reposListDao.setEnabled(magiskAltRepoRoomObj.id, magiskAltRepoRoom)
db.close()
editor.putString("last_shown_setup", "v3")
// Commit the changes
editor.commit()
@ -268,8 +247,8 @@ class SetupActivity : FoxActivity(), LanguageActivity {
}
// Log the changes
Timber.d("Setup finished. Preferences: %s", prefs.all)
Timber.d("Androidacy repo: %s", androidacyRepo)
Timber.d("Magisk Alt repo: %s", magiskAltRepo)
Timber.d("Androidacy repo: %s", androidacyRepoRoom)
Timber.d("Magisk Alt repo: %s", magiskAltRepoRoom)
// log last shown setup
Timber.d("Last shown setup: %s", prefs.getString("last_shown_setup", "v0"))
// Restart the activity
@ -384,7 +363,6 @@ class SetupActivity : FoxActivity(), LanguageActivity {
FileUtils.forceMkdir(File(MainApplication.INSTANCE!!.dataDir.toString() + "/cache/cronet"))
FileUtils.forceMkdir(File(MainApplication.INSTANCE!!.dataDir.toString() + "/cache/WebView/Default/HTTP Cache/Code Cache/wasm"))
FileUtils.forceMkdir(File(MainApplication.INSTANCE!!.dataDir.toString() + "/cache/WebView/Default/HTTP Cache/Code Cache/js"))
FileUtils.forceMkdir(File(MainApplication.INSTANCE!!.dataDir.toString() + "/repos/magiskAltRepo"))
} catch (e: IOException) {
Timber.e(e)
}
@ -393,7 +371,7 @@ class SetupActivity : FoxActivity(), LanguageActivity {
@Suppress("KotlinConstantConditions")
private fun disableUpdateActivityForFdroidFlavor() {
if (BuildConfig.FLAVOR == "fdroid") {
if (BuildConfig.FLAVOR == "fdroid" || BuildConfig.FLAVOR == "play") {
// check if the update activity is enabled
val pm = packageManager
val componentName = ComponentName(this, UpdateActivity::class.java)

@ -26,6 +26,7 @@ import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.fox2code.mmm.AppUpdateManager
import com.fox2code.mmm.BuildConfig
import com.fox2code.mmm.MainActivity
import com.fox2code.mmm.MainApplication
import com.fox2code.mmm.R
@ -53,7 +54,7 @@ class BackgroundUpdateChecker(context: Context, workerParams: WorkerParameters)
private const val NOTFIICATION_GROUP = "updates"
private const val NOTIFICATION_CHANNEL_ID_APP = "background_update_app"
val lock =
Any() // Avoid concurrency issuespublic static final String NOTIFICATION_CHANNEL_ID = "background_update";
Any() // Avoid concurrency issues
private const val NOTIFICATION_ID_ONGOING = 2
private const val NOTIFICATION_CHANNEL_ID_ONGOING = "mmm_background_update"
private const val NOTIFICATION_ID_APP = 3
@ -111,7 +112,7 @@ class BackgroundUpdateChecker(context: Context, workerParams: WorkerParameters)
}
}
@Suppress("NAME_SHADOWING")
@Suppress("NAME_SHADOWING", "KotlinConstantConditions")
fun doCheck(context: Context) {
// first, check if the user has enabled background update checking
if (!MainApplication.getSharedPreferences("mmm")!!
@ -280,14 +281,20 @@ class BackgroundUpdateChecker(context: Context, workerParams: WorkerParameters)
if (MainApplication.getSharedPreferences("mmm")!!
.getBoolean("pref_background_update_check_app", false)
) {
try {
val shouldUpdate = AppUpdateManager.appUpdateManager.checkUpdate(true)
if (shouldUpdate) {
Timber.d("Found app update")
postNotificationForAppUpdate(context)
// don't check if app is from play store or fdroid
if (BuildConfig.FLAVOR != "play" || BuildConfig.FLAVOR != "fdroid") {
try {
val shouldUpdate = AppUpdateManager.appUpdateManager.checkUpdate(true)
if (shouldUpdate) {
Timber.d("Found app update")
postNotificationForAppUpdate(context)
} else {
Timber.d("No app update found")
}
} catch (e: Exception) {
Timber.e("Failed to check for app update")
}
} catch (e: Exception) {
Timber.e("Failed to check for app update")
}
}
// remove checking notification

@ -4,6 +4,7 @@
package com.fox2code.mmm.repo
import android.net.Uri
import androidx.room.Room
import com.fox2code.mmm.AppUpdateManager.Companion.shouldForceHide
import com.fox2code.mmm.BuildConfig
import com.fox2code.mmm.MainActivity
@ -13,16 +14,13 @@ import com.fox2code.mmm.XRepo
import com.fox2code.mmm.manager.ModuleInfo
import com.fox2code.mmm.utils.io.Files.Companion.write
import com.fox2code.mmm.utils.io.PropUtils.Companion.readProperties
import com.fox2code.mmm.utils.realm.ModuleListCache
import com.fox2code.mmm.utils.realm.ReposList
import io.realm.Realm
import io.realm.RealmConfiguration
import com.fox2code.mmm.utils.room.ModuleListCacheDatabase
import com.fox2code.mmm.utils.room.ReposListDatabase
import org.json.JSONException
import org.json.JSONObject
import timber.log.Timber
import java.io.File
import java.io.IOException
import java.util.concurrent.atomic.AtomicBoolean
@Suppress("LeakingThis", "SENSELESS_COMPARISON", "RedundantSetter")
open class RepoData(url: String, cacheRoot: File) : XRepo() {
@ -150,40 +148,20 @@ open class RepoData(url: String, cacheRoot: File) : XRepo() {
defaultName = url // Set url as default name
val tempVarForPreferenceId = preferenceId!!
isForceHide = shouldForceHide(tempVarForPreferenceId)
// this.enable is set from the database
val realmConfiguration = RealmConfiguration.Builder().name("ReposList.realm").encryptionKey(
INSTANCE!!.key
).allowQueriesOnUiThread(true).allowWritesOnUiThread(true).directory(
INSTANCE!!.getDataDirWithPath("realms")
).schemaVersion(1).build()
val realm = Realm.getInstance(realmConfiguration)
val reposList = realm.where(ReposList::class.java).equalTo("id", preferenceId).findFirst()
if (reposList == null) {
Timber.d("RepoData for %s not found in database", preferenceId)
// log every repo in db
val fullList: Array<Any> = realm.where(ReposList::class.java).findAll().toTypedArray()
Timber.d("RepoData: " + preferenceId + ". repos in database: " + fullList.size)
for (repo in fullList) {
val r = repo as ReposList
Timber.d("RepoData: " + preferenceId + ". repo: " + r.id + " " + r.name + " " + r.website + " " + r.support + " " + r.donate + " " + r.submitModule + " " + r.isEnabled)
}
} else {
Timber.d("RepoData for %s found in database", preferenceId)
}
Timber.d(
"RepoData: $preferenceId. record in database: " + (reposList?.toString()
?: "none")
)
enabled = !isForceHide && reposList != null && reposList.isEnabled
// basically same as above but for room database
val db = Room.databaseBuilder(
INSTANCE!!.applicationContext,
ReposListDatabase::class.java,
"repo_database"
).allowMainThreadQueries().build()
val reposListRoom = db.reposListDao()
val reposListRoomList = reposListRoom.getById(preferenceId!!)
enabled = !isForceHide && reposListRoomList != null && reposListRoomList.enabled
defaultWebsite = "https://" + Uri.parse(url).host + "/"
// open realm database
// load metadata from realm database
if (enabled) {
try {
metaDataCache = ModuleListCache.getRepoModulesAsJson(preferenceId)
// log count of modules in the database
val tempMetaDataCacheVar = metaDataCache!!
Timber.d("RepoData: $preferenceId. modules in database: ${tempMetaDataCacheVar.length()}")
// load repo metadata from ReposList unless it's a built-in repo
if (RepoManager.isBuiltInRepo(preferenceId)) {
name = defaultName
@ -192,28 +170,25 @@ open class RepoData(url: String, cacheRoot: File) : XRepo() {
donate = defaultDonate
submitModule = defaultSubmitModule
} else {
// get everything from ReposList realm database
name = realm.where(
ReposList::class.java
).equalTo("id", preferenceId).findFirst()?.name
website = realm.where(
ReposList::class.java
).equalTo("id", preferenceId).findFirst()?.website
support = realm.where(
ReposList::class.java
).equalTo("id", preferenceId).findFirst()?.support
donate = realm.where(
ReposList::class.java
).equalTo("id", preferenceId).findFirst()?.donate
submitModule = realm.where(
ReposList::class.java
).equalTo("id", preferenceId).findFirst()?.submitModule
// get everything from the database
name = reposListRoomList.name
website = reposListRoomList.website
support = reposListRoomList.support
donate = reposListRoomList.donate
submitModule = reposListRoomList.submitModule
// if name is null return defaultName and if defaultName is null return url
if (name == null) {
name = if (defaultName == null) {
url
} else {
defaultName
}
}
}
} catch (e: Exception) {
Timber.w("Failed to load repo metadata from database: " + e.message + ". If this is a first time run, this is normal.")
}
}
realm.close()
}
open fun prepare(): Boolean {
@ -330,27 +305,14 @@ open class RepoData(url: String, cacheRoot: File) : XRepo() {
get() = if (field) {
field
} else {
val realmConfiguration2 =
RealmConfiguration.Builder().name("ReposList.realm").encryptionKey(
INSTANCE!!.key
).allowQueriesOnUiThread(true).allowWritesOnUiThread(true).directory(
INSTANCE!!.getDataDirWithPath("realms")
).schemaVersion(1).build()
val realm2 = Realm.getInstance(realmConfiguration2)
val dbEnabled = AtomicBoolean(false)
realm2.executeTransaction { realm: Realm ->
val reposList =
realm.where(ReposList::class.java).equalTo("id", preferenceId).findFirst()
if (reposList != null) {
dbEnabled.set(reposList.isEnabled)
} else {
// should never happen but for safety
dbEnabled.set(false)
}
}
realm2.close()
val db = Room.databaseBuilder(
INSTANCE!!.applicationContext,
ReposListDatabase::class.java,
"ReposList.db",
).build()
val reposList = db.reposListDao().getById(preferenceId!!)
// should never happen but for safety
if (dbEnabled.get()) {
if (reposList.enabled) {
!isForceHide
} else {
false
@ -359,22 +321,13 @@ open class RepoData(url: String, cacheRoot: File) : XRepo() {
set(value) {
field = value
this.enabled = enabled && !isForceHide
// reposlist realm
val realmConfiguration2 =
RealmConfiguration.Builder().name("ReposList.realm").encryptionKey(
INSTANCE!!.key
).allowQueriesOnUiThread(true).allowWritesOnUiThread(true).directory(
INSTANCE!!.getDataDirWithPath("realms")
).schemaVersion(1).build()
val realm2 = Realm.getInstance(realmConfiguration2)
realm2.executeTransaction { realm: Realm ->
val reposList =
realm.where(ReposList::class.java).equalTo("id", preferenceId).findFirst()
if (reposList != null) {
reposList.isEnabled = enabled
}
}
realm2.close()
val db = Room.databaseBuilder(
INSTANCE!!.applicationContext,
ReposListDatabase::class.java,
"ReposList.db",
).build()
val reposList = db.reposListDao().getById(preferenceId!!)
db.reposListDao().update(name = reposList.name, enabled = value, id = reposList.id, donate = reposList.donate, support = reposList.support, website = reposList.website, submitModule = reposList.submitModule, lastUpdate = reposList.lastUpdate.toLong(), url = reposList.url)
}
@Throws(IOException::class)
@ -423,24 +376,17 @@ open class RepoData(url: String, cacheRoot: File) : XRepo() {
}
// if repo starts with repo_, it's always enabled bc custom repos can't be disabled without being deleted.
isForceHide = shouldForceHide(preferenceId!!)
// reposlist realm
val realmConfiguration2 =
RealmConfiguration.Builder().name("ReposList.realm").encryptionKey(
INSTANCE!!.key
).allowQueriesOnUiThread(true).allowWritesOnUiThread(true).directory(
INSTANCE!!.getDataDirWithPath("realms")
).schemaVersion(1).build()
val realm2 = Realm.getInstance(realmConfiguration2)
var dbEnabled = false
try {
dbEnabled = realm2.where(
ReposList::class.java
).equalTo("id", preferenceId).findFirst()?.isEnabled == true
} catch (e: Exception) {
Timber.e(e, "Error while updating enabled state for repo %s", preferenceId)
val db = Room.databaseBuilder(
INSTANCE!!.applicationContext,
ReposListDatabase::class.java,
"ReposList.db",
).allowMainThreadQueries().build()
val reposList = db.reposListDao().getById(preferenceId!!)
enabled = if (reposList.enabled) {
!isForceHide
} else {
false
}
realm2.close()
enabled = !isForceHide && dbEnabled
}
open fun getUrl(): String? {
@ -467,42 +413,35 @@ open class RepoData(url: String, cacheRoot: File) : XRepo() {
// should update (lastUpdate > 15 minutes)
fun shouldUpdate(): Boolean {
Timber.d("Repo $preferenceId should update check called")
val realmConfiguration2 =
RealmConfiguration.Builder().name("ReposList.realm").encryptionKey(
INSTANCE!!.key
).allowQueriesOnUiThread(true).allowWritesOnUiThread(true).directory(
INSTANCE!!.getDataDirWithPath("realms")
).schemaVersion(1).build()
val realm2 = Realm.getInstance(realmConfiguration2)
val repo = realm2.where(ReposList::class.java).equalTo("id", preferenceId).findFirst()
// Make sure ModuleListCache for repoId is not null
val cacheRoot = INSTANCE!!.getDataDirWithPath("realms/repos/$preferenceId")
val realmConfiguration =
RealmConfiguration.Builder().name("ModuleListCache.realm").encryptionKey(
INSTANCE!!.key
).schemaVersion(1).deleteRealmIfMigrationNeeded().allowWritesOnUiThread(true)
.allowQueriesOnUiThread(true).directory(cacheRoot).build()
val realm = Realm.getInstance(realmConfiguration)
val moduleListCache = realm.where(
ModuleListCache::class.java
).equalTo("repoId", preferenceId).findAll()
val db = Room.databaseBuilder(
INSTANCE!!.applicationContext,
ReposListDatabase::class.java,
"ReposList.db",
).allowMainThreadQueries().build()
val repo = db.reposListDao().getById(preferenceId!!)
// get modulelistcache
val db2 = Room.databaseBuilder(
INSTANCE!!.applicationContext,
ModuleListCacheDatabase::class.java,
"ModuleListCache.db",
).allowMainThreadQueries().build()
val moduleListCache = db2.moduleListCacheDao().getByRepoId(preferenceId!!)
if (repo != null) {
return if (repo.lastUpdate != 0 && moduleListCache.size != 0) {
return if (repo.lastUpdate != 0 && moduleListCache.isNotEmpty()) {
val lastUpdate = repo.lastUpdate.toLong()
val currentTime = System.currentTimeMillis()
val diff = currentTime - lastUpdate
val diffMinutes = diff / (60 * 1000) % 60
Timber.d("Repo $preferenceId updated: $diffMinutes minutes ago")
realm.close()
diffMinutes > if (BuildConfig.DEBUG) 15 else 30
} else {
Timber.d("Repo $preferenceId should update could not find repo in database")
Timber.d("This is probably an error, please report this to the developer")
realm.close()
true
}
} else {
realm.close()
db.close()
db2.close()
}
return true
}

@ -4,12 +4,11 @@
package com.fox2code.mmm.repo
import androidx.room.Room
import com.fox2code.mmm.MainApplication
import com.fox2code.mmm.utils.io.net.Http.Companion.doHttpGet
import com.fox2code.mmm.utils.realm.ModuleListCache
import com.fox2code.mmm.utils.realm.ReposList
import io.realm.Realm
import io.realm.RealmConfiguration
import com.fox2code.mmm.utils.room.ModuleListCacheDatabase
import com.fox2code.mmm.utils.room.ReposListDatabase
import org.json.JSONArray
import org.json.JSONObject
import timber.log.Timber
@ -39,23 +38,15 @@ class RepoUpdater(repoData2: RepoData) {
// if we shouldn't update, get the values from the ModuleListCache realm
if (!repoData.shouldUpdate() && repoData.preferenceId == "androidacy_repo") { // for now, only enable cache reading for androidacy repo, until we handle storing module prop file values in cache
Timber.d("Fetching index from cache for %s", repoData.preferenceId)
val cacheRoot =
MainApplication.INSTANCE!!.getDataDirWithPath("realms/repos/" + repoData.preferenceId)
val realmConfiguration = RealmConfiguration.Builder().name("ModuleListCache.realm")
.encryptionKey(MainApplication.INSTANCE!!.key).schemaVersion(1)
.deleteRealmIfMigrationNeeded().allowWritesOnUiThread(true)
.allowQueriesOnUiThread(true).directory(cacheRoot).build()
val realm = Realm.getInstance(realmConfiguration)
val results = realm.where(
ModuleListCache::class.java
).equalTo("repoId", repoData.preferenceId).findAll()
// repos-list realm
val realmConfiguration2 = RealmConfiguration.Builder().name("ReposList.realm")
.encryptionKey(MainApplication.INSTANCE!!.key).allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.directory(MainApplication.INSTANCE!!.getDataDirWithPath("realms"))
.schemaVersion(1).build()
val realm2 = Realm.getInstance(realmConfiguration2)
// now the above but for room
val db = Room.databaseBuilder(
MainApplication.INSTANCE!!,
ModuleListCacheDatabase::class.java,
"ModuleListCache.db"
).allowMainThreadQueries().build()
val moduleListCacheDao = db.moduleListCacheDao()
// now we have the cache, we need to check if it's up to date
val results = moduleListCacheDao.getByRepoId(repoData.preferenceId!!)
toUpdate = emptyList()
toApply = HashSet()
for (moduleListCache in results) {
@ -83,14 +74,11 @@ class RepoUpdater(repoData2: RepoData) {
// apply the toApply list to the toUpdate list
try {
val jsonObject = JSONObject()
jsonObject.put("modules", JSONArray(results.asJSON()))
jsonObject.put("modules", JSONArray(results))
toUpdate = repoData.populate(jsonObject)
} catch (e: Exception) {
Timber.e(e)
}
// close realm
realm.close()
realm2.close()
// Since we reuse instances this should work
toApply = HashSet(repoData.moduleHashMap.values)
(toApply as HashSet<RepoModule>).removeAll(toUpdate!!.toSet())
@ -141,14 +129,13 @@ class RepoUpdater(repoData2: RepoData) {
if (indexRaw != null) {
try {
// iterate over modules, using this.supportedProperties as a template to attempt to get each property from the module. everything that is not null is added to the module
// use realm to insert to
// use room to insert to
// props avail:
val cacheRoot =
MainApplication.INSTANCE!!.getDataDirWithPath("realms/repos/" + repoData.preferenceId)
val realmConfiguration = RealmConfiguration.Builder().name("ModuleListCache.realm")
.encryptionKey(MainApplication.INSTANCE!!.key).schemaVersion(1)
.deleteRealmIfMigrationNeeded().allowWritesOnUiThread(true)
.allowQueriesOnUiThread(true).directory(cacheRoot).build()
val db = Room.databaseBuilder(
MainApplication.INSTANCE!!,
ModuleListCacheDatabase::class.java,
"ModuleListCache.db"
).allowMainThreadQueries().build()
// array with module info default values
// supported properties for a module
//id=<string>
@ -182,16 +169,8 @@ class RepoUpdater(repoData2: RepoData) {
// get modules from "modules" key. This is a JSONArray so we need to convert it to a JSONObject
modules.getJSONArray("modules")
}
val realm = Realm.getInstance(realmConfiguration)
// drop old data
if (realm.isInTransaction) {
realm.commitTransaction()
}
realm.beginTransaction()
realm.where(ModuleListCache::class.java).equalTo("repoId", repoData.preferenceId)
.findAll()
.deleteAllFromRealm()
realm.commitTransaction()
val moduleListCacheDao = db.moduleListCacheDao()
moduleListCacheDao.deleteByRepoId(repoData.preferenceId!!)
// iterate over modules. pls don't hate me for this, its ugly but it works
for (n in 0 until modulesArray.length()) {
// get module
@ -296,10 +275,6 @@ class RepoUpdater(repoData2: RepoData) {
}
// get module repo id
val repoId = repoData.preferenceId
// get module installed
val installed = false
// get module installed version code
val installedVersionCode = 0
// get safe property. for now, only supported by androidacy repo and they use "vt_status" key
var safe = false
if (repoData.name == "Androidacy Modules Repo") {
@ -309,81 +284,22 @@ class RepoUpdater(repoData2: RepoData) {
}
}
}
// insert module to realm
// first create a collection of all the properties
// then insert to realm
// then commit
// then close
if (realm.isInTransaction) {
realm.cancelTransaction()
}
// create a realm object and insert or update it
// add everything to the realm object
if (realm.isInTransaction) {
realm.commitTransaction()
}
realm.beginTransaction()
val moduleListCache = realm.createObject(
ModuleListCache::class.java, id
)
moduleListCache.name = name
moduleListCache.version = version
moduleListCache.versionCode = versionCode
moduleListCache.author = author
moduleListCache.description = description
moduleListCache.minApi = minApiInt
moduleListCache.maxApi = maxApiInt
moduleListCache.minMagisk = minMagiskInt
moduleListCache.isNeedRamdisk = needRamdisk
moduleListCache.support = support
moduleListCache.donate = donate
moduleListCache.config = config
moduleListCache.isChangeBoot = changeBoot
moduleListCache.isMmtReborn = mmtReborn
moduleListCache.repoId = repoId
moduleListCache.isInstalled = installed
moduleListCache.installedVersionCode = installedVersionCode
moduleListCache.isSafe = safe
moduleListCache.lastUpdate = lastUpdate
moduleListCache.stats = downloads
realm.copyToRealmOrUpdate(moduleListCache)
realm.commitTransaction()
moduleListCacheDao.insert(name = name, version = version, versionCode = versionCode, author = author, description = description, minApi = minApiInt, maxApi = maxApiInt, minMagisk = minMagiskInt, needRamdisk = needRamdisk, support = support ?: "", donate = donate ?: "", config = config ?: "", changeBoot = changeBoot, mmtReborn = mmtReborn, repoId = repoId!!, safe = safe, lastUpdate = lastUpdate.toLong(), stats = downloads, codename = id ?: "")
} catch (ignored: Exception) {
}
}
realm.close()
} catch (ignored: Exception) {
}
indexRaw = null
val realmConfiguration2 = RealmConfiguration.Builder().name("ReposList.realm")
.encryptionKey(MainApplication.INSTANCE!!.key).allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.directory(MainApplication.INSTANCE!!.getDataDirWithPath("realms"))
.schemaVersion(1).build()
val realm2 = Realm.getInstance(realmConfiguration2)
if (realm2.isInTransaction) {
realm2.cancelTransaction()
}
// set lastUpdate
realm2.executeTransaction { r: Realm ->
val repoListCache =
r.where(ReposList::class.java).equalTo("id", repoData.preferenceId).findFirst()
if (repoListCache != null) {
success.set(true)
// get unix timestamp of current time
val currentTime = (System.currentTimeMillis() / 1000).toInt()
Timber.d(
"Updating lastUpdate for repo %s to %s which is %s seconds ago",
repoData.preferenceId,
currentTime,
currentTime - repoListCache.lastUpdate
)
repoListCache.lastUpdate = currentTime
} else {
Timber.w("Failed to update lastUpdate for repo %s", repoData.preferenceId)
}
}
realm2.close()
val db = Room.databaseBuilder(
MainApplication.INSTANCE!!.applicationContext,
ReposListDatabase::class.java,
"ReposList.db"
).allowMainThreadQueries().build()
val repoListDao = db.reposListDao()
repoListDao.setLastUpdate(repoData.preferenceId!!, System.currentTimeMillis())
db.close()
} else {
success.set(true) // assume we're reading from cache. this may be unsafe but it's better than nothing
}

@ -48,6 +48,7 @@ import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceManager;
import androidx.preference.SwitchPreferenceCompat;
import androidx.preference.TwoStatePreference;
import androidx.room.Room;
import androidx.security.crypto.EncryptedSharedPreferences;
import androidx.security.crypto.MasterKey;
@ -75,7 +76,8 @@ import com.fox2code.mmm.utils.ExternalHelper;
import com.fox2code.mmm.utils.IntentHelper;
import com.fox2code.mmm.utils.ProcessHelper;
import com.fox2code.mmm.utils.io.net.Http;
import com.fox2code.mmm.utils.realm.ReposList;
import com.fox2code.mmm.utils.room.ReposList;
import com.fox2code.mmm.utils.room.ReposListDatabase;
import com.fox2code.mmm.utils.sentry.SentryMain;
import com.fox2code.rosettax.LanguageActivity;
import com.fox2code.rosettax.LanguageSwitcher;
@ -106,9 +108,6 @@ import java.util.Objects;
import java.util.Random;
import java.util.Set;
import io.realm.Realm;
import io.realm.RealmConfiguration;
import io.realm.RealmResults;
import timber.log.Timber;
public class SettingsActivity extends FoxActivity implements LanguageActivity {
@ -1071,28 +1070,13 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
return true;
});
}
// Get magisk_alt_repo enabled state from realm db
RealmConfiguration realmConfig = new RealmConfiguration.Builder().name("ReposList.realm").encryptionKey(MainApplication.getINSTANCE().getKey()).allowQueriesOnUiThread(true).allowWritesOnUiThread(true).directory(MainApplication.getINSTANCE().getDataDirWithPath("realms")).schemaVersion(1).build();
Realm realm1 = Realm.getInstance(realmConfig);
ReposList reposList = realm1.where(ReposList.class).equalTo("id", "magisk_alt_repo").findFirst();
if (reposList != null) {
// Set the switch to the current state
SwitchPreferenceCompat magiskAltRepoEnabled = Objects.requireNonNull(findPreference("pref_magisk_alt_repo_enabled"));
magiskAltRepoEnabled.setChecked(reposList.isEnabled());
}
// add listener to magisk_alt_repo_enabled switch to update realm db
// Get magisk_alt_repo enabled state from room reposlist db
ReposListDatabase db = Room.databaseBuilder(requireContext(), ReposListDatabase.class, "ReposList.db").allowMainThreadQueries().build();
// add listener to magisk_alt_repo_enabled switch to update room db
Preference magiskAltRepoEnabled = Objects.requireNonNull(findPreference("pref_magisk_alt_repo_enabled"));
magiskAltRepoEnabled.setOnPreferenceChangeListener((preference, newValue) -> {
// Update realm db
Realm realm = Realm.getInstance(realmConfig);
realm.executeTransaction(realm2 -> {
ReposList reposList1 = realm2.where(ReposList.class).equalTo("id", "magisk_alt_repo").findFirst();
if (reposList1 != null) {
reposList1.setEnabled(Boolean.parseBoolean(String.valueOf(newValue)));
} else {
Timber.e("Alt Repo not found in realm db");
}
});
// Update room db
db.reposListDao().setEnabled("magisk_alt_repo", Boolean.parseBoolean(String.valueOf(newValue)));
return true;
});
// Disable toggling the pref_androidacy_repo_enabled on builds without an
@ -1107,37 +1091,21 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
}).show();
// Revert the switch to off
androidacyRepoEnabled.setChecked(false);
// Disable in realm db
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder().name("ReposList.realm").encryptionKey(MainApplication.getINSTANCE().getKey()).allowQueriesOnUiThread(true).allowWritesOnUiThread(true).directory(MainApplication.getINSTANCE().getDataDirWithPath("realms")).schemaVersion(1).build();
Realm realm = Realm.getInstance(realmConfiguration);
realm.executeTransaction(realm2 -> {
ReposList repoRealmResults = realm2.where(ReposList.class).equalTo("id", "androidacy_repo").findFirst();
assert repoRealmResults != null;
repoRealmResults.setEnabled(false);
realm2.insertOrUpdate(repoRealmResults);
realm2.close();
});
// Disable in room db
db.reposListDao().setEnabled("androidacy_repo", false);
return false;
});
} else {
// get if androidacy repo is enabled from realm db
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder().name("ReposList.realm").encryptionKey(MainApplication.getINSTANCE().getKey()).allowQueriesOnUiThread(true).allowWritesOnUiThread(true).directory(MainApplication.getINSTANCE().getDataDirWithPath("realms")).schemaVersion(1).build();
Realm realm = Realm.getInstance(realmConfiguration);
ReposList repoRealmResults = realm.where(ReposList.class).equalTo("id", "androidacy_repo").findFirst();
if (repoRealmResults == null) {
throw new IllegalStateException("Androidacy repo not found in realm db");
}
boolean androidacyRepoEnabledPref = repoRealmResults.isEnabled();
// get if androidacy repo is enabled from room db
ReposList repoRealmResults = db.reposListDao().getById("androidacy_repo");
boolean androidacyRepoEnabledPref = repoRealmResults.getEnabled();
// set the switch to the current state
androidacyRepoEnabled.setChecked(androidacyRepoEnabledPref);
// add a click listener to the switch
androidacyRepoEnabled.setOnPreferenceClickListener(preference -> {
boolean enabled = androidacyRepoEnabled.isChecked();
// save the new state
realm.executeTransaction(realm2 -> {
ReposList repoRealmResults1 = realm2.where(ReposList.class).equalTo("id", "androidacy_repo").findFirst();
repoRealmResults1.setEnabled(enabled);
});
db.reposListDao().setEnabled("androidacy_repo", enabled);
return true;
});
if (androidacyRepoEnabledPref) {

@ -25,8 +25,9 @@ class ModuleListCache (
var mmtReborn: Boolean,
var repoId: String,
var lastUpdate: Long,
val name: String,
var safe: Boolean
var name: String,
var safe: Boolean,
var stats: Int
) {
// functions:
// getAll(): List<ModuleListCache>

@ -69,7 +69,7 @@ interface ModuleListCacheDao {
fun getByCodename(codename: String): ModuleListCache
@Insert(entity = ModuleListCache::class, onConflict = OnConflictStrategy.REPLACE)
fun insert(codename: String, version: String, versionCode: Int, author: String, description: String, minApi: Int, maxApi: Int, minMagisk: Int, needRamdisk: Boolean, support: String, donate: String, config: String, changeBoot: Boolean, mmtReborn: Boolean, repoId: String, lastUpdate: Long, safe: Boolean, name: String)
fun insert(codename: String, version: String, versionCode: Int, author: String, description: String, minApi: Int, maxApi: Int, minMagisk: Int, needRamdisk: Boolean, support: String, donate: String, config: String, changeBoot: Boolean, mmtReborn: Boolean, repoId: String, lastUpdate: Long, safe: Boolean, name: String, stats: Int)
@Query("UPDATE modulelistcache SET version = :version WHERE codename = :codename")
fun setVersion(codename: String, version: String)
@ -122,6 +122,9 @@ interface ModuleListCacheDao {
@Query("UPDATE modulelistcache SET name = :name WHERE codename = :codename")
fun setName(codename: String, name: String)
@Query("UPDATE modulelistcache SET stats = :stats WHERE codename = :codename")
fun setStats(codename: String, stats: Int)
@Query("DELETE FROM modulelistcache WHERE codename = :codename")
fun delete(codename: String)
@ -182,10 +185,21 @@ interface ModuleListCacheDao {
@Query("SELECT name FROM modulelistcache WHERE codename = :codename")
fun getName(codename: String): String
@Query("SELECT stats FROM modulelistcache WHERE codename = :codename")
fun getStats(codename: String): Int
@Query("SELECT * FROM modulelistcache WHERE codename = :codename")
fun get(codename: String): ModuleListCache
// exists
@Query("SELECT EXISTS(SELECT * FROM modulelistcache WHERE codename = :codename)")
fun exists(codename: String): Boolean
// asJson by repoId
@Query("SELECT * FROM modulelistcache WHERE repoId = :repoId")
fun asJson(repoId: String): List<ModuleListCache>
// delete by repoId
@Query("DELETE FROM modulelistcache WHERE repoId = :repoId")
fun deleteByRepoId(repoId: String)
}

@ -11,7 +11,7 @@ import androidx.room.Query
@Dao
interface ReposListDao {
// contains
// id (string, primary), url (string), enabled (boolean), donate (string), support (string), submitMoulde (string), lastUpdate (bigint), name (string) and website (string)
// id (string, primary), url (string), enabled (boolean), donate (string), support (string), submitModule (string), lastUpdate (bigint), name (string) and website (string)
// functions:
// getAll(): List<ReposList>
@ -30,7 +30,7 @@ interface ReposListDao {
fun insert(id: String, url: String, enabled: Boolean, donate: String?, support: String?, submitModule: String?, lastUpdate: Long, name: String, website: String?)
@Query("UPDATE ReposList SET url = :url, enabled = :enabled, donate = :donate, support = :support, submitModule = :submitModule, lastUpdate = :lastUpdate, name = :name, website = :website WHERE id = :id")
fun update(id: String, url: String, enabled: Boolean, donate: String, support: String, submitModule: String, lastUpdate: Long, name: String, website: String)
fun update(id: String, url: String?, enabled: Boolean?, donate: String?, support: String?, submitModule: String?, lastUpdate: Long?, name: String?, website: String?)
@Query("DELETE FROM ReposList WHERE id = :id")
fun delete(id: String)

Loading…
Cancel
Save