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

@ -26,6 +26,7 @@ import androidx.work.WorkManager
import androidx.work.Worker import androidx.work.Worker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import com.fox2code.mmm.AppUpdateManager import com.fox2code.mmm.AppUpdateManager
import com.fox2code.mmm.BuildConfig
import com.fox2code.mmm.MainActivity import com.fox2code.mmm.MainActivity
import com.fox2code.mmm.MainApplication import com.fox2code.mmm.MainApplication
import com.fox2code.mmm.R import com.fox2code.mmm.R
@ -53,7 +54,7 @@ class BackgroundUpdateChecker(context: Context, workerParams: WorkerParameters)
private const val NOTFIICATION_GROUP = "updates" private const val NOTFIICATION_GROUP = "updates"
private const val NOTIFICATION_CHANNEL_ID_APP = "background_update_app" private const val NOTIFICATION_CHANNEL_ID_APP = "background_update_app"
val lock = 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_ID_ONGOING = 2
private const val NOTIFICATION_CHANNEL_ID_ONGOING = "mmm_background_update" private const val NOTIFICATION_CHANNEL_ID_ONGOING = "mmm_background_update"
private const val NOTIFICATION_ID_APP = 3 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) { fun doCheck(context: Context) {
// first, check if the user has enabled background update checking // first, check if the user has enabled background update checking
if (!MainApplication.getSharedPreferences("mmm")!! if (!MainApplication.getSharedPreferences("mmm")!!
@ -280,14 +281,20 @@ class BackgroundUpdateChecker(context: Context, workerParams: WorkerParameters)
if (MainApplication.getSharedPreferences("mmm")!! if (MainApplication.getSharedPreferences("mmm")!!
.getBoolean("pref_background_update_check_app", false) .getBoolean("pref_background_update_check_app", false)
) { ) {
try {
val shouldUpdate = AppUpdateManager.appUpdateManager.checkUpdate(true) // don't check if app is from play store or fdroid
if (shouldUpdate) { if (BuildConfig.FLAVOR != "play" || BuildConfig.FLAVOR != "fdroid") {
Timber.d("Found app update") try {
postNotificationForAppUpdate(context) 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 // remove checking notification

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

@ -4,12 +4,11 @@
package com.fox2code.mmm.repo package com.fox2code.mmm.repo
import androidx.room.Room
import com.fox2code.mmm.MainApplication import com.fox2code.mmm.MainApplication
import com.fox2code.mmm.utils.io.net.Http.Companion.doHttpGet import com.fox2code.mmm.utils.io.net.Http.Companion.doHttpGet
import com.fox2code.mmm.utils.realm.ModuleListCache import com.fox2code.mmm.utils.room.ModuleListCacheDatabase
import com.fox2code.mmm.utils.realm.ReposList import com.fox2code.mmm.utils.room.ReposListDatabase
import io.realm.Realm
import io.realm.RealmConfiguration
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import timber.log.Timber 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 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 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) Timber.d("Fetching index from cache for %s", repoData.preferenceId)
val cacheRoot = // now the above but for room
MainApplication.INSTANCE!!.getDataDirWithPath("realms/repos/" + repoData.preferenceId) val db = Room.databaseBuilder(
val realmConfiguration = RealmConfiguration.Builder().name("ModuleListCache.realm") MainApplication.INSTANCE!!,
.encryptionKey(MainApplication.INSTANCE!!.key).schemaVersion(1) ModuleListCacheDatabase::class.java,
.deleteRealmIfMigrationNeeded().allowWritesOnUiThread(true) "ModuleListCache.db"
.allowQueriesOnUiThread(true).directory(cacheRoot).build() ).allowMainThreadQueries().build()
val realm = Realm.getInstance(realmConfiguration) val moduleListCacheDao = db.moduleListCacheDao()
val results = realm.where( // now we have the cache, we need to check if it's up to date
ModuleListCache::class.java val results = moduleListCacheDao.getByRepoId(repoData.preferenceId!!)
).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)
toUpdate = emptyList() toUpdate = emptyList()
toApply = HashSet() toApply = HashSet()
for (moduleListCache in results) { for (moduleListCache in results) {
@ -83,14 +74,11 @@ class RepoUpdater(repoData2: RepoData) {
// apply the toApply list to the toUpdate list // apply the toApply list to the toUpdate list
try { try {
val jsonObject = JSONObject() val jsonObject = JSONObject()
jsonObject.put("modules", JSONArray(results.asJSON())) jsonObject.put("modules", JSONArray(results))
toUpdate = repoData.populate(jsonObject) toUpdate = repoData.populate(jsonObject)
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e) Timber.e(e)
} }
// close realm
realm.close()
realm2.close()
// Since we reuse instances this should work // Since we reuse instances this should work
toApply = HashSet(repoData.moduleHashMap.values) toApply = HashSet(repoData.moduleHashMap.values)
(toApply as HashSet<RepoModule>).removeAll(toUpdate!!.toSet()) (toApply as HashSet<RepoModule>).removeAll(toUpdate!!.toSet())
@ -141,14 +129,13 @@ class RepoUpdater(repoData2: RepoData) {
if (indexRaw != null) { if (indexRaw != null) {
try { 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 // 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: // props avail:
val cacheRoot = val db = Room.databaseBuilder(
MainApplication.INSTANCE!!.getDataDirWithPath("realms/repos/" + repoData.preferenceId) MainApplication.INSTANCE!!,
val realmConfiguration = RealmConfiguration.Builder().name("ModuleListCache.realm") ModuleListCacheDatabase::class.java,
.encryptionKey(MainApplication.INSTANCE!!.key).schemaVersion(1) "ModuleListCache.db"
.deleteRealmIfMigrationNeeded().allowWritesOnUiThread(true) ).allowMainThreadQueries().build()
.allowQueriesOnUiThread(true).directory(cacheRoot).build()
// array with module info default values // array with module info default values
// supported properties for a module // supported properties for a module
//id=<string> //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 // get modules from "modules" key. This is a JSONArray so we need to convert it to a JSONObject
modules.getJSONArray("modules") modules.getJSONArray("modules")
} }
val realm = Realm.getInstance(realmConfiguration) val moduleListCacheDao = db.moduleListCacheDao()
// drop old data moduleListCacheDao.deleteByRepoId(repoData.preferenceId!!)
if (realm.isInTransaction) {
realm.commitTransaction()
}
realm.beginTransaction()
realm.where(ModuleListCache::class.java).equalTo("repoId", repoData.preferenceId)
.findAll()
.deleteAllFromRealm()
realm.commitTransaction()
// iterate over modules. pls don't hate me for this, its ugly but it works // iterate over modules. pls don't hate me for this, its ugly but it works
for (n in 0 until modulesArray.length()) { for (n in 0 until modulesArray.length()) {
// get module // get module
@ -296,10 +275,6 @@ class RepoUpdater(repoData2: RepoData) {
} }
// get module repo id // get module repo id
val repoId = repoData.preferenceId 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 // get safe property. for now, only supported by androidacy repo and they use "vt_status" key
var safe = false var safe = false
if (repoData.name == "Androidacy Modules Repo") { if (repoData.name == "Androidacy Modules Repo") {
@ -309,81 +284,22 @@ class RepoUpdater(repoData2: RepoData) {
} }
} }
} }
// insert module to realm 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 ?: "")
// 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()
} catch (ignored: Exception) { } catch (ignored: Exception) {
} }
} }
realm.close()
} catch (ignored: Exception) { } catch (ignored: Exception) {
} }
indexRaw = null 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 // set lastUpdate
realm2.executeTransaction { r: Realm -> val db = Room.databaseBuilder(
val repoListCache = MainApplication.INSTANCE!!.applicationContext,
r.where(ReposList::class.java).equalTo("id", repoData.preferenceId).findFirst() ReposListDatabase::class.java,
if (repoListCache != null) { "ReposList.db"
success.set(true) ).allowMainThreadQueries().build()
// get unix timestamp of current time val repoListDao = db.reposListDao()
val currentTime = (System.currentTimeMillis() / 1000).toInt() repoListDao.setLastUpdate(repoData.preferenceId!!, System.currentTimeMillis())
Timber.d( db.close()
"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()
} else { } else {
success.set(true) // assume we're reading from cache. this may be unsafe but it's better than nothing 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.PreferenceManager;
import androidx.preference.SwitchPreferenceCompat; import androidx.preference.SwitchPreferenceCompat;
import androidx.preference.TwoStatePreference; import androidx.preference.TwoStatePreference;
import androidx.room.Room;
import androidx.security.crypto.EncryptedSharedPreferences; import androidx.security.crypto.EncryptedSharedPreferences;
import androidx.security.crypto.MasterKey; 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.IntentHelper;
import com.fox2code.mmm.utils.ProcessHelper; import com.fox2code.mmm.utils.ProcessHelper;
import com.fox2code.mmm.utils.io.net.Http; 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.mmm.utils.sentry.SentryMain;
import com.fox2code.rosettax.LanguageActivity; import com.fox2code.rosettax.LanguageActivity;
import com.fox2code.rosettax.LanguageSwitcher; import com.fox2code.rosettax.LanguageSwitcher;
@ -106,9 +108,6 @@ import java.util.Objects;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import io.realm.Realm;
import io.realm.RealmConfiguration;
import io.realm.RealmResults;
import timber.log.Timber; import timber.log.Timber;
public class SettingsActivity extends FoxActivity implements LanguageActivity { public class SettingsActivity extends FoxActivity implements LanguageActivity {
@ -1071,28 +1070,13 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
return true; return true;
}); });
} }
// Get magisk_alt_repo enabled state from realm db // Get magisk_alt_repo enabled state from room reposlist 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(); ReposListDatabase db = Room.databaseBuilder(requireContext(), ReposListDatabase.class, "ReposList.db").allowMainThreadQueries().build();
Realm realm1 = Realm.getInstance(realmConfig); // add listener to magisk_alt_repo_enabled switch to update room db
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
Preference magiskAltRepoEnabled = Objects.requireNonNull(findPreference("pref_magisk_alt_repo_enabled")); Preference magiskAltRepoEnabled = Objects.requireNonNull(findPreference("pref_magisk_alt_repo_enabled"));
magiskAltRepoEnabled.setOnPreferenceChangeListener((preference, newValue) -> { magiskAltRepoEnabled.setOnPreferenceChangeListener((preference, newValue) -> {
// Update realm db // Update room db
Realm realm = Realm.getInstance(realmConfig); db.reposListDao().setEnabled("magisk_alt_repo", Boolean.parseBoolean(String.valueOf(newValue)));
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");
}
});
return true; return true;
}); });
// Disable toggling the pref_androidacy_repo_enabled on builds without an // Disable toggling the pref_androidacy_repo_enabled on builds without an
@ -1107,37 +1091,21 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
}).show(); }).show();
// Revert the switch to off // Revert the switch to off
androidacyRepoEnabled.setChecked(false); androidacyRepoEnabled.setChecked(false);
// Disable in realm db // Disable in room 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(); db.reposListDao().setEnabled("androidacy_repo", false);
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();
});
return false; return false;
}); });
} else { } else {
// get if androidacy repo is enabled from realm db // get if androidacy repo is enabled from room 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(); ReposList repoRealmResults = db.reposListDao().getById("androidacy_repo");
Realm realm = Realm.getInstance(realmConfiguration); boolean androidacyRepoEnabledPref = repoRealmResults.getEnabled();
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();
// set the switch to the current state // set the switch to the current state
androidacyRepoEnabled.setChecked(androidacyRepoEnabledPref); androidacyRepoEnabled.setChecked(androidacyRepoEnabledPref);
// add a click listener to the switch // add a click listener to the switch
androidacyRepoEnabled.setOnPreferenceClickListener(preference -> { androidacyRepoEnabled.setOnPreferenceClickListener(preference -> {
boolean enabled = androidacyRepoEnabled.isChecked(); boolean enabled = androidacyRepoEnabled.isChecked();
// save the new state // save the new state
realm.executeTransaction(realm2 -> { db.reposListDao().setEnabled("androidacy_repo", enabled);
ReposList repoRealmResults1 = realm2.where(ReposList.class).equalTo("id", "androidacy_repo").findFirst();
repoRealmResults1.setEnabled(enabled);
});
return true; return true;
}); });
if (androidacyRepoEnabledPref) { if (androidacyRepoEnabledPref) {

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

@ -69,7 +69,7 @@ interface ModuleListCacheDao {
fun getByCodename(codename: String): ModuleListCache fun getByCodename(codename: String): ModuleListCache
@Insert(entity = ModuleListCache::class, onConflict = OnConflictStrategy.REPLACE) @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") @Query("UPDATE modulelistcache SET version = :version WHERE codename = :codename")
fun setVersion(codename: String, version: String) fun setVersion(codename: String, version: String)
@ -122,6 +122,9 @@ interface ModuleListCacheDao {
@Query("UPDATE modulelistcache SET name = :name WHERE codename = :codename") @Query("UPDATE modulelistcache SET name = :name WHERE codename = :codename")
fun setName(codename: String, name: String) 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") @Query("DELETE FROM modulelistcache WHERE codename = :codename")
fun delete(codename: String) fun delete(codename: String)
@ -182,10 +185,21 @@ interface ModuleListCacheDao {
@Query("SELECT name FROM modulelistcache WHERE codename = :codename") @Query("SELECT name FROM modulelistcache WHERE codename = :codename")
fun getName(codename: String): String 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") @Query("SELECT * FROM modulelistcache WHERE codename = :codename")
fun get(codename: String): ModuleListCache fun get(codename: String): ModuleListCache
// exists // exists
@Query("SELECT EXISTS(SELECT * FROM modulelistcache WHERE codename = :codename)") @Query("SELECT EXISTS(SELECT * FROM modulelistcache WHERE codename = :codename)")
fun exists(codename: String): Boolean 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 @Dao
interface ReposListDao { interface ReposListDao {
// contains // 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: // functions:
// getAll(): List<ReposList> // 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?) 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") @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") @Query("DELETE FROM ReposList WHERE id = :id")
fun delete(id: String) fun delete(id: String)

Loading…
Cancel
Save