migrate to room db pt1/?

WARNING: does not compile as-is. tests are expected to fail.

[skip actions]

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

@ -19,8 +19,6 @@ plugins {
id("io.sentry.android.gradle")
}
// apply realm-android
apply(plugin = "realm-android")
val hasSentryConfig = File(rootProject.projectDir, "sentry.properties").exists()
android {
// functions to get git info: gitCommitHash, gitBranch, gitRemote
@ -527,6 +525,9 @@ dependencies {
// yes
implementation("com.github.fingerprintjs:fingerprint-android:2.0.0")
// encryption for room
implementation("net.zetetic:android-database-sqlcipher:4.5.4")
// room
implementation("androidx.room:room-runtime:2.5.1")

@ -195,6 +195,9 @@
-keepclassmembers class org.apache.commons.compress.archivers.zip.* { *; }
-keep,includedescriptorclasses class net.sqlcipher.** { *; }
-keep,includedescriptorclasses interface net.sqlcipher.** { *; }
# dontwarn
-dontwarn android.os.SystemProperties
-dontwarn android.view.ThreadedRenderer

@ -28,6 +28,7 @@ import androidx.appcompat.widget.SearchView
import androidx.cardview.widget.CardView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.room.Room
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener
import com.fox2code.foxcompat.app.FoxActivity
@ -54,11 +55,9 @@ import com.fox2code.mmm.utils.RuntimeUtils
import com.fox2code.mmm.utils.SyncManager
import com.fox2code.mmm.utils.io.net.Http.Companion.cleanDnsCache
import com.fox2code.mmm.utils.io.net.Http.Companion.hasWebView
import com.fox2code.mmm.utils.realm.ReposList
import com.fox2code.mmm.utils.room.ReposListDatabase
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.progressindicator.LinearProgressIndicator
import io.realm.Realm
import io.realm.RealmConfiguration
import org.matomo.sdk.extra.TrackHelper
import timber.log.Timber
import java.sql.Timestamp
@ -104,25 +103,24 @@ class MainActivity : FoxActivity(), OnRefreshListener, SearchView.OnQueryTextLis
super.onCreate(savedInstanceState)
TrackHelper.track().screen(this).with(MainApplication.INSTANCE!!.tracker)
// track enabled repos
val realmConfig = RealmConfiguration.Builder().name("ReposList.realm")
.encryptionKey(MainApplication.INSTANCE!!.key)
.directory(MainApplication.INSTANCE!!.getDataDirWithPath("realms")).schemaVersion(1)
.allowQueriesOnUiThread(true).allowWritesOnUiThread(true).build()
val realm = Realm.getInstance(realmConfig)
val db = Room.databaseBuilder(
applicationContext,
ReposListDatabase::class.java,
"reposlist.db"
).build()
val repoDao = db.reposListDao()
val repos = repoDao.getAll()
val enabledRepos = StringBuilder()
realm.executeTransaction { r: Realm ->
for (r2 in r.where(
ReposList::class.java
).equalTo("enabled", true).findAll()) {
enabledRepos.append(r2.url).append(":").append(r2.name).append(",")
for (repo in repos) {
if (repo.enabled) {
enabledRepos.append(repo.url).append(", ")
}
}
if (enabledRepos.isNotEmpty()) {
enabledRepos.setLength(enabledRepos.length - 1)
enabledRepos.delete(enabledRepos.length - 2, enabledRepos.length)
TrackHelper.track().event("Enabled Repos", enabledRepos.toString())
.with(MainApplication.INSTANCE!!.tracker)
}
TrackHelper.track().event("enabled_repos", enabledRepos.toString())
.with(MainApplication.INSTANCE!!.tracker)
realm.close()
// hide this behind a buildconfig flag for now, but crash the app if it's not an official build and not debug
if (BuildConfig.ENABLE_PROTECTION && !MainApplication.o && !BuildConfig.DEBUG) {
throw RuntimeException("This is not an official build of AMM")

@ -18,10 +18,13 @@ import android.webkit.CookieManager
import android.widget.CompoundButton
import android.widget.Toast
import androidx.fragment.app.FragmentActivity
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
import com.fox2code.rosettax.LanguageSwitcher
import com.google.android.material.bottomnavigation.BottomNavigationItemView
@ -254,7 +257,7 @@ class SetupActivity : FoxActivity(), LanguageActivity {
r.close()
Timber.d("Realm transaction committed")
}
editor.putString("last_shown_setup", "v2")
editor.putString("last_shown_setup", "v3")
// Commit the changes
editor.commit()
// sleep to allow the realm transaction to finish
@ -347,7 +350,18 @@ class SetupActivity : FoxActivity(), LanguageActivity {
// creates the room database
private fun createDatabases() {
val startTime = System.currentTimeMillis()
val appContext = MainApplication.INSTANCE!!.applicationContext
Room.databaseBuilder(appContext, ReposListDatabase::class.java, "reposlist.db")
.createFromAsset("assets/reposlist.db")
.fallbackToDestructiveMigration()
.build()
// same for modulelistcache
Room.databaseBuilder(appContext, ModuleListCacheDatabase::class.java, "modulelistcache.db")
.createFromAsset("assets/modulelistcache.db")
.fallbackToDestructiveMigration()
.build()
Timber.d("Databases created in %s ms", System.currentTimeMillis() - startTime)
}
private fun createFiles() {

@ -374,7 +374,7 @@ class BackgroundUpdateChecker(context: Context, workerParams: WorkerParameters)
fun onMainActivityCreate(context: Context) {
// Refuse to run if first_launch pref is not false
if (MainApplication.getSharedPreferences("mmm")!!
.getString("last_shown_setup", null) != "v2"
.getString("last_shown_setup", null) != "v3"
) return
// create notification channel group
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

@ -7,25 +7,24 @@
package com.fox2code.mmm.manager
import android.content.SharedPreferences
import androidx.room.Room
import com.fox2code.mmm.BuildConfig
import com.fox2code.mmm.MainApplication
import com.fox2code.mmm.installer.InstallerInitializer.Companion.peekModulesPath
import com.fox2code.mmm.utils.SyncManager
import com.fox2code.mmm.utils.io.PropUtils
import com.fox2code.mmm.utils.realm.ModuleListCache
import com.fox2code.mmm.utils.room.ModuleListCache
import com.fox2code.mmm.utils.room.ModuleListCacheDao
import com.fox2code.mmm.utils.room.ModuleListCacheDatabase
import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.io.SuFile
import com.topjohnwu.superuser.io.SuFileInputStream
import io.realm.Realm
import io.realm.RealmConfiguration
import org.matomo.sdk.extra.TrackHelper
import timber.log.Timber
import java.io.BufferedReader
import java.io.File
import java.io.IOException
import java.io.InputStreamReader
import java.nio.charset.StandardCharsets
import java.util.Objects
class ModuleManager private constructor() : SyncManager() {
private val moduleInfos: HashMap<String, LocalModuleInfo> = HashMap()
@ -33,9 +32,9 @@ class ModuleManager private constructor() : SyncManager() {
private var updatableModuleCount = 0
override fun scanInternal(updateListener: UpdateListener) {
// if last_shown_setup is not "v2", then refuse to continue
// if last_shown_setup is not "v3", then refuse to continue
if (MainApplication.getSharedPreferences("mmm")!!
.getString("last_shown_setup", "") != "v2"
.getString("last_shown_setup", "") != "v3"
) {
return
}
@ -65,60 +64,36 @@ class ModuleManager private constructor() : SyncManager() {
for (module in modules) {
if (!SuFile("/data/adb/modules/$module").isDirectory) continue // Ignore non directory files inside modules folder
var moduleInfo = moduleInfos[module]
// next, merge the module info with a record from ModuleListCache if it exists
var realmConfiguration: RealmConfiguration?
// get all dirs under the realms/repos/ dir under app's data dir
val cacheRoot =
File(MainApplication.INSTANCE!!.getDataDirWithPath("realms/repos/").toURI())
var moduleListCache: ModuleListCache?
for (dir in Objects.requireNonNull<Array<File>>(cacheRoot.listFiles())) {
if (dir.isDirectory) {
// if the dir name matches the module name, use it as the cache dir
val tempCacheRoot = File(dir.toString())
Timber.d("Looking for cache in %s", tempCacheRoot)
realmConfiguration =
RealmConfiguration.Builder().name("ModuleListCache.realm")
.encryptionKey(MainApplication.INSTANCE!!.key).schemaVersion(1)
.deleteRealmIfMigrationNeeded().allowWritesOnUiThread(true)
.allowQueriesOnUiThread(true).directory(tempCacheRoot).build()
val realm = Realm.getInstance(realmConfiguration!!)
Timber.d(
"Looking for cache for %s out of %d", module, realm.where(
ModuleListCache::class.java
).count()
)
moduleListCache =
realm.where(ModuleListCache::class.java).equalTo("codename", module)
.findFirst()
Timber.d("Found cache for %s", module)
// get module info from cache
if (moduleInfo == null) {
moduleInfo = LocalModuleInfo(module)
}
if (moduleListCache != null) {
moduleInfo.name =
if (moduleListCache.name != "") moduleListCache.name else module
moduleInfo.description =
if (moduleListCache.description != "") moduleListCache.description else moduleInfo.description
moduleInfo.author =
if (moduleListCache.author != "") moduleListCache.author else moduleInfo.author
moduleInfo.safe = moduleListCache.isSafe == true
moduleInfo.support =
if (moduleListCache.support != "") moduleListCache.support else null
moduleInfo.donate =
if (moduleListCache.donate != "") moduleListCache.donate else null
moduleInfo.flags = moduleInfo.flags or FLAG_MM_REMOTE_MODULE
moduleInfos[module] = moduleInfo
}
realm.close()
break
}
}
// next, merge the module info with a record from ModuleListCache room db if it exists
// initialize modulelistcache db
// DO NOT USE REALM ANYMORE
val db = Room.databaseBuilder(
MainApplication.INSTANCE!!,
ModuleListCacheDatabase::class.java,
"ModuleListCache"
).build()
// get module info from cache
val moduleListCacheDao: ModuleListCacheDao = db.moduleListCacheDao()
Timber.d("Found cache for %s", module)
// get module info from cache
if (moduleInfo == null) {
moduleInfo = LocalModuleInfo(module)
}
if (moduleListCacheDao.exists(module)) {
val moduleListCache: ModuleListCache = moduleListCacheDao.getByCodename(module)
moduleInfo.name =
if (moduleListCache.name != "") moduleListCache.name else module
moduleInfo.description =
if (moduleListCache.description != "") moduleListCache.description else moduleInfo.description
moduleInfo.author =
if (moduleListCache.author != "") moduleListCache.author else moduleInfo.author
moduleInfo.safe = moduleListCache.safe == true
moduleInfo.support =
if (moduleListCache.support != "") moduleListCache.support else null
moduleInfo.donate =
if (moduleListCache.donate != "") moduleListCache.donate else null
moduleInfo.flags = moduleInfo.flags or FLAG_MM_REMOTE_MODULE
moduleInfos[module] = moduleInfo
// This should not really happen, but let's handles theses cases anyway
moduleInfo.flags = moduleInfo.flags or ModuleInfo.FLAG_MODULE_UPDATING_ONLY
}
moduleInfo.flags = moduleInfo.flags and FLAGS_RESET_UPDATE.inv()
if (SuFile("/data/adb/modules/$module/disable").exists()) {
@ -131,8 +106,7 @@ class ModuleManager private constructor() : SyncManager() {
moduleInfo.flags = moduleInfo.flags or ModuleInfo.FLAG_MODULE_UNINSTALLING
}
if (firstScan && !needFallback && SuFile(
modulesPath,
module
modulesPath, module
).exists() || bootPrefs.getBoolean("module_" + moduleInfo.id + "_active", false)
) {
moduleInfo.flags = moduleInfo.flags or ModuleInfo.FLAG_MODULE_ACTIVE
@ -152,9 +126,7 @@ class ModuleManager private constructor() : SyncManager() {
}
try {
PropUtils.readProperties(
moduleInfo,
"/data/adb/modules/$module/module.prop",
true
moduleInfo, "/data/adb/modules/$module/module.prop", true
)
} catch (e: Exception) {
if (BuildConfig.DEBUG) Timber.d(e)
@ -186,9 +158,7 @@ class ModuleManager private constructor() : SyncManager() {
moduleInfo.flags = moduleInfo.flags or ModuleInfo.FLAG_MODULE_UPDATING
try {
PropUtils.readProperties(
moduleInfo,
"/data/adb/modules_update/$module/module.prop",
true
moduleInfo, "/data/adb/modules_update/$module/module.prop", true
)
} catch (e: Exception) {
if (BuildConfig.DEBUG) Timber.d(e)

@ -3,23 +3,21 @@
*/
package com.fox2code.mmm.repo
import androidx.room.Room
import com.fox2code.mmm.MainApplication
import com.fox2code.mmm.MainApplication.Companion.INSTANCE
import com.fox2code.mmm.MainApplication.Companion.getSharedPreferences
import com.fox2code.mmm.utils.io.Hashes.Companion.hashSha256
import com.fox2code.mmm.utils.io.PropUtils.Companion.isNullString
import com.fox2code.mmm.utils.io.net.Http.Companion.doHttpGet
import com.fox2code.mmm.utils.realm.ReposList
import io.realm.Realm
import io.realm.RealmConfiguration
import com.fox2code.mmm.utils.room.ReposListDatabase
import org.json.JSONObject
import timber.log.Timber
import java.nio.charset.StandardCharsets
@Suppress("UNUSED_PARAMETER", "MemberVisibilityCanBePrivate")
class CustomRepoManager internal constructor(
mainApplication: MainApplication?,
private val repoManager: RepoManager
mainApplication: MainApplication?, private val repoManager: RepoManager
) {
private val customRepos: Array<String?> = arrayOfNulls(MAX_CUSTOM_REPOS)
@ -31,34 +29,24 @@ class CustomRepoManager internal constructor(
init {
repoCount = 0
// refuse to load if setup is not complete
if (getSharedPreferences("mmm")!!.getString("last_shown_setup", "") != "") {
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)
if (realm.isInTransaction) {
realm.commitTransaction()
}
if (getSharedPreferences("mmm")!!.getString("last_shown_setup", "") == "v3") {
val i = 0
val lastFilled = intArrayOf(0)
realm.executeTransaction { realm1: Realm ->
// find all repos that are not built-in
for (reposList in realm1.where(ReposList::class.java)
.notEqualTo("id", "androidacy_repo").and().notEqualTo("id", "magisk_alt_repo")
.and()
.notEqualTo("id", "magisk_official_repo").findAll()) {
val repo = reposList.url
if (!isNullString(repo) && !RepoManager.isBuiltInRepo(repo)) {
lastFilled[0] = i
val index = if (AUTO_RECOMPILE) repoCount else i
customRepos[index] = repo
repoCount++
(repoManager.addOrGet(repo) as CustomRepoData).override =
"custom_repo_$index"
}
// now the same as above but for room database
val applicationContext = mainApplication!!.applicationContext
val db = Room.databaseBuilder(
applicationContext, ReposListDatabase::class.java, "reposlist.db"
).build()
val reposListDao = db.reposListDao()
val reposListList = reposListDao.getAll()
for (reposList in reposListList) {
val repo = reposList.url
if (!isNullString(repo) && !RepoManager.isBuiltInRepo(repo)) {
lastFilled[0] = i
val index = if (AUTO_RECOMPILE) repoCount else i
customRepos[index] = repo
repoCount++
(repoManager.addOrGet(repo) as CustomRepoData).override = "custom_repo_$index"
}
}
}
@ -119,29 +107,13 @@ class CustomRepoManager internal constructor(
null
}
val id = "repo_" + hashSha256(repo.toByteArray(StandardCharsets.UTF_8))
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)
realm.executeTransaction { realm1: Realm ->
// find the matching entry for repo_0, repo_1, etc.
var reposList =
realm1.where(ReposList::class.java).equalTo("id", id).findFirst()
if (reposList == null) {
reposList = realm1.createObject(ReposList::class.java, id)
}
reposList!!.url = repo
reposList.name = name
reposList.website = website
reposList.support = support
reposList.donate = donate
reposList.submitModule = submitModule
reposList.isEnabled = true
// save the object
realm1.copyToRealmOrUpdate(reposList)
}
// now the same as above but for room database
val applicationContext = INSTANCE!!.applicationContext
val db = Room.databaseBuilder(
applicationContext, ReposListDatabase::class.java, "reposlist.db"
).build()
val reposListDao = db.reposListDao()
reposListDao.insert(id, repo, true, donate, support, submitModule, 0, name, website)
repoCount++
dirty = true
val customRepoData = repoManager.addOrGet(repo) as CustomRepoData
@ -155,7 +127,6 @@ class CustomRepoManager internal constructor(
// Set the enabled state to true
customRepoData.isEnabled = true
customRepoData.updateEnabledState()
realm.close()
return customRepoData
}

@ -56,7 +56,7 @@ class RepoManager private constructor(mainApplication: MainApplication) : SyncMa
repoData = LinkedHashMap()
modules = HashMap()
// refuse to load if setup is not complete
if (getSharedPreferences("mmm")!!.getString("last_shown_setup", "") != "") {
if (getSharedPreferences("mmm")!!.getString("last_shown_setup", "") == "v3") {
// We do not have repo list config yet.
androidacyRepoData = addAndroidacyRepoData()
val altRepo = addRepoData(MAGISK_ALT_REPO, "Magisk Modules Alt Repo")
@ -82,8 +82,8 @@ class RepoManager private constructor(mainApplication: MainApplication) : SyncMa
}
private fun populateDefaultCache(repoData: RepoData?) {
// if last_shown_setup is not "v2", them=n refuse to continue
if (getSharedPreferences("mmm")!!.getString("last_shown_setup", "") != "v2") {
// if last_shown_setup is not "v3", them=n refuse to continue
if (getSharedPreferences("mmm")!!.getString("last_shown_setup", "") != "v3") {
return
}
// make sure repodata is not null

@ -154,7 +154,7 @@ class RuntimeUtils {
if (BuildConfig.DEBUG) Timber.i("Checking if we need to run setup")
// Check if context is the first launch using prefs and if doSetupRestarting was passed in the intent
val prefs = MainApplication.getSharedPreferences("mmm")!!
var firstLaunch = prefs.getString("last_shown_setup", null) != "v2"
var firstLaunch = prefs.getString("last_shown_setup", null) != "v3"
// First launch
// context is intentionally separate from the above if statement, because it needs to be checked even if the first launch check is true due to some weird edge cases
if (activity.intent.getBooleanExtra("doSetupRestarting", false)) {

@ -1,317 +0,0 @@
/*
* Copyright (c) 2023 to present Androidacy and contributors. Names, logos, icons, and the Androidacy name are all trademarks of Androidacy and may not be used without license. See LICENSE for more information.
*/
package com.fox2code.mmm.utils.realm;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import io.realm.Realm;
import io.realm.RealmObject;
import io.realm.RealmResults;
import io.realm.annotations.PrimaryKey;
import io.realm.annotations.Required;
import timber.log.Timber;
@SuppressWarnings("unused")
public class ModuleListCache extends RealmObject {
// for compatibility, only id is required
@PrimaryKey
@Required
private String codename;
private String name;
private String version;
private int versionCode;
private String author;
private String description;
private int minApi;
private int maxApi;
private int minMagisk;
private boolean needRamdisk;
private String support;
private String donate;
private String config;
private boolean changeBoot;
private boolean mmtReborn;
private String repoId;
private boolean installed;
private int installedVersionCode;
private int lastUpdate;
// androidacy specific, may be added by other repos
private boolean safe;
private int stats;
public ModuleListCache(String codename, String name, String version, int versionCode, String author, String description, int minApi, int maxApi, int minMagisk, boolean needRamdisk, String support, String donate, String config, boolean changeBoot, boolean mmtReborn, String repoId, boolean installed, int installedVersionCode, int lastUpdate, int stats) {
this.codename = codename;
this.name = name;
this.version = version;
this.versionCode = versionCode;
this.author = author;
this.description = description;
this.minApi = minApi;
this.maxApi = maxApi;
this.minMagisk = minMagisk;
this.needRamdisk = needRamdisk;
this.support = support;
this.donate = donate;
this.config = config;
this.changeBoot = changeBoot;
this.mmtReborn = mmtReborn;
this.repoId = repoId;
this.installed = installed;
this.installedVersionCode = installedVersionCode;
this.lastUpdate = lastUpdate;
this.safe = false;
this.stats = stats;
}
public ModuleListCache() {
}
// get all modules from a repo as a json object
public static JSONObject getRepoModulesAsJson(String repoId) {
Realm realm = Realm.getDefaultInstance();
RealmResults<ModuleListCache> modules = realm.where(ModuleListCache.class).equalTo("repoId", repoId).findAll();
JSONObject jsonObject = new JSONObject();
for (ModuleListCache module : modules) {
try {
jsonObject.put(module.getCodename(), module.toJson());
} catch (
JSONException e) {
Timber.e(e);
}
}
realm.close();
return jsonObject;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public int getVersionCode() {
return versionCode;
}
public void setVersionCode(int versionCode) {
this.versionCode = versionCode;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getSupport() {
return support;
}
public void setSupport(String support) {
this.support = support;
}
public String getDonate() {
return donate;
}
public void setDonate(String donate) {
this.donate = donate;
}
public String getConfig() {
return config;
}
public void setConfig(String config) {
this.config = config;
}
public boolean isChangeBoot() {
return changeBoot;
}
public void setChangeBoot(boolean changeBoot) {
this.changeBoot = changeBoot;
}
public boolean isMmtReborn() {
return mmtReborn;
}
public void setMmtReborn(boolean mmtReborn) {
this.mmtReborn = mmtReborn;
}
public String getRepoId() {
return repoId;
}
public void setRepoId(String repoId) {
this.repoId = repoId;
}
public boolean isInstalled() {
return installed;
}
public void setInstalled(boolean installed) {
this.installed = installed;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public int getMinApi() {
return minApi;
}
public void setMinApi(int minApi) {
this.minApi = minApi;
}
public int getMaxApi() {
return maxApi;
}
public void setMaxApi(int maxApi) {
this.maxApi = maxApi;
}
public int getMinMagisk() {
return minMagisk;
}
public void setMinMagisk(int minMagisk) {
this.minMagisk = minMagisk;
}
public boolean isNeedRamdisk() {
return needRamdisk;
}
public void setNeedRamdisk(boolean needRamdisk) {
this.needRamdisk = needRamdisk;
}
public int getInstalledVersionCode() {
return installedVersionCode;
}
public void setInstalledVersionCode(int installedVersionCode) {
this.installedVersionCode = installedVersionCode;
}
public String getCodename() {
return codename;
}
public void setCodename(String codename) {
this.codename = codename;
}
public int getLastUpdate() {
return lastUpdate;
}
public void setLastUpdate(int lastUpdate) {
this.lastUpdate = lastUpdate;
}
public boolean isSafe() {
return safe;
}
public void setSafe(boolean safe) {
this.safe = safe;
}
public int getStats() {
return stats;
}
public void setStats(int stats) {
this.stats = stats;
}
private JSONObject toJson() {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("name", name);
jsonObject.put("version", version);
jsonObject.put("versionCode", versionCode);
jsonObject.put("author", author);
jsonObject.put("description", description);
jsonObject.put("minApi", minApi);
jsonObject.put("maxApi", maxApi);
jsonObject.put("minMagisk", minMagisk);
jsonObject.put("needRamdisk", needRamdisk);
jsonObject.put("support", support);
jsonObject.put("donate", donate);
jsonObject.put("config", config);
jsonObject.put("changeBoot", changeBoot);
jsonObject.put("mmtReborn", mmtReborn);
jsonObject.put("repoId", repoId);
jsonObject.put("installed", installed);
jsonObject.put("installedVersionCode", installedVersionCode);
jsonObject.put("lastUpdate", lastUpdate);
jsonObject.put("safe", safe);
jsonObject.put("stats", stats);
} catch (JSONException e) {
e.printStackTrace();
}
return jsonObject;
}
public RealmResults<ModuleListCache> getModules() {
// return all modules matching the repo id
Realm realm = Realm.getDefaultInstance();
RealmResults<ModuleListCache> modules = realm.where(ModuleListCache.class).equalTo("repoId", repoId).findAll();
realm.close();
return modules;
}
// same as above but returns a json object
public JSONObject getModulesAsJson(String repoId) {
Realm realm = Realm.getDefaultInstance();
RealmResults<ModuleListCache> modules = realm.where(ModuleListCache.class).equalTo("repoId", repoId).findAll();
JSONObject jsonObject = new JSONObject();
// everything goes under top level "modules" key
try {
jsonObject.put("modules", new JSONArray());
} catch (JSONException ignored) {
// we should never get here
}
for (ModuleListCache module : modules) {
try {
jsonObject.getJSONArray("modules").put(module.toJson());
} catch (
JSONException e) {
Timber.e(e);
}
}
realm.close();
return jsonObject;
}
}

@ -1,122 +0,0 @@
/*
* Copyright (c) 2023 to present Androidacy and contributors. Names, logos, icons, and the Androidacy name are all trademarks of Androidacy and may not be used without license. See LICENSE for more information.
*/
package com.fox2code.mmm.utils.realm;
import io.realm.Realm;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
import io.realm.annotations.Required;
@SuppressWarnings("unused")
public class ReposList extends RealmObject {
// Each repo is identified by its id, has a url field, and an enabled field
// there's also an optional donate and support field
@Required
@PrimaryKey
private String id;
@Required
private String url;
private boolean enabled;
private String donate;
private String support;
private String submitModule;
private int lastUpdate;
private String website;
private String name;
public ReposList(String id, String url, boolean enabled, String donate, String support) {
this.id = id;
this.url = url;
this.enabled = enabled;
this.donate = donate;
this.support = support;
this.submitModule = null;
this.lastUpdate = 0;
}
public ReposList() {
}
// get metadata for a repo
public static ReposList getRepo(String id) {
Realm realm = Realm.getDefaultInstance();
ReposList repo = realm.where(ReposList.class).equalTo("id", id).findFirst();
realm.close();
return repo;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getDonate() {
return donate;
}
public void setDonate(String donate) {
this.donate = donate;
}
public String getSupport() {
return support;
}
public void setSupport(String support) {
this.support = support;
}
public String getSubmitModule() {
return submitModule;
}
public void setSubmitModule(String submitModule) {
this.submitModule = submitModule;
}
public int getLastUpdate() {
return lastUpdate;
}
public void setLastUpdate(int lastUpdate) {
this.lastUpdate = lastUpdate;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
}

@ -24,7 +24,9 @@ class ModuleListCache (
var changeBoot: Boolean,
var mmtReborn: Boolean,
var repoId: String,
var lastUpdate: Long
var lastUpdate: Long,
val name: String,
var safe: Boolean
) {
// functions:
// getAll(): List<ModuleListCache>

@ -5,11 +5,13 @@
package com.fox2code.mmm.utils.room
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
// contains
// codename (string, primary), version (string), versionCode (int), author (string), description (string), minApi (int), maxApi (int), minMagisk (int), needRamdisk (boolean), support (string), donate (string), config (string), changeBoot (bool), mmtReborn (bool), repoId (string), lastUpdate (bigint)
// codename (string, primary), version (string), versionCode (int), author (string), description (string), minApi (int), maxApi (int), minMagisk (int), needRamdisk (boolean), support (string), donate (string), config (string), changeBoot (bool), mmtReborn (bool), repoId (string), lastUpdate (bigint), safe (bool)
@Suppress("unused")
@Dao
interface ModuleListCacheDao {
@ -66,8 +68,8 @@ interface ModuleListCacheDao {
@Query("SELECT * FROM modulelistcache WHERE codename = :codename")
fun getByCodename(codename: String): ModuleListCache
@Query("INSERT INTO modulelistcache VALUES (:codename, :version, :versionCode, :author, :description, :minApi, :maxApi, :minMagisk, :needRamdisk, :support, :donate, :config, :changeBoot, :mmtReborn, :repoId, :lastUpdate)")
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)
@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)
@Query("UPDATE modulelistcache SET version = :version WHERE codename = :codename")
fun setVersion(codename: String, version: String)
@ -114,6 +116,12 @@ interface ModuleListCacheDao {
@Query("UPDATE modulelistcache SET lastUpdate = :lastUpdate WHERE codename = :codename")
fun setLastUpdate(codename: String, lastUpdate: Long)
@Query("UPDATE modulelistcache SET safe = :safe WHERE codename = :codename")
fun setSafe(codename: String, safe: Boolean)
@Query("UPDATE modulelistcache SET name = :name WHERE codename = :codename")
fun setName(codename: String, name: String)
@Query("DELETE FROM modulelistcache WHERE codename = :codename")
fun delete(codename: String)
@ -168,6 +176,16 @@ interface ModuleListCacheDao {
@Query("SELECT lastUpdate FROM modulelistcache WHERE codename = :codename")
fun getLastUpdate(codename: String): Long
@Query("SELECT safe FROM modulelistcache WHERE codename = :codename")
fun getSafe(codename: String): Boolean
@Query("SELECT name FROM modulelistcache WHERE codename = :codename")
fun getName(codename: String): String
@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
}

@ -5,9 +5,10 @@
package com.fox2code.mmm.utils.room
import androidx.room.Database
import androidx.room.RoomDatabase
@Suppress("unused")
@Database(entities = [ModuleListCache::class], version = 1)
abstract class ModuleListCacheDatabase {
abstract class ModuleListCacheDatabase : RoomDatabase() {
abstract fun moduleListCacheDao(): ModuleListCacheDao
}

@ -12,10 +12,10 @@ data class ReposList(
@PrimaryKey var id: String,
var url: String,
var enabled: Boolean,
var donate: String,
var support: String,
var submitModule: String,
var lastUpdate: Long,
var donate: String?,
var support: String?,
var submitModule: String?,
var lastUpdate: Int,
var name: String,
var website: String
var website: String?
)

@ -27,7 +27,7 @@ interface ReposListDao {
fun getById(id: String): ReposList
@Query("INSERT INTO ReposList VALUES (:id, :url, :enabled, :donate, :support, :submitModule, :lastUpdate, :name, :website)")
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")
fun update(id: String, url: String, enabled: Boolean, donate: String, support: String, submitModule: String, lastUpdate: Long, name: String, website: String)

@ -77,7 +77,7 @@ object SentryMain {
}
// If first_launch pref is not false, refuse to initialize Sentry
val sharedPreferences = MainApplication.getSharedPreferences("mmm")!!
if (sharedPreferences.getString("last_shown_setup", null) != "v2") {
if (sharedPreferences.getString("last_shown_setup", null) != "v3") {
return
}
isSentryEnabled = sharedPreferences.getBoolean("pref_crash_reporting_enabled", false)

@ -24,7 +24,6 @@ buildscript {
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath("io.realm:realm-gradle-plugin:10.16.0")
classpath("io.sentry:sentry-android-gradle-plugin:3.7.0")
classpath("org.gradle.android.cache-fix:org.gradle.android.cache-fix.gradle.plugin:2.7.1")
}

Loading…
Cancel
Save