diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ec6a8f1..43205ae 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -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") diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 50c95fe..6f1cc41 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -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 diff --git a/app/src/main/assets/modulelistcache.db b/app/src/main/assets/modulelistcache.db index b8ec0e5..1338adb 100644 Binary files a/app/src/main/assets/modulelistcache.db and b/app/src/main/assets/modulelistcache.db differ diff --git a/app/src/main/kotlin/com/fox2code/mmm/MainActivity.kt b/app/src/main/kotlin/com/fox2code/mmm/MainActivity.kt index 7d87ebc..2220b17 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/MainActivity.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/MainActivity.kt @@ -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") diff --git a/app/src/main/kotlin/com/fox2code/mmm/SetupActivity.kt b/app/src/main/kotlin/com/fox2code/mmm/SetupActivity.kt index 067da99..890d305 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/SetupActivity.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/SetupActivity.kt @@ -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() { diff --git a/app/src/main/kotlin/com/fox2code/mmm/background/BackgroundUpdateChecker.kt b/app/src/main/kotlin/com/fox2code/mmm/background/BackgroundUpdateChecker.kt index 436ccc9..5f3ab2f 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/background/BackgroundUpdateChecker.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/background/BackgroundUpdateChecker.kt @@ -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) { diff --git a/app/src/main/kotlin/com/fox2code/mmm/manager/ModuleManager.kt b/app/src/main/kotlin/com/fox2code/mmm/manager/ModuleManager.kt index 70b5a54..cd18bd0 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/manager/ModuleManager.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/manager/ModuleManager.kt @@ -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 = 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>(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) diff --git a/app/src/main/kotlin/com/fox2code/mmm/repo/CustomRepoManager.kt b/app/src/main/kotlin/com/fox2code/mmm/repo/CustomRepoManager.kt index 2734ea6..bab26ff 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/repo/CustomRepoManager.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/repo/CustomRepoManager.kt @@ -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 = 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 } diff --git a/app/src/main/kotlin/com/fox2code/mmm/repo/RepoManager.kt b/app/src/main/kotlin/com/fox2code/mmm/repo/RepoManager.kt index 9dba4ab..67668f4 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/repo/RepoManager.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/repo/RepoManager.kt @@ -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 diff --git a/app/src/main/kotlin/com/fox2code/mmm/utils/RuntimeUtils.kt b/app/src/main/kotlin/com/fox2code/mmm/utils/RuntimeUtils.kt index 2097bcd..0f8b06c 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/utils/RuntimeUtils.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/utils/RuntimeUtils.kt @@ -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)) { diff --git a/app/src/main/kotlin/com/fox2code/mmm/utils/realm/ModuleListCache.java b/app/src/main/kotlin/com/fox2code/mmm/utils/realm/ModuleListCache.java deleted file mode 100644 index 40442c8..0000000 --- a/app/src/main/kotlin/com/fox2code/mmm/utils/realm/ModuleListCache.java +++ /dev/null @@ -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 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 getModules() { - // return all modules matching the repo id - Realm realm = Realm.getDefaultInstance(); - RealmResults 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 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; - } -} diff --git a/app/src/main/kotlin/com/fox2code/mmm/utils/realm/ReposList.java b/app/src/main/kotlin/com/fox2code/mmm/utils/realm/ReposList.java deleted file mode 100644 index 30e2e73..0000000 --- a/app/src/main/kotlin/com/fox2code/mmm/utils/realm/ReposList.java +++ /dev/null @@ -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; - } -} diff --git a/app/src/main/kotlin/com/fox2code/mmm/utils/room/ModuleListCache.kt b/app/src/main/kotlin/com/fox2code/mmm/utils/room/ModuleListCache.kt index ff21e21..1d485f9 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/utils/room/ModuleListCache.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/utils/room/ModuleListCache.kt @@ -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 diff --git a/app/src/main/kotlin/com/fox2code/mmm/utils/room/ModuleListCacheDao.kt b/app/src/main/kotlin/com/fox2code/mmm/utils/room/ModuleListCacheDao.kt index 6a21ec5..354dd9e 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/utils/room/ModuleListCacheDao.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/utils/room/ModuleListCacheDao.kt @@ -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 } \ No newline at end of file diff --git a/app/src/main/kotlin/com/fox2code/mmm/utils/room/ModuleListCacheDatabase.kt b/app/src/main/kotlin/com/fox2code/mmm/utils/room/ModuleListCacheDatabase.kt index 2e81d7b..5a2ff2d 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/utils/room/ModuleListCacheDatabase.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/utils/room/ModuleListCacheDatabase.kt @@ -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 } \ No newline at end of file diff --git a/app/src/main/kotlin/com/fox2code/mmm/utils/room/ReposList.kt b/app/src/main/kotlin/com/fox2code/mmm/utils/room/ReposList.kt index 1973cf0..8405d8a 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/utils/room/ReposList.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/utils/room/ReposList.kt @@ -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? ) \ No newline at end of file diff --git a/app/src/main/kotlin/com/fox2code/mmm/utils/room/ReposListDao.kt b/app/src/main/kotlin/com/fox2code/mmm/utils/room/ReposListDao.kt index 5476a66..2076421 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/utils/room/ReposListDao.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/utils/room/ReposListDao.kt @@ -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) diff --git a/app/src/main/kotlin/com/fox2code/mmm/utils/sentry/SentryMain.kt b/app/src/main/kotlin/com/fox2code/mmm/utils/sentry/SentryMain.kt index 80af61e..6f49cf7 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/utils/sentry/SentryMain.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/utils/sentry/SentryMain.kt @@ -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) diff --git a/build.gradle.kts b/build.gradle.kts index 57d36b2..b9c9e33 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -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") }