diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 888d648..266551e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -34,7 +34,7 @@ android { val timestamp = System.currentTimeMillis() namespace = "com.fox2code.mmm" - compileSdk = 33 + compileSdk = 34 ndkVersion = "25.2.9519653" signingConfigs { create("release") { @@ -52,9 +52,9 @@ android { defaultConfig { applicationId = "com.fox2code.mmm" minSdk = 24 - targetSdk = 33 - versionCode = 81 - versionName = "2.2.3" + targetSdk = 34 + versionCode = 82 + versionName = "2.3.0" vectorDrawables { useSupportLibrary = true } @@ -460,11 +460,11 @@ dependencies { // UI implementation("androidx.appcompat:appcompat:1.6.1") implementation("androidx.activity:activity-ktx:1.7.2") - implementation("androidx.emoji2:emoji2:1.3.0") - implementation("androidx.emoji2:emoji2-views-helper:1.3.0") - implementation("androidx.preference:preference-ktx:1.2.0") + implementation("androidx.emoji2:emoji2:1.4.0") + implementation("androidx.emoji2:emoji2-views-helper:1.4.0") + implementation("androidx.preference:preference-ktx:1.2.1") implementation("androidx.constraintlayout:constraintlayout:2.1.4") - implementation("androidx.recyclerview:recyclerview:1.3.0") + implementation("androidx.recyclerview:recyclerview:1.3.1") implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") implementation("androidx.webkit:webkit:1.7.0") implementation("com.google.android.material:material:1.9.0") @@ -498,12 +498,12 @@ dependencies { implementation("com.github.Fox2Code:AndroidANSI:1.2.1") // sentry - implementation("io.sentry:sentry-android:6.25.2") - implementation("io.sentry:sentry-android-timber:6.25.2") - implementation("io.sentry:sentry-android-fragment:6.25.2") - implementation("io.sentry:sentry-android-okhttp:6.25.2") - implementation("io.sentry:sentry-kotlin-extensions:6.25.2") - implementation("io.sentry:sentry-android-ndk:6.25.2") + implementation("io.sentry:sentry-android:6.28.0") + implementation("io.sentry:sentry-android-timber:6.28.0") + implementation("io.sentry:sentry-android-fragment:6.28.0") + implementation("io.sentry:sentry-android-okhttp:6.28.0") + implementation("io.sentry:sentry-kotlin-extensions:6.28.0") + implementation("io.sentry:sentry-android-ndk:6.28.0") // Markdown // TODO: switch to an updated implementation @@ -543,7 +543,7 @@ dependencies { coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.3") // yes - implementation("com.github.fingerprintjs:fingerprint-android:2.0.0") + implementation("com.github.fingerprintjs:fingerprint-android:2.0.2") // room implementation("androidx.room:room-runtime:2.5.2") diff --git a/app/src/main/kotlin/com/fox2code/mmm/AppUpdateManager.kt b/app/src/main/kotlin/com/fox2code/mmm/AppUpdateManager.kt index a5fe604..2388732 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/AppUpdateManager.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/AppUpdateManager.kt @@ -44,7 +44,7 @@ class AppUpdateManager private constructor() { lastChecked < System.currentTimeMillis() - 60000L ) return force && peekShouldUpdate() synchronized(updateLock) { - Timber.d("Checking for app updates") + if (BuildConfig.DEBUG) Timber.d("Checking for app updates") if (lastChecked != this.lastChecked) return peekShouldUpdate() // make a request to https://production-api.androidacy.com/amm/updates/check with appVersionCode and token/device_id/client_id var token = AndroidacyRepoData.token @@ -59,7 +59,7 @@ class AppUpdateManager private constructor() { val response = doHttpGet(url, false) // convert response to string val responseString = String(response, Charsets.UTF_8) - Timber.d("Response: $responseString") + if (BuildConfig.DEBUG) Timber.d("Response: $responseString") // json response has a boolean shouldUpdate and an int latestVersion JSONObject(responseString).let { if (it.getBoolean("shouldUpdate")) { @@ -105,7 +105,7 @@ class AppUpdateManager private constructor() { @Throws(IOException::class) private fun parseCompatibilityFlags(inputStream: InputStream) { compatDataId.clear() - Timber.d("Not implemented") + if (BuildConfig.DEBUG) Timber.d("Not implemented") } fun getCompatibilityFlags(moduleId: String): Int { diff --git a/app/src/main/kotlin/com/fox2code/mmm/CrashHandler.kt b/app/src/main/kotlin/com/fox2code/mmm/CrashHandler.kt index 0052ebb..e1c8962 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/CrashHandler.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/CrashHandler.kt @@ -28,7 +28,7 @@ class CrashHandler : FoxActivity() { override fun onCreate(savedInstanceState: Bundle?) { Timber.i("CrashHandler.onCreate(%s)", savedInstanceState) // log intent with extras - Timber.d("CrashHandler.onCreate: intent=%s", intent) + if (BuildConfig.DEBUG) Timber.d("CrashHandler.onCreate: intent=%s", intent) super.onCreate(savedInstanceState) setContentView(R.layout.activity_crash_handler) // set crash_details MaterialTextView to the exception passed in the intent or unknown if null @@ -58,7 +58,7 @@ class CrashHandler : FoxActivity() { if (lastEventId?.matches("^0+$".toRegex()) == true) { lastEventId = "" } - Timber.d( + if (BuildConfig.DEBUG) Timber.d( "CrashHandler.onCreate: lastEventId=%s, crashReportingEnabled=%s", lastEventId, crashReportingEnabled @@ -71,7 +71,7 @@ class CrashHandler : FoxActivity() { val submit = findViewById(R.id.feedback_submit) if (lastEventId.isNullOrEmpty() && crashReportingEnabled) { // if lastEventId is null, hide the feedback button - Timber.d("CrashHandler.onCreate: lastEventId is null but crash reporting is enabled. This may indicate a bug in the crash reporting system.") + if (BuildConfig.DEBUG) Timber.d("CrashHandler.onCreate: lastEventId is null but crash reporting is enabled. This may indicate a bug in the crash reporting system.") submit.visibility = View.GONE findViewById(R.id.feedback_text).setText(R.string.no_sentry_id) } else { diff --git a/app/src/main/kotlin/com/fox2code/mmm/MainActivity.kt b/app/src/main/kotlin/com/fox2code/mmm/MainActivity.kt index 872a62b..dc577ac 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/MainActivity.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/MainActivity.kt @@ -139,7 +139,7 @@ class MainActivity : FoxActivity(), OnRefreshListener, SearchView.OnQueryTextLis if (ts.time > buildTime.time) { val pm = packageManager val intent = Intent(this, ExpiredActivity::class.java) - @Suppress("DEPRECATION") val resolveInfo = pm.queryIntentActivities(intent, 0) + val resolveInfo = pm.queryIntentActivities(intent, 0) if (resolveInfo.size > 0) { startActivity(intent) finish() @@ -231,11 +231,8 @@ class MainActivity : FoxActivity(), OnRefreshListener, SearchView.OnQueryTextLis .create() rebootDialog.show() } + // get background color and elevation of reboot fab val searchCard = searchCard!! - // copy reboot fab style to search card - searchCard.elevation = rebootFab.elevation - searchCard.translationY = rebootFab.translationY - searchCard.foreground = rebootFab.foreground moduleList.addOnScrollListener(object : RecyclerView.OnScrollListener() { override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { if (newState != RecyclerView.SCROLL_STATE_IDLE) searchView.clearFocus() @@ -307,8 +304,6 @@ class MainActivity : FoxActivity(), OnRefreshListener, SearchView.OnQueryTextLis TrackHelper.track().event("view_list", "settings") .with(MainApplication.INSTANCE!!.tracker) startActivity(Intent(this@MainActivity, SettingsActivity::class.java)) - overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out) - finish() } R.id.online_menu_item -> { @@ -388,9 +383,17 @@ class MainActivity : FoxActivity(), OnRefreshListener, SearchView.OnQueryTextLis tryGetMagiskPathAsync(object : InstallerInitializer.Callback { override fun onPathReceived(path: String?) { Timber.i("Got magisk path: %s", path) - if (peekMagiskVersion() < Constants.MAGISK_VER_CODE_INSTALL_COMMAND) moduleViewListBuilder.addNotification( - NotificationType.MAGISK_OUTDATED - ) + if (peekMagiskVersion() < Constants.MAGISK_VER_CODE_INSTALL_COMMAND) { + if (!InstallerInitializer.isKsu) { + moduleViewListBuilder.addNotification( + NotificationType.MAGISK_OUTDATED + ) + } else { + moduleViewListBuilder.addNotification( + NotificationType.KSU_EXPERIMENTAL + ) + } + } if (!MainApplication.isShowcaseMode) moduleViewListBuilder.addNotification( NotificationType.INSTALL_FROM_STORAGE ) @@ -409,7 +412,7 @@ class MainActivity : FoxActivity(), OnRefreshListener, SearchView.OnQueryTextLis fun commonNext() { if (BuildConfig.DEBUG) { - Timber.d("Common next") + if (BuildConfig.DEBUG) Timber.d("Common next") moduleViewListBuilder.addNotification(NotificationType.DEBUG) } NotificationType.NO_INTERNET.autoAdd(moduleViewListBuilderOnline) @@ -426,7 +429,7 @@ class MainActivity : FoxActivity(), OnRefreshListener, SearchView.OnQueryTextLis updateScreenInsets() // Fix an edge case val context: Context = this@MainActivity if (runtimeUtils!!.waitInitialSetupFinished(context, this@MainActivity)) { - Timber.d("waiting...") + if (BuildConfig.DEBUG) Timber.d("waiting...") return } swipeRefreshBlocker = System.currentTimeMillis() + 5000L @@ -869,7 +872,7 @@ class MainActivity : FoxActivity(), OnRefreshListener, SearchView.OnQueryTextLis // wait for up to 10 seconds for AndroidacyRepoData to be initialized var i: Int if (AndroidacyRepoData.instance.isEnabled && AndroidacyRepoData.instance.memberLevel == null) { - Timber.d("Member level is null, waiting for it to be initialized") + if (BuildConfig.DEBUG) Timber.d("Member level is null, waiting for it to be initialized") i = 0 while (AndroidacyRepoData.instance.memberLevel == null && i < 20) { i++ diff --git a/app/src/main/kotlin/com/fox2code/mmm/MainApplication.kt b/app/src/main/kotlin/com/fox2code/mmm/MainApplication.kt index a989bd9..a225119 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/MainApplication.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/MainApplication.kt @@ -264,24 +264,24 @@ class MainApplication : FoxApplication(), Configuration.Provider { fileUtils.ensureCacheDirs() fileUtils.ensureURLHandler(this) } - Timber.d("Initializing AMM") - Timber.d("Started from background: %s", !isInForeground) - Timber.d("AMM is running in debug mode") + if (BuildConfig.DEBUG) Timber.d("Initializing AMM") + if (BuildConfig.DEBUG) Timber.d("Started from background: %s", !isInForeground) + if (BuildConfig.DEBUG) Timber.d("AMM is running in debug mode") // analytics - Timber.d("Initializing matomo") + if (BuildConfig.DEBUG) Timber.d("Initializing matomo") getTracker() if (!isMatomoAllowed()) { - Timber.d("Matomo is not allowed") + if (BuildConfig.DEBUG) Timber.d("Matomo is not allowed") tracker!!.isOptOut = true } else { tracker!!.isOptOut = false } if (getSharedPreferences("matomo")!!.getBoolean("install_tracked", false)) { TrackHelper.track().download().with(INSTANCE!!.getTracker()) - Timber.d("Sent install event to matomo") + if (BuildConfig.DEBUG) Timber.d("Sent install event to matomo") getSharedPreferences("matomo")!!.edit().putBoolean("install_tracked", true).apply() } else { - Timber.d("Matomo already has install") + if (BuildConfig.DEBUG) Timber.d("Matomo already has install") } try { @Suppress("DEPRECATION") @SuppressLint("PackageManagerGetSignatures") val s = @@ -413,12 +413,12 @@ class MainApplication : FoxApplication(), Configuration.Provider { val activityManager = this.getSystemService(ACTIVITY_SERVICE) as ActivityManager val appProcesses = activityManager.runningAppProcesses if (appProcesses == null) { - Timber.d("appProcesses is null") + if (BuildConfig.DEBUG) Timber.d("appProcesses is null") return false } val packageName = this.packageName for (appProcess in appProcesses) { - Timber.d( + if (BuildConfig.DEBUG) Timber.d( "Process: %s, Importance: %d", appProcess.processName, appProcess.importance ) if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName == packageName) { @@ -503,6 +503,14 @@ class MainApplication : FoxApplication(), Configuration.Provider { init { Shell.setDefaultBuilder(Shell.Builder.create() .setFlags(Shell.FLAG_REDIRECT_STDERR or Shell.FLAG_MOUNT_MASTER).setTimeout(15)) + // set verbose logging for debug builds + if (BuildConfig.DEBUG) { + Shell.enableVerboseLogging = true + } + // prewarm shell + Shell.getShell { + // do nothing + } val random = Random() do { secret = random.nextLong() diff --git a/app/src/main/kotlin/com/fox2code/mmm/NotificationType.kt b/app/src/main/kotlin/com/fox2code/mmm/NotificationType.kt index 97e7f65..aab84e6 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/NotificationType.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/NotificationType.kt @@ -3,12 +3,16 @@ */ @file:Suppress( - "KotlinConstantConditions", "UNINITIALIZED_ENUM_COMPANION_WARNING", - "ktConcatNullable", "BlockingMethodInNonBlockingContext", "UnusedEquals" + "KotlinConstantConditions", + "UNINITIALIZED_ENUM_COMPANION_WARNING", + "ktConcatNullable", + "BlockingMethodInNonBlockingContext", + "UnusedEquals" ) package com.fox2code.mmm +import android.content.Intent import android.net.Uri import android.view.View import android.widget.Toast @@ -33,7 +37,7 @@ import java.util.Date import java.util.zip.ZipFile -enum class NotificationType constructor( +enum class NotificationType( @field:StringRes @param:StringRes @JvmField val textId: Int, @field:DrawableRes @JvmField val iconId: Int, @field:AttrRes @JvmField val backgroundAttr: Int = androidx.appcompat.R.attr.colorError, @@ -43,10 +47,10 @@ enum class NotificationType constructor( ) : NotificationTypeCst { @JvmStatic - DEBUG( - R.string.debug_build, + DEBUG(R.string.debug_build, R.drawable.ic_baseline_bug_report_24, - com.google.android.material.R.attr.colorPrimary, com.google.android.material.R.attr.colorOnPrimary, + com.google.android.material.R.attr.colorPrimary, + com.google.android.material.R.attr.colorOnPrimary, // on click show a toast formatted with commit hash and build date, plus number of days before expiration (builds expire 30 days after build date) View.OnClickListener { v: View -> val buildTime = BuildConfig.BUILD_TIME @@ -62,12 +66,9 @@ enum class NotificationType constructor( 30 - buildTimeDays ) Toast.makeText( - v.context, - toastText, - Toast.LENGTH_LONG + v.context, toastText, Toast.LENGTH_LONG ).show() - } - ) { + }) { override fun shouldRemove(): Boolean { return !BuildConfig.DEBUG } @@ -75,8 +76,10 @@ enum class NotificationType constructor( @JvmStatic SHOWCASE_MODE( - R.string.showcase_mode, R.drawable.ic_baseline_lock_24, - com.google.android.material.R.attr.colorPrimary, com.google.android.material.R.attr.colorOnPrimary + R.string.showcase_mode, + R.drawable.ic_baseline_lock_24, + com.google.android.material.R.attr.colorPrimary, + com.google.android.material.R.attr.colorOnPrimary ) { override fun shouldRemove(): Boolean { return !MainApplication.isShowcaseMode @@ -84,13 +87,11 @@ enum class NotificationType constructor( }, @JvmStatic - NO_MAGISK( - R.string.fail_magisk_missing, + NO_MAGISK(R.string.fail_magisk_missing, R.drawable.ic_baseline_numbers_24, View.OnClickListener { v: View -> IntentHelper.openUrl( - v.context, - "https://github.com/topjohnwu/Magisk/blob/master/docs/install.md" + v.context, "https://github.com/topjohnwu/Magisk/blob/master/docs/install.md" ) }) { override fun shouldRemove(): Boolean { @@ -111,19 +112,15 @@ enum class NotificationType constructor( }, @JvmStatic - MAGISK_OUTDATED( - R.string.magisk_outdated, + MAGISK_OUTDATED(R.string.magisk_outdated, R.drawable.ic_baseline_update_24, View.OnClickListener { v: View -> IntentHelper.openUrl( - v.context, - "https://github.com/topjohnwu/Magisk/releases" + v.context, "https://github.com/topjohnwu/Magisk/releases" ) }) { override fun shouldRemove(): Boolean { - return InstallerInitializer.peekMagiskPath() == null || - InstallerInitializer.peekMagiskVersion() >= - Constants.MAGISK_VER_CODE_INSTALL_COMMAND + return InstallerInitializer.peekMagiskPath() == null || InstallerInitializer.peekMagiskVersion() >= Constants.MAGISK_VER_CODE_INSTALL_COMMAND } }, @@ -142,18 +139,15 @@ enum class NotificationType constructor( }, @JvmStatic - NEED_CAPTCHA_ANDROIDACY( - R.string.androidacy_need_captcha, + NEED_CAPTCHA_ANDROIDACY(R.string.androidacy_need_captcha, R.drawable.ic_baseline_refresh_24, View.OnClickListener { v: View -> IntentHelper.openUrlAndroidacy( - v.context, - "https://" + Http.needCaptchaAndroidacyHost() + "/", false + v.context, "https://" + Http.needCaptchaAndroidacyHost() + "/", false ) }) { override fun shouldRemove(): Boolean { - return (!RepoManager.isAndroidacyRepoEnabled - || !Http.needCaptchaAndroidacy()) + return (!RepoManager.isAndroidacyRepoEnabled || !Http.needCaptchaAndroidacy()) } }, @@ -171,10 +165,21 @@ enum class NotificationType constructor( androidx.appcompat.R.attr.colorPrimary, com.google.android.material.R.attr.colorOnPrimary, View.OnClickListener { v: View -> - IntentHelper.openUrl( + // launch update activity with action download + val pendingIntent = android.app.PendingIntent.getActivity( v.context, - "https://github.com/Androidacy/MagiskModuleManager/releases" + 0, + Intent( + v.context, + UpdateActivity::class.java + ).setAction(UpdateActivity.ACTIONS.DOWNLOAD.toString()), + android.app.PendingIntent.FLAG_UPDATE_CURRENT ) + try { + pendingIntent.send() + } catch (e: android.app.PendingIntent.CanceledException) { + Timber.e(e) + } }, false ) { @@ -192,30 +197,31 @@ enum class NotificationType constructor( View.OnClickListener { v: View? -> val compatActivity = FoxActivity.getFoxActivity(v) val module = File( - compatActivity.cacheDir, - "installer" + File.separator + "module.zip" + compatActivity.cacheDir, "installer" + File.separator + "module.zip" ) IntentHelper.openFileTo(compatActivity, module) { d: File, u: Uri, s: Int -> if (s == IntentHelper.RESPONSE_FILE) { try { if (needPatch(d)) { patchModuleSimple( - read(d), - FileOutputStream(d) + read(d), FileOutputStream(d) ) } if (needPatch(d)) { if (d.exists() && !d.delete()) Timber.w("Failed to delete non module zip") Toast.makeText( - compatActivity, - R.string.invalid_format, Toast.LENGTH_SHORT + compatActivity, R.string.invalid_format, Toast.LENGTH_SHORT ).show() } else { IntentHelper.openInstaller( - compatActivity, d.absolutePath, + compatActivity, + d.absolutePath, compatActivity.getString( R.string.local_install_title - ), null, null, false, + ), + null, + null, + false, BuildConfig.DEBUG && // Use debug mode if no root InstallerInitializer.peekMagiskPath() == null ) @@ -223,17 +229,14 @@ enum class NotificationType constructor( } catch (ignored: IOException) { if (d.exists() && !d.delete()) Timber.w("Failed to delete invalid module") Toast.makeText( - compatActivity, - R.string.invalid_format, Toast.LENGTH_SHORT + compatActivity, R.string.invalid_format, Toast.LENGTH_SHORT ).show() } } else if (s == IntentHelper.RESPONSE_URL) { IntentHelper.openInstaller( - compatActivity, u.toString(), - compatActivity.getString( + compatActivity, u.toString(), compatActivity.getString( R.string.remote_install_title - ), null, null, false, - BuildConfig.DEBUG && // Use debug mode if no root + ), null, null, false, BuildConfig.DEBUG && // Use debug mode if no root InstallerInitializer.peekMagiskPath() == null ) } @@ -242,9 +245,19 @@ enum class NotificationType constructor( false ) { override fun shouldRemove(): Boolean { - return !BuildConfig.DEBUG && - (MainApplication.isShowcaseMode || - InstallerInitializer.peekMagiskPath() == null) + return !BuildConfig.DEBUG && (MainApplication.isShowcaseMode || InstallerInitializer.peekMagiskPath() == null) + } + }, + KSU_EXPERIMENTAL( + R.string.ksu_experimental, + R.drawable.ic_baseline_warning_24, + androidx.appcompat.R.attr.colorError, + com.google.android.material.R.attr.colorOnPrimary, + null, + false + ) { + override fun shouldRemove(): Boolean { + return !BuildConfig.DEBUG && (MainApplication.isShowcaseMode || InstallerInitializer.peekMagiskPath() == null || !InstallerInitializer.isKsu) } }; diff --git a/app/src/main/kotlin/com/fox2code/mmm/SetupActivity.kt b/app/src/main/kotlin/com/fox2code/mmm/SetupActivity.kt index 8982420..ddbe98a 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/SetupActivity.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/SetupActivity.kt @@ -211,9 +211,9 @@ class SetupActivity : FoxActivity(), LanguageActivity { setupButton.setOnClickListener { _: View? -> Timber.i("Setup button clicked") // get instance of editor - Timber.d("Saving preferences") + if (BuildConfig.DEBUG) Timber.d("Saving preferences") val editor = prefs.edit() - Timber.d("Got editor: %s", editor) + if (BuildConfig.DEBUG) Timber.d("Got editor: %s", editor) // Set the Automatic update check pref editor.putBoolean( "pref_background_update_check", (Objects.requireNonNull( @@ -247,7 +247,7 @@ class SetupActivity : FoxActivity(), LanguageActivity { "pref_analytics_enabled", (Objects.requireNonNull(view.findViewById(R.id.setup_app_analytics)) as MaterialSwitch).isChecked ) - Timber.d("Saving preferences") + if (BuildConfig.DEBUG) Timber.d("Saving preferences") // now basically do the same thing for room db val db = Room.databaseBuilder( applicationContext, @@ -256,7 +256,7 @@ class SetupActivity : FoxActivity(), LanguageActivity { val androidacyRepoRoom = andRepoView.isChecked val magiskAltRepoRoom = magiskAltRepoView.isChecked val reposListDao = db.reposListDao() - Timber.d(reposListDao.getAll().toString()) + if (BuildConfig.DEBUG) Timber.d(reposListDao.getAll().toString()) val androidacyRepoRoomObj = reposListDao.getById("androidacy_repo") val magiskAltRepoRoomObj = reposListDao.getById("magisk_alt_repo") reposListDao.setEnabled(androidacyRepoRoomObj.id, androidacyRepoRoom) @@ -266,11 +266,11 @@ class SetupActivity : FoxActivity(), LanguageActivity { // Commit the changes editor.commit() // Log the changes - Timber.d("Setup finished. Preferences: %s", prefs.all) - Timber.d("Androidacy repo: %s", androidacyRepoRoom) - Timber.d("Magisk Alt repo: %s", magiskAltRepoRoom) + if (BuildConfig.DEBUG) Timber.d("Setup finished. Preferences: %s", prefs.all) + if (BuildConfig.DEBUG) Timber.d("Androidacy repo: %s", androidacyRepoRoom) + if (BuildConfig.DEBUG) Timber.d("Magisk Alt repo: %s", magiskAltRepoRoom) // log last shown setup - Timber.d("Last shown setup: %s", prefs.getString("last_shown_setup", "v0")) + if (BuildConfig.DEBUG) Timber.d("Last shown setup: %s", prefs.getString("last_shown_setup", "v0")) // Restart the activity MainActivity.doSetupRestarting = true val pendingIntent = PendingIntent.getActivity( @@ -350,7 +350,7 @@ class SetupActivity : FoxActivity(), LanguageActivity { // creates the room database private fun createDatabases() { val thread = Thread { - Timber.d("Creating databases") + if (BuildConfig.DEBUG) Timber.d("Creating databases") val startTime = System.currentTimeMillis() val appContext = MainApplication.INSTANCE!!.applicationContext val db = Room.databaseBuilder(appContext, ReposListDatabase::class.java, "ReposList.db") @@ -432,7 +432,7 @@ class SetupActivity : FoxActivity(), LanguageActivity { ).show() } } else { - Timber.d("ReposList is updated with 2 entries") + if (BuildConfig.DEBUG) Timber.d("ReposList is updated with 2 entries") } // make sure modulelistcache is updated with 1 entry if (moduleListCacheList.size != 1) { @@ -446,12 +446,12 @@ class SetupActivity : FoxActivity(), LanguageActivity { ).show() } } else { - Timber.d("ModuleListCache is updated with 1 entry") + if (BuildConfig.DEBUG) Timber.d("ModuleListCache is updated with 1 entry") } // close the databases db.close() db2.close() - Timber.d("Databases created in %s ms", System.currentTimeMillis() - startTime) + if (BuildConfig.DEBUG) Timber.d("Databases created in %s ms", System.currentTimeMillis() - startTime) } thread.start() } @@ -490,7 +490,7 @@ class SetupActivity : FoxActivity(), LanguageActivity { val componentName = ComponentName(this, UpdateActivity::class.java) val componentEnabledSetting = pm.getComponentEnabledSetting(componentName) if (componentEnabledSetting == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) { - Timber.d("Disabling update activity for fdroid flavor") + if (BuildConfig.DEBUG) Timber.d("Disabling update activity for fdroid flavor") // disable update activity through package manager pm.setComponentEnabledSetting( componentName, diff --git a/app/src/main/kotlin/com/fox2code/mmm/androidacy/AndroidacyRepoData.kt b/app/src/main/kotlin/com/fox2code/mmm/androidacy/AndroidacyRepoData.kt index 4e0f560..e3768dc 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/androidacy/AndroidacyRepoData.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/androidacy/AndroidacyRepoData.kt @@ -82,7 +82,7 @@ class AndroidacyRepoData(cacheRoot: File?, testMode: Boolean) : RepoData( // response is JSON val jsonObject = JSONObject(String(resp)) memberLevel = jsonObject.getString("role") - Timber.d("Member level: %s", memberLevel) + if (BuildConfig.DEBUG) Timber.d("Member level: %s", memberLevel) val memberPermissions = jsonObject.getJSONArray("permissions") // set role and permissions on userInfo property userInfo = arrayOf( @@ -133,13 +133,12 @@ class AndroidacyRepoData(cacheRoot: File?, testMode: Boolean) : RepoData( "https://" + host + "/auth/register?fmt=json&device_id=" + deviceId + "&client_id=" + BuildConfig.ANDROIDACY_CLIENT_ID, false ) - var token: String - try { + val token: String = try { val jsonObject = JSONObject(String(resp)) - token = jsonObject.getString("token") + jsonObject.getString("token") } catch (e: JSONException) { if (String(resp).count() == 64) { - token = String(resp) + String(resp) } else { return "" } @@ -264,7 +263,7 @@ class AndroidacyRepoData(cacheRoot: File?, testMode: Boolean) : RepoData( @Throws(JSONException::class) override fun populate(jsonObject: JSONObject): List? { var jsonObject = jsonObject - Timber.d("AndroidacyRepoData populate start") + if (BuildConfig.DEBUG) Timber.d("AndroidacyRepoData populate start") val name = jsonObject.optString("name", "Androidacy Modules Repo") val nameForModules = if (name.endsWith(" (Official)")) name.substring(0, name.length - 11) else name @@ -285,18 +284,16 @@ class AndroidacyRepoData(cacheRoot: File?, testMode: Boolean) : RepoData( } val newModules = ArrayList() val len = jsonArray.length() - // stringify json array for logging but only log the first 200 characters - val tempJsonArray = jsonArray.toString() - Timber.d( - "AndroidacyRepoData populate loop start with json %s", - if (tempJsonArray.length > 200) tempJsonArray.substring(0, 200) else tempJsonArray - ) var lastLastUpdate: Long = 0 for (i in 0 until len) { try { - jsonObject = jsonArray.getJSONObject(i) + if (!jsonArray.isNull(i)) { + jsonObject = jsonArray.getJSONObject(i) + } else { + if (BuildConfig.DEBUG) Timber.d("Skipping null module at index %d", i) + continue + } } catch (e: JSONException) { - Timber.e(e, "Failed to parse module") continue } val moduleId: String = try { diff --git a/app/src/main/kotlin/com/fox2code/mmm/androidacy/AndroidacyWebAPI.kt b/app/src/main/kotlin/com/fox2code/mmm/androidacy/AndroidacyWebAPI.kt index 5d39576..c952966 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/androidacy/AndroidacyWebAPI.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/androidacy/AndroidacyWebAPI.kt @@ -74,7 +74,7 @@ class AndroidacyWebAPI( checksum: String?, canInstall: Boolean ) { - if (BuildConfig.DEBUG) Timber.d( + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d( "ModuleDialog, downloadUrl: " + hideToken( moduleUrl!! ) + ", moduleId: " + moduleId + ", installTitle: " + installTitle + ", checksum: " + checksum + ", canInstall: " + canInstall @@ -174,7 +174,7 @@ class AndroidacyWebAPI( fun notifyCompatModeRaw(value: Int) { var value = value if (consumedAction) return - if (BuildConfig.DEBUG) Timber.d("Androidacy Compat mode: %s", value) + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d("Androidacy Compat mode: %s", value) notifiedCompatMode = value if (value < 0) { value = 0 @@ -208,7 +208,7 @@ class AndroidacyWebAPI( if (consumedAction) return consumedAction = true downloadMode = false - if (BuildConfig.DEBUG) Timber.d("Received openUrl request: %s", url) + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d("Received openUrl request: %s", url) if (Uri.parse(url).scheme == "https") { openUrl(activity, url) } @@ -222,7 +222,7 @@ class AndroidacyWebAPI( if (consumedAction) return consumedAction = true downloadMode = false - if (BuildConfig.DEBUG) Timber.d("Received openCustomTab request: %s", url) + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d("Received openCustomTab request: %s", url) if (Uri.parse(url).scheme == "https") { openCustomTab(activity, url) } @@ -266,7 +266,7 @@ class AndroidacyWebAPI( } consumedAction = true downloadMode = false - if (BuildConfig.DEBUG) Timber.d("Received install request: $moduleUrl $installTitle $checksum") + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d("Received install request: $moduleUrl $installTitle $checksum") if (!isAndroidacyLink(moduleUrl)) { forceQuitRaw("Non Androidacy module link used on Androidacy") return 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 3e8c728..2002715 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/background/BackgroundUpdateChecker.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/background/BackgroundUpdateChecker.kt @@ -179,7 +179,7 @@ class BackgroundUpdateChecker(context: Context, workerParams: WorkerParameters) builder.setContentText(context.getString(R.string.notification_channel_background_update_description)) notificationManager.notify(NOTIFICATION_ID_ONGOING, builder.build()) } else { - Timber.d("Not posting notification because of missing permission") + if (BuildConfig.DEBUG) Timber.d("Not posting notification because of missing permission") } ModuleManager.instance!!.scanAsync() RepoManager.getINSTANCE()!!.update(null) @@ -212,7 +212,7 @@ class BackgroundUpdateChecker(context: Context, workerParams: WorkerParameters) for (s in stringSet!!) { if (s.startsWith(localModuleInfo.id)) { version = s - Timber.d("igV: %s", version) + if (BuildConfig.DEBUG) Timber.d("igV: %s", version) break } } @@ -223,7 +223,7 @@ class BackgroundUpdateChecker(context: Context, workerParams: WorkerParameters) remoteVersionCode = repoModule.moduleInfo.versionCode.toString() } if (version.isNotEmpty()) { - Timber.d("igV found: %s", version) + if (BuildConfig.DEBUG) Timber.d("igV found: %s", version) val remoteVersionCodeInt = remoteVersionCode.toInt() val wantsVersion = version.split(":".toRegex()).dropLastWhile { it.isEmpty() } @@ -233,23 +233,23 @@ class BackgroundUpdateChecker(context: Context, workerParams: WorkerParameters) version = version.split(":".toRegex()).dropLastWhile { it.isEmpty() } .toTypedArray()[1] if (version.startsWith("^")) { - Timber.d("igV: newer") + if (BuildConfig.DEBUG) Timber.d("igV: newer") // the wantsversion and newer if (remoteVersionCodeInt >= wantsVersion) { - Timber.d("igV: skipping") + if (BuildConfig.DEBUG) Timber.d("igV: skipping") // if it is, we skip it continue } } else if (version.endsWith("$")) { - Timber.d("igV: older") + if (BuildConfig.DEBUG) Timber.d("igV: older") // this wantsversion and older if (remoteVersionCodeInt <= wantsVersion) { - Timber.d("igV: skipping") + if (BuildConfig.DEBUG) Timber.d("igV: skipping") // if it is, we skip it continue } } else if (wantsVersion == remoteVersionCodeInt) { - Timber.d("igV: equal") + if (BuildConfig.DEBUG) Timber.d("igV: equal") // if it is, we skip it continue } @@ -273,7 +273,7 @@ class BackgroundUpdateChecker(context: Context, workerParams: WorkerParameters) } } if (moduleUpdateCount != 0) { - Timber.d("Found %d updates", moduleUpdateCount) + if (BuildConfig.DEBUG) Timber.d("Found %d updates", moduleUpdateCount) postNotification(context, updateableModules, moduleUpdateCount, false) } } @@ -287,10 +287,10 @@ class BackgroundUpdateChecker(context: Context, workerParams: WorkerParameters) try { val shouldUpdate = AppUpdateManager.appUpdateManager.checkUpdate(true) if (shouldUpdate) { - Timber.d("Found app update") + if (BuildConfig.DEBUG) Timber.d("Found app update") postNotificationForAppUpdate(context) } else { - Timber.d("No app update found") + if (BuildConfig.DEBUG) Timber.d("No app update found") } } catch (e: Exception) { Timber.e("Failed to check for app update") @@ -303,7 +303,7 @@ class BackgroundUpdateChecker(context: Context, workerParams: WorkerParameters) Manifest.permission.POST_NOTIFICATIONS ) == PackageManager.PERMISSION_GRANTED ) { - Timber.d("Removing notification") + if (BuildConfig.DEBUG) Timber.d("Removing notification") val notificationManager = NotificationManagerCompat.from(context) notificationManager.cancel(NOTIFICATION_ID_ONGOING) } @@ -420,11 +420,11 @@ class BackgroundUpdateChecker(context: Context, workerParams: WorkerParameters) ).build() ) notificationManagerCompat.cancel(NOTIFICATION_ID_ONGOING) - Timber.d("Scheduling periodic background check") + if (BuildConfig.DEBUG) Timber.d("Scheduling periodic background check") // use pref_background_update_check_frequency to set frequency. value is in minutes val frequency = MainApplication.getSharedPreferences("mmm")!! .getInt("pref_background_update_check_frequency", 60).toLong() - Timber.d("Frequency: $frequency minutes") + if (BuildConfig.DEBUG) Timber.d("Frequency: $frequency minutes") WorkManager.getInstance(context).enqueueUniquePeriodicWork( "background_checker", ExistingPeriodicWorkPolicy.UPDATE, diff --git a/app/src/main/kotlin/com/fox2code/mmm/installer/InstallerInitializer.kt b/app/src/main/kotlin/com/fox2code/mmm/installer/InstallerInitializer.kt index 7325c7a..af3ac43 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/installer/InstallerInitializer.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/installer/InstallerInitializer.kt @@ -4,6 +4,7 @@ package com.fox2code.mmm.installer +import com.fox2code.mmm.BuildConfig import com.fox2code.mmm.Constants import com.fox2code.mmm.MainApplication import com.fox2code.mmm.NotificationType @@ -21,6 +22,7 @@ class InstallerInitializer { } companion object { + var isKsu: Boolean = false private val MAGISK_SBIN = File("/sbin/magisk") private val MAGISK_SYSTEM = File("/system/bin/magisk") private val MAGISK_SYSTEM_EX = File("/system/xbin/magisk") @@ -120,13 +122,18 @@ class InstallerInitializer { var hsRmdsk = hsRmdsk if (mgskPth != null && !forceCheck) return mgskPth val output = ArrayList() + if (Shell.isAppGrantedRoot() == null || !Shell.isAppGrantedRoot()!!) { + return null + } try { if (!Shell.cmd( "if grep ' / ' /proc/mounts | grep -q '/dev/root' &> /dev/null; " + "then echo true; else echo false; fi", - "magisk -V", - "magisk --path" + "su -V", ).to(output).exec().isSuccess ) { + if (BuildConfig.DEBUG) { + Timber.i("Failed to search for ramdisk") + } if (output.size != 0) { hsRmdsk = "false" == output[0] || "true".equals( System.getProperty("ro.build.ab_update"), ignoreCase = true @@ -135,21 +142,45 @@ class InstallerInitializer { Companion.hsRmdsk = hsRmdsk return null } - mgskPth = if (output.size < 3) "" else output[2] + if (BuildConfig.DEBUG) { + Timber.i("Found ramdisk: %s", output[0]) + Timber.i("Searching for Magisk path. Current path: %s", mgskPth) + } + // reset output + output.clear() + // try to use magisk --path. if that fails, check for /data/adb/ksu for kernelsu support + if (Shell.cmd("magisk --path", "su -V").to(output).exec().isSuccess) { + mgskPth = output[0] + if (BuildConfig.DEBUG) { + Timber.i("Magisk path 1: %s", mgskPth) + } + } else if (Shell.cmd("if [ -f /data/adb/ksu ]; then echo true; else echo false; fi").to( + output + ).exec().isSuccess && "true" == output[0] + ) { + mgskPth = "/data/adb" + isKsu = true + } Timber.i("Magisk runtime path: %s", mgskPth) mgskVerCode = output[1].toInt() Timber.i("Magisk version code: %s", mgskVerCode) - if (mgskVerCode >= Constants.MAGISK_VER_CODE_FLAT_MODULES && mgskVerCode < Constants.MAGISK_VER_CODE_PATH_SUPPORT && (mgskPth.isEmpty() || !File( - mgskPth - ).exists()) - ) { - mgskPth = "/sbin" + if (mgskPth != null) { + if (mgskVerCode >= Constants.MAGISK_VER_CODE_FLAT_MODULES && mgskVerCode < Constants.MAGISK_VER_CODE_PATH_SUPPORT && (mgskPth.isEmpty() || !File( + mgskPth + ).exists()) + ) { + mgskPth = "/sbin" + } } - if (mgskPth.isNotEmpty() && existsSU(File(mgskPth))) { - Companion.mgskPth = mgskPth + if (mgskPth != null) { + if (mgskPth.isNotEmpty() && existsSU(File(mgskPth))) { + Companion.mgskPth = mgskPth + } else { + Timber.e("Failed to get Magisk path (Got $mgskPth)") + mgskPth = null + } } else { - Timber.e("Failed to get Magisk path (Got $mgskPth)") - mgskPth = null + Timber.e("Failed to get Magisk path (Got null)") } Companion.mgskVerCode = mgskVerCode return mgskPth 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 2ab8376..03744c1 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/manager/ModuleManager.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/manager/ModuleManager.kt @@ -58,7 +58,7 @@ class ModuleManager private constructor() : SyncManager() { if (!FORCE_NEED_FALLBACK && needFallback) { Timber.e("using fallback instead.") } - if (BuildConfig.DEBUG) Timber.d("Scan") + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d("Scan") val modulesList = StringBuilder() if (modules != null) { Timber.i("Found %d modules on device in data", modules.size) @@ -69,7 +69,7 @@ class ModuleManager private constructor() : SyncManager() { ).allowMainThreadQueries().build() for (module in modules) { if (!SuFile("/data/adb/modules/$module").isDirectory) continue // Ignore non directory files inside modules folder - Timber.d("Found module %s", module) + if (BuildConfig.DEBUG) Timber.d("Found module %s", module) var moduleInfo = moduleInfos[module] // next, merge the module info with a record from ModuleListCache room db if it exists // initialize modulelistcache db @@ -80,7 +80,7 @@ class ModuleManager private constructor() : SyncManager() { moduleInfo = LocalModuleInfo(module) } if (moduleListCacheDao.exists(module)) { - Timber.d("Found cache for %s", module) + if (BuildConfig.DEBUG) Timber.d("Found cache for %s", module) val moduleListCache: ModuleListCache = moduleListCacheDao.getByCodename(module) moduleInfo.name = if (moduleListCache.name != "") moduleListCache.name else module @@ -130,7 +130,7 @@ class ModuleManager private constructor() : SyncManager() { moduleInfo, "/data/adb/modules/$module/module.prop", true ) } catch (e: Exception) { - if (BuildConfig.DEBUG) Timber.d(e) + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d(e) moduleInfo.flags = moduleInfo.flags or FLAG_MM_INVALID } moduleInfos[module] = moduleInfo @@ -148,12 +148,12 @@ class ModuleManager private constructor() : SyncManager() { // send list to matomo TrackHelper.track().event("installed_modules", modulesList.toString()) .with(MainApplication.INSTANCE!!.tracker) - if (BuildConfig.DEBUG) Timber.d("Scan update") + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d("Scan update") val modulesUpdate = SuFile("/data/adb/modules_update").list() if (modulesUpdate != null) { for (module in modulesUpdate) { if (!SuFile("/data/adb/modules_update/$module").isDirectory) continue // Ignore non directory files inside modules folder - if (BuildConfig.DEBUG) Timber.d(module) + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d(module) var moduleInfo = moduleInfos[module] if (moduleInfo == null) { moduleInfo = LocalModuleInfo(module) @@ -166,17 +166,17 @@ class ModuleManager private constructor() : SyncManager() { moduleInfo, "/data/adb/modules_update/$module/module.prop", true ) } catch (e: Exception) { - if (BuildConfig.DEBUG) Timber.d(e) + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d(e) moduleInfo.flags = moduleInfo.flags or FLAG_MM_INVALID } } } - if (BuildConfig.DEBUG) Timber.d("Finalize scan") + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d("Finalize scan") updatableModuleCount = 0 val moduleInfoIterator = moduleInfos.values.iterator() while (moduleInfoIterator.hasNext()) { val moduleInfo = moduleInfoIterator.next() - if (BuildConfig.DEBUG) Timber.d(moduleInfo.id) + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d(moduleInfo.id) if (moduleInfo.flags and FLAG_MM_UNPROCESSED != 0) { moduleInfoIterator.remove() continue // Don't process fallbacks if unreferenced @@ -225,7 +225,7 @@ class ModuleManager private constructor() : SyncManager() { @Suppress("unused") fun setEnabledState(moduleInfo: ModuleInfo, checked: Boolean): Boolean { - Timber.d("setEnabledState(%s, %s)", moduleInfo.id, checked) + if (BuildConfig.DEBUG) Timber.d("setEnabledState(%s, %s)", moduleInfo.id, checked) if (moduleInfo.hasFlag(ModuleInfo.FLAG_MODULE_UPDATING) && !checked) return false val disable = SuFile("/data/adb/modules/" + moduleInfo.id + "/disable") if (checked) { diff --git a/app/src/main/kotlin/com/fox2code/mmm/markdown/MarkdownUrlLinker.kt b/app/src/main/kotlin/com/fox2code/mmm/markdown/MarkdownUrlLinker.kt index 71cade5..c29b89e 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/markdown/MarkdownUrlLinker.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/markdown/MarkdownUrlLinker.kt @@ -4,6 +4,7 @@ package com.fox2code.mmm.markdown +import com.fox2code.mmm.BuildConfig import timber.log.Timber enum class MarkdownUrlLinker { @@ -33,7 +34,7 @@ enum class MarkdownUrlLinker { if (endDomain != -1 && endDomain < end && endCh != '>' && endCh != ')' && endCh != ']') { linkifyTasks.add(LinkifyTask(index, end)) extra += end - index + 4 - Timber.d("Linkify url: %s", url.substring(end)) + if (BuildConfig.DEBUG) Timber.d("Linkify url: %s", url.substring(end)) } } index = url.indexOf("https://", end) diff --git a/app/src/main/kotlin/com/fox2code/mmm/module/ActionButtonType.kt b/app/src/main/kotlin/com/fox2code/mmm/module/ActionButtonType.kt index f356a95..c90b3bd 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/module/ActionButtonType.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/module/ActionButtonType.kt @@ -13,6 +13,7 @@ import android.widget.Toast import androidx.annotation.DrawableRes import com.fox2code.foxcompat.app.FoxActivity import com.fox2code.foxcompat.view.FoxDisplay +import com.fox2code.mmm.BuildConfig import com.fox2code.mmm.MainApplication.Companion.INSTANCE import com.fox2code.mmm.MainApplication.Companion.isShowcaseMode import com.fox2code.mmm.R @@ -387,7 +388,7 @@ enum class ActionButtonType { REMOTE { @Suppress("NAME_SHADOWING") override fun doAction(button: Chip, moduleHolder: ModuleHolder) { - Timber.d("doAction: remote module for %s", moduleHolder.moduleInfo?.name ?: "null") + if (BuildConfig.DEBUG) Timber.d("doAction: remote module for %s", moduleHolder.moduleInfo?.name ?: "null") // that module is from remote repo val name: String? = if (moduleHolder.moduleInfo != null) { moduleHolder.moduleInfo!!.name @@ -441,18 +442,18 @@ enum class ActionButtonType { madb.setPositiveButton( R.string.reinstall ) { _: DialogInterface?, _: Int -> - Timber.d("Set moduleinfo to %s", moduleInfo.name) + if (BuildConfig.DEBUG) Timber.d("Set moduleinfo to %s", moduleInfo.name) val name: String? = if (moduleHolder.moduleInfo != null) { moduleHolder.moduleInfo!!.name } else { moduleHolder.repoModule?.moduleInfo?.name } - Timber.d("doAction: remote module for %s", name) + if (BuildConfig.DEBUG) Timber.d("doAction: remote module for %s", name) TrackHelper.track().event("view_update_install", name) .with(INSTANCE!!.getTracker()) // Androidacy manage the selection between download and install if (isAndroidacyLink(updateZipUrl)) { - Timber.d("Androidacy link detected") + if (BuildConfig.DEBUG) Timber.d("Androidacy link detected") openUrlAndroidacy( button.context, updateZipUrl, diff --git a/app/src/main/kotlin/com/fox2code/mmm/module/ModuleHolder.kt b/app/src/main/kotlin/com/fox2code/mmm/module/ModuleHolder.kt index 826d4bb..b75b43a 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/module/ModuleHolder.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/module/ModuleHolder.kt @@ -7,6 +7,7 @@ import android.content.Context import android.content.pm.PackageManager import android.view.View import androidx.annotation.StringRes +import com.fox2code.mmm.BuildConfig import com.fox2code.mmm.MainApplication.Companion.INSTANCE import com.fox2code.mmm.MainApplication.Companion.formatTime import com.fox2code.mmm.MainApplication.Companion.getSharedPreferences @@ -136,13 +137,13 @@ class ModuleHolder : Comparable { HashSet() ) var version = "" - Timber.d(stringSetT.toString()) + if (BuildConfig.DEBUG) Timber.d(stringSetT.toString()) // unfortunately, stringset.contains() doesn't work for partial matches // so we have to iterate through the set for (s in stringSetT!!) { if (s.startsWith(moduleInfo!!.id)) { version = s - Timber.d("igV: %s", version) + if (BuildConfig.DEBUG) Timber.d("igV: %s", version) break } } @@ -156,34 +157,34 @@ class ModuleHolder : Comparable { val wantsVersion = version.split(":".toRegex()).dropLastWhile { it.isEmpty() } .toTypedArray()[1].replace("[^0-9]".toRegex(), "").toInt() // now find out if user wants up to and including this version, or this version and newer - Timber.d("igV start with") + if (BuildConfig.DEBUG) Timber.d("igV start with") version = version.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1] // this version and newer if (version.startsWith("^")) { - Timber.d("igV: newer") + if (BuildConfig.DEBUG) Timber.d("igV: newer") // the wantsversion and newer if (remoteVersionCodeInt >= wantsVersion) { - Timber.d("igV: skipping") + if (BuildConfig.DEBUG) Timber.d("igV: skipping") // if it is, we skip it ignoreUpdate = true } } else if (version.endsWith("$")) { - Timber.d("igV: older") + if (BuildConfig.DEBUG) Timber.d("igV: older") // this wantsversion and older if (remoteVersionCodeInt <= wantsVersion) { - Timber.d("igV: skipping") + if (BuildConfig.DEBUG) Timber.d("igV: skipping") // if it is, we skip it ignoreUpdate = true } } else if (wantsVersion == remoteVersionCodeInt) { - Timber.d("igV: equal") + if (BuildConfig.DEBUG) Timber.d("igV: equal") // if it is, we skip it ignoreUpdate = true } } if (ignoreUpdate) { - Timber.d("Module %s has update, but is ignored", moduleId) + if (BuildConfig.DEBUG) Timber.d("Module %s has update, but is ignored", moduleId) Type.INSTALLABLE } else { INSTANCE!!.modulesHaveUpdates = true @@ -191,7 +192,7 @@ class ModuleHolder : Comparable { INSTANCE!!.updateModules += moduleId INSTANCE!!.updateModuleCount++ } - Timber.d( + if (BuildConfig.DEBUG) Timber.d( "modulesHaveUpdates = %s, updateModuleCount = %s", INSTANCE!!.modulesHaveUpdates, INSTANCE!!.updateModuleCount @@ -248,16 +249,16 @@ class ModuleHolder : Comparable { // set updatezipurl on moduleholder if (localModuleInfo.updateZipUrl != null) { - Timber.d("localModuleInfo: %s", localModuleInfo.updateZipUrl) + if (BuildConfig.DEBUG) Timber.d("localModuleInfo: %s", localModuleInfo.updateZipUrl) updateZipUrl = localModuleInfo.updateZipUrl } if (repoModule != null) { - Timber.d("repoModule: %s", repoModule!!.zipUrl) + if (BuildConfig.DEBUG) Timber.d("repoModule: %s", repoModule!!.zipUrl) updateZipUrl = repoModule!!.zipUrl } // last ditch effort, try to get remoteModuleInfo from localModuleInfo if (rInfo != null) { - Timber.d("remoteModuleInfo: %s", rInfo.zipUrl) + if (BuildConfig.DEBUG) Timber.d("remoteModuleInfo: %s", rInfo.zipUrl) updateZipUrl = rInfo.zipUrl moduleInfo?.updateZipUrl = rInfo.zipUrl } diff --git a/app/src/main/kotlin/com/fox2code/mmm/module/ModuleViewAdapter.kt b/app/src/main/kotlin/com/fox2code/mmm/module/ModuleViewAdapter.kt index 10d0e2a..1d6d94f 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/module/ModuleViewAdapter.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/module/ModuleViewAdapter.kt @@ -27,6 +27,7 @@ import androidx.cardview.widget.CardView import androidx.core.graphics.ColorUtils import androidx.recyclerview.widget.RecyclerView import com.fox2code.foxcompat.view.FoxDisplay +import com.fox2code.mmm.BuildConfig import com.fox2code.mmm.MainApplication import com.fox2code.mmm.R import com.fox2code.mmm.manager.ModuleInfo @@ -406,7 +407,7 @@ ${getString(R.string.module_repo)} ${moduleHolder.repoName}""" + if ((repoModule // get string value of Theme val themeName = theme.toString() if (theme.resources.getBoolean(R.bool.force_transparency) || themeName.contains("transparent")) { - Timber.d("Theme is transparent, fixing bgColor") + if (BuildConfig.DEBUG) Timber.d("Theme is transparent, fixing bgColor") bgColor = ColorUtils.setAlphaComponent(bgColor, 0x70) } titleText.setTextColor(fgColor) diff --git a/app/src/main/kotlin/com/fox2code/mmm/module/ModuleViewListBuilder.kt b/app/src/main/kotlin/com/fox2code/mmm/module/ModuleViewListBuilder.kt index 57e9f69..4c54b41 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/module/ModuleViewListBuilder.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/module/ModuleViewListBuilder.kt @@ -15,6 +15,7 @@ import com.fox2code.mmm.BuildConfig import com.fox2code.mmm.MainActivity import com.fox2code.mmm.MainApplication import com.fox2code.mmm.NotificationType +import com.fox2code.mmm.installer.InstallerInitializer import com.fox2code.mmm.installer.InstallerInitializer.Companion.peekHasRamdisk import com.fox2code.mmm.installer.InstallerInitializer.Companion.peekMagiskPath import com.fox2code.mmm.installer.InstallerInitializer.Companion.peekMagiskVersion @@ -106,7 +107,7 @@ class ModuleViewListBuilder(private val activity: Activity) { continue } val moduleInfo = repoModule.moduleInfo - if (!showIncompatible && (moduleInfo.minApi > Build.VERSION.SDK_INT || moduleInfo.maxApi != 0 && moduleInfo.maxApi < Build.VERSION.SDK_INT || peekMagiskPath() != null) && repoModule.moduleInfo.minMagisk > peekMagiskVersion() || no32bitSupport && (AppUpdateManager.getFlagsForModule( + if (!showIncompatible && (moduleInfo.minApi > Build.VERSION.SDK_INT || moduleInfo.maxApi != 0 && moduleInfo.maxApi < Build.VERSION.SDK_INT || peekMagiskPath() != null) && (!InstallerInitializer.isKsu && repoModule.moduleInfo.minMagisk > peekMagiskVersion()) || no32bitSupport && (AppUpdateManager.getFlagsForModule( repoModule.id ) and AppUpdateManager.FLAG_COMPAT_NEED_32BIT) != 0 || repoModule.moduleInfo.needRamdisk && !peekHasRamdisk() ) continue // Skip adding incompatible modules diff --git a/app/src/main/kotlin/com/fox2code/mmm/repo/RepoData.kt b/app/src/main/kotlin/com/fox2code/mmm/repo/RepoData.kt index b01b67d..8e3f784 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/repo/RepoData.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/repo/RepoData.kt @@ -357,7 +357,7 @@ open class RepoData(url: String, cacheRoot: File) : XRepo() { } } } else { - Timber.d("Metadata file not found for %s", repoModule.id) + if (BuildConfig.DEBUG) Timber.d("Metadata file not found for %s", repoModule.id) } repoModule.moduleInfo.flags = repoModule.moduleInfo.flags or ModuleInfo.FLAG_METADATA_INVALID @@ -412,7 +412,7 @@ open class RepoData(url: String, cacheRoot: File) : XRepo() { // should update (lastUpdate > 15 minutes) fun shouldUpdate(): Boolean { - Timber.d("Repo $preferenceId should update check called") + if (BuildConfig.DEBUG) Timber.d("Repo $preferenceId should update check called") val db = Room.databaseBuilder( INSTANCE!!.applicationContext, ReposListDatabase::class.java, @@ -432,12 +432,12 @@ open class RepoData(url: String, cacheRoot: File) : XRepo() { val currentTime = System.currentTimeMillis() val diff = currentTime - lastUpdate val diffMinutes = diff / (60 * 1000) % 60 - Timber.d("Repo $preferenceId updated: $diffMinutes minutes ago") + if (BuildConfig.DEBUG) Timber.d("Repo $preferenceId updated: $diffMinutes minutes ago") db.close() db2.close() diffMinutes > if (BuildConfig.DEBUG) 15 else 30 } else { - Timber.d("Repo $preferenceId shouldUpdate true: lastUpdate is " + repo.lastUpdate + " and moduleListCache is " + moduleListCache.size) + if (BuildConfig.DEBUG) Timber.d("Repo $preferenceId shouldUpdate true: lastUpdate is " + repo.lastUpdate + " and moduleListCache is " + moduleListCache.size) db.close() db2.close() true 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 f179ae5..051358f 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/repo/RepoManager.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/repo/RepoManager.kt @@ -152,18 +152,18 @@ class RepoManager private constructor(mainApplication: MainApplication) : SyncMa } for (i in repoDatas.indices) { updateListener.update(STEP1 * (i / repoDatas.size)) - if (BuildConfig.DEBUG) Timber.d("Preparing to fetch: %s", repoDatas[i].name) + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d("Preparing to fetch: %s", repoDatas[i].name) moduleToUpdate += RepoUpdater(repoDatas[i]).also { repoUpdaters[i] = it }.fetchIndex() // divvy the 40 of step1 to each repo updateListener.update(STEP1 * ((i + 1) / repoDatas.size)) } - if (BuildConfig.DEBUG) Timber.d("Updating meta-data") + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d("Updating meta-data") var updatedModules = 0 val allowLowQualityModules = isDisableLowQualityModuleFilter for (i in repoUpdaters.indices) { // Check if the repo is enabled if (!repoUpdaters[i]!!.repoData.isEnabled) { - if (BuildConfig.DEBUG) Timber.d( + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d( "Skipping disabled repo: %s", repoUpdaters[i]!!.repoData.name ) @@ -171,7 +171,7 @@ class RepoManager private constructor(mainApplication: MainApplication) : SyncMa } val repoModules = repoUpdaters[i]!!.toUpdate() val repoData = repoDatas[i] - if (BuildConfig.DEBUG) Timber.d("Registering %s", repoData.name) + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d("Registering %s", repoData.name) for (repoModule in repoModules!!) { try { if (repoModule.propUrl != null && repoModule.propUrl!!.isNotEmpty()) { @@ -229,15 +229,15 @@ class RepoManager private constructor(mainApplication: MainApplication) : SyncMa } MainApplication.INSTANCE!!.repoModules.putAll(modules) } - if (BuildConfig.DEBUG) Timber.d("Finishing update") + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d("Finishing update") if (hasConnectivity()) { for (i in repoDatas.indices) { // If repo is not enabled, skip if (!repoDatas[i].isEnabled) { - if (BuildConfig.DEBUG) Timber.d("Skipping ${repoDatas[i].name} because it's disabled") + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d("Skipping ${repoDatas[i].name} because it's disabled") continue } - if (BuildConfig.DEBUG) Timber.d("Finishing: %s", repoUpdaters[i]!!.repoData.name) + if (BuildConfig.DEBUG) if (BuildConfig.DEBUG) Timber.d("Finishing: %s", repoUpdaters[i]!!.repoData.name) isLastUpdateSuccess = repoUpdaters[i]!!.finish() if (!isLastUpdateSuccess || modules.isEmpty()) { Timber.e("Failed to update %s", repoUpdaters[i]!!.repoData.name) diff --git a/app/src/main/kotlin/com/fox2code/mmm/repo/RepoUpdater.kt b/app/src/main/kotlin/com/fox2code/mmm/repo/RepoUpdater.kt index 8854cc5..b274a51 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/repo/RepoUpdater.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/repo/RepoUpdater.kt @@ -5,6 +5,7 @@ package com.fox2code.mmm.repo import androidx.room.Room +import com.fox2code.mmm.BuildConfig import com.fox2code.mmm.MainApplication import com.fox2code.mmm.utils.io.net.Http.Companion.doHttpGet import com.fox2code.mmm.utils.room.ModuleListCache @@ -38,7 +39,7 @@ class RepoUpdater(repoData2: RepoData) { } // if MainApplication.repoModules is not empty, return it /*if (MainApplication.INSTANCE!!.repoModules.isNotEmpty()) { - Timber.d("Returning MainApplication.repoModules for %s", repoData.preferenceId) + if (BuildConfig.DEBUG) Timber.d("Returning MainApplication.repoModules for %s", repoData.preferenceId) // convert to list for toUpdate val toUpdateList = ArrayList() for (module in MainApplication.INSTANCE!!.repoModules) { @@ -51,7 +52,7 @@ class RepoUpdater(repoData2: RepoData) { }*/ // if we shouldn't update, get the values from the ModuleListCache realm if (!repoData.shouldUpdate() && repoData.preferenceId == "androidacy_repo") { // for now, only enable cache reading for androidacy repo, until we handle storing module prop file values in cache - Timber.d("Fetching index from cache for %s", repoData.preferenceId) + if (BuildConfig.DEBUG) Timber.d("Fetching index from cache for %s", repoData.preferenceId) // now the above but for room val db = Room.databaseBuilder( MainApplication.INSTANCE!!, @@ -60,10 +61,15 @@ class RepoUpdater(repoData2: RepoData) { ).allowMainThreadQueries().build() val moduleListCacheDao = db.moduleListCacheDao() // now we have the cache, we need to check if it's up to date - val results = moduleListCacheDao.getByRepoId(repoData.preferenceId!!) + var results = moduleListCacheDao.getByRepoId(repoData.preferenceId!!) if (results.isNotEmpty()) { toUpdate = emptyList() toApply = HashSet() + // if results is not empty, check each module to see if it's null. this should never happen, but if it does, remove it from the cache + // copy results to a new list so we can remove items from the original list, then set results to the new list + val resultsCopy = ArrayList(results) + resultsCopy.removeIf { it == null } + results = resultsCopy for (moduleListCache in results) { (toApply as HashSet).add( RepoModule( @@ -80,7 +86,7 @@ class RepoUpdater(repoData2: RepoData) { ) ) } - Timber.d( + if (BuildConfig.DEBUG) Timber.d( "Fetched %d modules from cache for %s, from %s records", (toApply as HashSet).size, repoData.preferenceId, @@ -96,7 +102,7 @@ class RepoUpdater(repoData2: RepoData) { } // log first 100 chars of indexRaw indexRaw = jsonObject.toString().toByteArray() - Timber.d( + if (BuildConfig.DEBUG) Timber.d( "Index raw: %s", String(indexRaw!!, StandardCharsets.UTF_8).subSequence(0, 100) ) @@ -147,18 +153,18 @@ class RepoUpdater(repoData2: RepoData) { fun finish(): Boolean { // If repo is not enabled we don't need to do anything, just return true if (!repoData.isEnabled) { - Timber.d("Repo %s is disabled, skipping", repoData.preferenceId) + if (BuildConfig.DEBUG) Timber.d("Repo %s is disabled, skipping", repoData.preferenceId) return true } val success = AtomicBoolean(false) - Timber.d("Finishing update for %s", repoData.preferenceId) + if (BuildConfig.DEBUG) Timber.d("Finishing update for %s", repoData.preferenceId) if (indexRaw != null) { val tmpIndexRaw = indexRaw!! - Timber.d("Updating database for %s", repoData.preferenceId) + if (BuildConfig.DEBUG) Timber.d("Updating database for %s", repoData.preferenceId) // new thread to update the database val thread = Thread { val startTime = System.currentTimeMillis() - Timber.d("Updating database thread for %s", repoData.preferenceId) + if (BuildConfig.DEBUG) Timber.d("Updating database thread for %s", repoData.preferenceId) try { // iterate over modules, using this.supportedProperties as a template to attempt to get each property from the module. everything that is not null is added to the module // use room to insert to @@ -179,21 +185,21 @@ class RepoUpdater(repoData2: RepoData) { } catch (e: Exception) { Timber.e(e) Timber.w("No modules were found in the index file for %s", repoData.preferenceId) - Timber.d("Finished updating database for %s in %dms", repoData.preferenceId, System.currentTimeMillis() - startTime) + if (BuildConfig.DEBUG) Timber.d("Finished updating database for %s in %dms", repoData.preferenceId, System.currentTimeMillis() - startTime) success.set(false) return@Thread } - Timber.d("Got modules for %s", repoData.preferenceId) + if (BuildConfig.DEBUG) Timber.d("Got modules for %s", repoData.preferenceId) val moduleListCacheDao = db.moduleListCacheDao() moduleListCacheDao.deleteByRepoId(repoData.preferenceId!!) - Timber.d("Deleted old modules for %s", repoData.preferenceId) + if (BuildConfig.DEBUG) Timber.d("Deleted old modules for %s", repoData.preferenceId) if (modulesArray.length() == 0) { Timber.w("No modules were found in the index file for %s", repoData.preferenceId) - Timber.d("Finished updating database for %s in %dms", repoData.preferenceId, System.currentTimeMillis() - startTime) + if (BuildConfig.DEBUG) Timber.d("Finished updating database for %s in %dms", repoData.preferenceId, System.currentTimeMillis() - startTime) success.set(false) return@Thread } - Timber.d("Iterating over modules for %s", repoData.preferenceId) + if (BuildConfig.DEBUG) Timber.d("Iterating over modules for %s", repoData.preferenceId) // iterate over modules for (n in 0 until modulesArray.length()) { // get module @@ -335,7 +341,7 @@ class RepoUpdater(repoData2: RepoData) { db.close() val endTime = System.currentTimeMillis() val timeTaken = endTime - startTime - Timber.d("Time taken to parse modules: $timeTaken ms") + if (BuildConfig.DEBUG) Timber.d("Time taken to parse modules: $timeTaken ms") } catch (ignored: Exception) { } } @@ -352,7 +358,7 @@ class RepoUpdater(repoData2: RepoData) { db.close() success.set(true) } else { - Timber.d("No index file found for %s", repoData.preferenceId) + if (BuildConfig.DEBUG) Timber.d("No index file found for %s", repoData.preferenceId) success.set(true) // assume we're reading from cache. this may be unsafe but it's better than nothing } return success.get() diff --git a/app/src/main/kotlin/com/fox2code/mmm/settings/AppearanceFragment.kt b/app/src/main/kotlin/com/fox2code/mmm/settings/AppearanceFragment.kt index 2815df8..420266a 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/settings/AppearanceFragment.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/settings/AppearanceFragment.kt @@ -17,6 +17,7 @@ import androidx.preference.TwoStatePreference import androidx.security.crypto.EncryptedSharedPreferences import androidx.security.crypto.MasterKey import com.fox2code.foxcompat.app.FoxActivity +import com.fox2code.mmm.BuildConfig import com.fox2code.mmm.MainApplication import com.fox2code.mmm.R import com.fox2code.rosettax.LanguageSwitcher @@ -58,7 +59,7 @@ class AppearanceFragment : PreferenceFragmentCompat() { val themePreference = findPreference("pref_theme") // If transparent theme(s) are set, disable monet if (themePreference!!.value == "transparent_light") { - Timber.d("disabling monet") + if (BuildConfig.DEBUG) Timber.d("disabling monet") findPreference("pref_enable_monet")!!.isEnabled = false // Toggle monet off (findPreference("pref_enable_monet") as TwoStatePreference?)!!.isChecked = @@ -77,11 +78,11 @@ class AppearanceFragment : PreferenceFragmentCompat() { Preference.SummaryProvider { _: Preference? -> themePreference.entry } themePreference.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any -> - Timber.d("refreshing activity. New value: %s", newValue) + if (BuildConfig.DEBUG) Timber.d("refreshing activity. New value: %s", newValue) editor.putString("pref_theme", newValue as String).apply() // If theme contains "transparent" then disable monet if (newValue.toString().contains("transparent")) { - Timber.d("disabling monet") + if (BuildConfig.DEBUG) Timber.d("disabling monet") // Show a dialogue warning the user about issues with transparent themes and // that blur/monet will be disabled MaterialAlertDialogBuilder(requireContext()).setTitle(R.string.transparent_theme_dialogue_title) diff --git a/app/src/main/kotlin/com/fox2code/mmm/settings/DebugFragment.kt b/app/src/main/kotlin/com/fox2code/mmm/settings/DebugFragment.kt index d53ddef..c64e2be 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/settings/DebugFragment.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/settings/DebugFragment.kt @@ -123,7 +123,7 @@ class DebugFragment : PreferenceFragmentCompat() { ) } } - if (InstallerInitializer.peekMagiskVersion() < Constants.MAGISK_VER_CODE_INSTALL_COMMAND || !MainApplication.isDeveloper) { + if (InstallerInitializer.peekMagiskVersion() < Constants.MAGISK_VER_CODE_INSTALL_COMMAND || !MainApplication.isDeveloper || InstallerInitializer.isKsu) { findPreference("pref_use_magisk_install_command")!!.isVisible = false } diff --git a/app/src/main/kotlin/com/fox2code/mmm/settings/InfoFragment.kt b/app/src/main/kotlin/com/fox2code/mmm/settings/InfoFragment.kt index 15faa1d..9c73921 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/settings/InfoFragment.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/settings/InfoFragment.kt @@ -78,7 +78,7 @@ class InfoFragment : PreferenceFragmentCompat() { var userRepo = BuildConfig.REMOTE_URL // remove .git userRepo = userRepo.replace("\\.git$".toRegex(), "") - Timber.d("userRepo: %s", userRepo) + if (BuildConfig.DEBUG) Timber.d("userRepo: %s", userRepo) // finalUserRepo is the user/repo part of REMOTE_URL // get everything after .com/ or .org/ or .io/ or .me/ or .net/ or .xyz/ or .tk/ or .co/ minus .git @@ -89,7 +89,7 @@ class InfoFragment : PreferenceFragmentCompat() { linkClickable!!.summary = String.format( getString(R.string.source_code_summary), BuildConfig.COMMIT_HASH, finalUserRepo ) - Timber.d("finalUserRepo: %s", finalUserRepo) + if (BuildConfig.DEBUG) Timber.d("finalUserRepo: %s", finalUserRepo) val finalUserRepo1 = userRepo linkClickable.onPreferenceClickListener = Preference.OnPreferenceClickListener setOnPreferenceClickListener@{ p: Preference -> @@ -179,7 +179,6 @@ class InfoFragment : PreferenceFragmentCompat() { prefDonateAndroidacy!!.isVisible = false } - linkClickable = findPreference("pref_support") linkClickable!!.onPreferenceClickListener = Preference.OnPreferenceClickListener { p: Preference -> diff --git a/app/src/main/kotlin/com/fox2code/mmm/settings/PrivacyFragment.kt b/app/src/main/kotlin/com/fox2code/mmm/settings/PrivacyFragment.kt index 8305c38..e7bf202 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/settings/PrivacyFragment.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/settings/PrivacyFragment.kt @@ -13,6 +13,7 @@ import androidx.preference.TwoStatePreference import androidx.security.crypto.EncryptedSharedPreferences import androidx.security.crypto.MasterKey import com.fox2code.foxcompat.app.FoxActivity +import com.fox2code.mmm.BuildConfig import com.fox2code.mmm.MainActivity import com.fox2code.mmm.MainApplication import com.fox2code.mmm.R @@ -77,7 +78,7 @@ class PrivacyFragment : PreferenceFragmentCompat() { val mgr = requireContext().getSystemService(FoxActivity.ALARM_SERVICE) as AlarmManager mgr[AlarmManager.RTC, System.currentTimeMillis() + 100] = mPendingIntent - Timber.d("Restarting app to save crash reporting preference: %s", newValue) + if (BuildConfig.DEBUG) Timber.d("Restarting app to save crash reporting preference: %s", newValue) exitProcess(0) // Exit app process } // Do not reverse the change if the user cancels the dialog diff --git a/app/src/main/kotlin/com/fox2code/mmm/settings/RepoFragment.kt b/app/src/main/kotlin/com/fox2code/mmm/settings/RepoFragment.kt index e87c4e8..75aa769 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/settings/RepoFragment.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/settings/RepoFragment.kt @@ -92,7 +92,7 @@ class RepoFragment : PreferenceFragmentCompat() { requireContext().getSystemService(ALARM_SERVICE) as AlarmManager mgr[AlarmManager.RTC, System.currentTimeMillis() + 100] = mPendingIntent - Timber.d( + if (BuildConfig.DEBUG) Timber.d( "Restarting app to save staging endpoint preference: %s", newValue ) @@ -134,7 +134,7 @@ class RepoFragment : PreferenceFragmentCompat() { requireContext().getSystemService(ALARM_SERVICE) as AlarmManager mgr[AlarmManager.RTC, System.currentTimeMillis() + 100] = mPendingIntent - Timber.d( + if (BuildConfig.DEBUG) Timber.d( "Restarting app to save staging endpoint preference: %s", newValue ) @@ -319,7 +319,7 @@ class RepoFragment : PreferenceFragmentCompat() { requireContext().getSystemService(ALARM_SERVICE) as AlarmManager mgr[AlarmManager.RTC, System.currentTimeMillis() + 100] = mPendingIntent - Timber.d( + if (BuildConfig.DEBUG) Timber.d( "Restarting app to save token preference: %s", newValue ) @@ -407,7 +407,7 @@ class RepoFragment : PreferenceFragmentCompat() { ) as AlarmManager mgr[AlarmManager.RTC, System.currentTimeMillis() + 100] = mPendingIntent - Timber.d( + if (BuildConfig.DEBUG) Timber.d( "Restarting app to save token preference: %s", newValue ) @@ -462,13 +462,13 @@ class RepoFragment : PreferenceFragmentCompat() { customRepos.add(id) } } - Timber.d("%d repos: %s", custRepoEntries, customRepos) + if (BuildConfig.DEBUG) Timber.d("%d repos: %s", custRepoEntries, customRepos) val customRepoManager = RepoManager.getINSTANCE()!!.customRepoManager for (i in 0 until custRepoEntries) { // get the id of the repo at current index in customRepos val repoData = customRepoManager!!.getRepo(customRepos[i]) // convert repoData to a json string for logging - Timber.d("RepoData for %d is %s", i, repoData.toJSON()) + if (BuildConfig.DEBUG) Timber.d("RepoData for %d is %s", i, repoData.toJSON()) setRepoData(repoData, "pref_custom_repo_$i") if (initial) { val preference = findPreference("pref_custom_repo_" + i + "_delete") @@ -594,25 +594,25 @@ class RepoFragment : PreferenceFragmentCompat() { // show error if string is empty, does not start with https://, or contains spaces if (charSequence.toString().isEmpty()) { input.error = getString(R.string.empty_field) - Timber.d("No input for repo") + if (BuildConfig.DEBUG) Timber.d("No input for repo") positiveButton.isEnabled = false } else if (!charSequence.toString() .matches("^https://.*".toRegex()) ) { input.error = getString(R.string.invalid_repo_url) - Timber.d("Non https link for repo") + if (BuildConfig.DEBUG) Timber.d("Non https link for repo") positiveButton.isEnabled = false } else if (charSequence.toString().contains(" ")) { input.error = getString(R.string.invalid_repo_url) - Timber.d("Repo url has space") + if (BuildConfig.DEBUG) Timber.d("Repo url has space") positiveButton.isEnabled = false } else if (!customRepoManager.canAddRepo(charSequence.toString())) { input.error = getString(R.string.repo_already_added) - Timber.d("Could not add repo for misc reason") + if (BuildConfig.DEBUG) Timber.d("Could not add repo for misc reason") positiveButton.isEnabled = false } else { // enable ok button - Timber.d("Repo URL is ok") + if (BuildConfig.DEBUG) Timber.d("Repo URL is ok") positiveButton.isEnabled = true } } @@ -638,7 +638,7 @@ class RepoFragment : PreferenceFragmentCompat() { private fun setRepoData(repoData: RepoData?, preferenceName: String) { if (repoData == null) return - Timber.d("Setting preference $preferenceName to $repoData") + if (BuildConfig.DEBUG) Timber.d("Setting preference $preferenceName to $repoData") val clipboard = requireContext().getSystemService(CLIPBOARD_SERVICE) as ClipboardManager var preference = findPreference(preferenceName) ?: return if (!preferenceName.contains("androidacy") && !preferenceName.contains("magisk_alt_repo")) { @@ -649,13 +649,13 @@ class RepoFragment : PreferenceFragmentCompat() { "ReposList.db" ).allowMainThreadQueries().build() val reposList = db.reposListDao().getById(repoData.preferenceId!!) - Timber.d("Setting preference $preferenceName because it is not the Androidacy repo or the Magisk Alt Repo") + if (BuildConfig.DEBUG) Timber.d("Setting preference $preferenceName because it is not the Androidacy repo or the Magisk Alt Repo") if (repoData.isForceHide || reposList == null) { - Timber.d("Hiding preference $preferenceName because it is null or force hidden") + if (BuildConfig.DEBUG) Timber.d("Hiding preference $preferenceName because it is null or force hidden") hideRepoData(preferenceName) return } else { - Timber.d( + if (BuildConfig.DEBUG) Timber.d( "Showing preference %s because the forceHide status is %s and the RealmResults is %s", preferenceName, repoData.isForceHide, @@ -718,7 +718,7 @@ class RepoFragment : PreferenceFragmentCompat() { } } } else { - Timber.d("Hiding preference $preferenceName because it's data is null") + if (BuildConfig.DEBUG) Timber.d("Hiding preference $preferenceName because it's data is null") hideRepoData(preferenceName) return } diff --git a/app/src/main/kotlin/com/fox2code/mmm/settings/SecurityFragment.kt b/app/src/main/kotlin/com/fox2code/mmm/settings/SecurityFragment.kt index 443a9ad..5108f4a 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/settings/SecurityFragment.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/settings/SecurityFragment.kt @@ -13,6 +13,7 @@ import androidx.preference.TwoStatePreference import androidx.security.crypto.EncryptedSharedPreferences import androidx.security.crypto.MasterKey import com.fox2code.foxcompat.app.FoxActivity +import com.fox2code.mmm.BuildConfig import com.fox2code.mmm.MainActivity import com.fox2code.mmm.MainApplication import com.fox2code.mmm.R @@ -88,7 +89,7 @@ class SecurityFragment : PreferenceFragmentCompat() { requireContext().getSystemService(FoxActivity.ALARM_SERVICE) as AlarmManager mgr[AlarmManager.RTC, System.currentTimeMillis() + 100] = mPendingIntent - Timber.d("Restarting app to save showcase mode preference: %s", v) + if (BuildConfig.DEBUG) Timber.d("Restarting app to save showcase mode preference: %s", v) exitProcess(0) // Exit app process }.setNegativeButton(R.string.cancel) { _: DialogInterface?, _: Int -> // Revert to showcase mode on @@ -111,7 +112,7 @@ class SecurityFragment : PreferenceFragmentCompat() { requireContext().getSystemService(FoxActivity.ALARM_SERVICE) as AlarmManager mgr[AlarmManager.RTC, System.currentTimeMillis() + 100] = mPendingIntent - Timber.d("Restarting app to save showcase mode preference: %s", v) + if (BuildConfig.DEBUG) Timber.d("Restarting app to save showcase mode preference: %s", v) exitProcess(0) // Exit app process }.show() } diff --git a/app/src/main/kotlin/com/fox2code/mmm/settings/SettingsActivity.kt b/app/src/main/kotlin/com/fox2code/mmm/settings/SettingsActivity.kt index f6a8d25..7f91cb1 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/settings/SettingsActivity.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/settings/SettingsActivity.kt @@ -38,7 +38,8 @@ import timber.log.Timber import java.sql.Timestamp @Suppress("SENSELESS_COMPARISON") -class SettingsActivity : FoxActivity(), LanguageActivity { +class SettingsActivity : FoxActivity(), LanguageActivity, + PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { lateinit var sharedPreferences: SharedPreferences @SuppressLint("RestrictedApi") @@ -94,7 +95,7 @@ class SettingsActivity : FoxActivity(), LanguageActivity { if (ts.time > buildTime.time) { val pm = packageManager val intent = Intent(this, ExpiredActivity::class.java) - @Suppress("DEPRECATION") val resolveInfo = pm.queryIntentActivities(intent, 0) + val resolveInfo = pm.queryIntentActivities(intent, 0) if (resolveInfo.size > 0) { startActivity(intent) finish() @@ -192,7 +193,7 @@ class SettingsActivity : FoxActivity(), LanguageActivity { findPreference("pref_pkg_info")!!.onPreferenceClickListener = Preference.OnPreferenceClickListener { p: Preference -> versionClicks++ - Timber.d("Version clicks: %d", versionClicks) + if (BuildConfig.DEBUG) Timber.d("Version clicks: %d", versionClicks) if (versionClicks == 7) { versionClicks = 0 openUrl(p.context, "https://www.youtube.com/watch?v=dQw4w9WgXcQ") @@ -266,7 +267,7 @@ class SettingsActivity : FoxActivity(), LanguageActivity { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { points += 1 } - Timber.d("Device performance class: %d", points) + if (BuildConfig.DEBUG) Timber.d("Device performance class: %d", points) return if (points <= 7) { PERFORMANCE_CLASS_LOW } else if (points <= 12) { @@ -276,4 +277,19 @@ class SettingsActivity : FoxActivity(), LanguageActivity { } } } + + override fun onPreferenceStartFragment( + caller: PreferenceFragmentCompat, + pref: Preference + ): Boolean { + val fragment = supportFragmentManager.fragmentFactory.instantiate( + classLoader, pref.fragment.toString() + ) + fragment.arguments = pref.extras + @Suppress("DEPRECATION") fragment.setTargetFragment(caller, 0) + supportFragmentManager.beginTransaction().replace(R.id.settings, fragment) + .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).addToBackStack(null) + .commit() + return true + } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/fox2code/mmm/settings/SharedPreferenceDataStore.kt b/app/src/main/kotlin/com/fox2code/mmm/settings/SharedPreferenceDataStore.kt index 804f7fb..f0535d7 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/settings/SharedPreferenceDataStore.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/settings/SharedPreferenceDataStore.kt @@ -6,19 +6,20 @@ package com.fox2code.mmm.settings import android.content.SharedPreferences import androidx.preference.PreferenceDataStore +import com.fox2code.mmm.BuildConfig import timber.log.Timber class SharedPreferenceDataStore(sharedPreferences: SharedPreferences) : PreferenceDataStore() { private val mSharedPreferences: SharedPreferences init { - Timber.d("SharedPreferenceDataStore: %s", sharedPreferences) + if (BuildConfig.DEBUG) Timber.d("SharedPreferenceDataStore: %s", sharedPreferences) mSharedPreferences = sharedPreferences } val sharedPreferences: SharedPreferences get() { - Timber.d("getSharedPreferences: %s", mSharedPreferences) + if (BuildConfig.DEBUG) Timber.d("getSharedPreferences: %s", mSharedPreferences) return mSharedPreferences } diff --git a/app/src/main/kotlin/com/fox2code/mmm/settings/UpdateFragment.kt b/app/src/main/kotlin/com/fox2code/mmm/settings/UpdateFragment.kt index f7f2561..388c60f 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/settings/UpdateFragment.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/settings/UpdateFragment.kt @@ -86,7 +86,7 @@ class UpdateFragment : PreferenceFragmentCompat() { do { fakeVersion = random.nextInt(10) } while (fakeVersion == 0) - Timber.d("Fake version: %s, count: %s", fakeVersion, i) + if (BuildConfig.DEBUG) Timber.d("Fake version: %s, count: %s", fakeVersion, i) updateableModules["FakeModule $i"] = "1.0.$fakeVersion" } BackgroundUpdateChecker.postNotification( @@ -158,7 +158,7 @@ class UpdateFragment : PreferenceFragmentCompat() { moduleNames[i] = localModuleInfo!!.name // Stringset uses id, we show name checkedItems[i] = stringSet.contains(localModuleInfo.id) - Timber.d("name: %s, checked: %s", moduleNames[i], checkedItems[i]) + if (BuildConfig.DEBUG) Timber.d("name: %s, checked: %s", moduleNames[i], checkedItems[i]) } MaterialAlertDialogBuilder(requireContext()).setTitle(R.string.background_update_check_excludes) .setMultiChoiceItems( @@ -205,7 +205,7 @@ class UpdateFragment : PreferenceFragmentCompat() { val stringSet = sharedPreferences.getStringSet( "pref_background_update_check_excludes_version", HashSet() ) - Timber.d("stringSet: %s", stringSet) + if (BuildConfig.DEBUG) Timber.d("stringSet: %s", stringSet) // for every module, add it's name and a text field to the dialog. the text field should accept a comma separated list of versions val localModuleInfos: Collection = ModuleManager.instance!!.modules.values @@ -263,7 +263,7 @@ class UpdateFragment : PreferenceFragmentCompat() { .setView(scrollView).setPositiveButton( R.string.ok ) { _: DialogInterface?, _: Int -> - Timber.d("ok clicked") + if (BuildConfig.DEBUG) Timber.d("ok clicked") // for every module, get the text field and save it to the stringset val stringSetTemp: MutableSet = HashSet() var prevMod = "" @@ -287,9 +287,9 @@ class UpdateFragment : PreferenceFragmentCompat() { localModuleInfo!!.name.equals(finalprevMod) }.findFirst().orElse(null)!!.id + ":" + text ) - Timber.d("text is %s for %s", text, editText.hint.toString()) + if (BuildConfig.DEBUG) Timber.d("text is %s for %s", text, editText.hint.toString()) } else { - Timber.d("text is empty for %s", editText.hint.toString()) + if (BuildConfig.DEBUG) Timber.d("text is empty for %s", editText.hint.toString()) } } sharedPreferences.edit().putStringSet( diff --git a/app/src/main/kotlin/com/fox2code/mmm/utils/IntentHelper.kt b/app/src/main/kotlin/com/fox2code/mmm/utils/IntentHelper.kt index e1915d2..2d67d22 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/utils/IntentHelper.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/utils/IntentHelper.kt @@ -76,7 +76,7 @@ enum class IntentHelper {; @JvmOverloads fun openUrl(context: Context, url: String?, forceBrowser: Boolean = false) { - Timber.d("Opening url: %s, forced browser %b", url, forceBrowser) + if (BuildConfig.DEBUG) Timber.d("Opening url: %s, forced browser %b", url, forceBrowser) try { val myIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) myIntent.flags = FLAG_GRANT_URI_PERMISSION @@ -85,7 +85,7 @@ enum class IntentHelper {; } startActivity(context, myIntent, false) } catch (e: ActivityNotFoundException) { - Timber.d(e, "Could not find suitable activity to handle url") + if (BuildConfig.DEBUG) Timber.d(e, "Could not find suitable activity to handle url") Toast.makeText( context, FoxActivity.getFoxActivity(context).getString( R.string.no_browser @@ -96,7 +96,7 @@ enum class IntentHelper {; @JvmStatic fun openCustomTab(context: Context, url: String?) { - Timber.d("Opening url: %s in custom tab", url) + if (BuildConfig.DEBUG) Timber.d("Opening url: %s in custom tab", url) try { val viewIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) viewIntent.flags = FLAG_GRANT_URI_PERMISSION @@ -105,7 +105,7 @@ enum class IntentHelper {; tabIntent.addCategory(Intent.CATEGORY_BROWSABLE) startActivityEx(context, tabIntent, viewIntent) } catch (e: ActivityNotFoundException) { - Timber.d(e, "Could not find suitable activity to handle url") + if (BuildConfig.DEBUG) Timber.d(e, "Could not find suitable activity to handle url") Toast.makeText( context, FoxActivity.getFoxActivity(context).getString( R.string.no_browser @@ -389,7 +389,7 @@ enum class IntentHelper {; compatActivity.startActivityForResult(intent, param) { result: Int, data: Intent? -> val uri = data?.data if (uri == null || result == Activity.RESULT_CANCELED) { - Timber.d("invalid uri recieved") + if (BuildConfig.DEBUG) Timber.d("invalid uri recieved") callback.onReceived(destination, null, RESPONSE_ERROR) return@startActivityForResult } diff --git a/app/src/main/kotlin/com/fox2code/mmm/utils/TimberUtils.kt b/app/src/main/kotlin/com/fox2code/mmm/utils/TimberUtils.kt index 6a55839..5c86ee3 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/utils/TimberUtils.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/utils/TimberUtils.kt @@ -27,8 +27,8 @@ object TimberUtils { plant( SentryTimberTree( Sentry.getCurrentHub(), - SentryLevel.ERROR, - SentryLevel.ERROR + SentryLevel.WARNING, + SentryLevel.WARNING ) ) } else { diff --git a/app/src/main/kotlin/com/fox2code/mmm/utils/ZipFileOpener.kt b/app/src/main/kotlin/com/fox2code/mmm/utils/ZipFileOpener.kt index b59e20c..6cdc093 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/utils/ZipFileOpener.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/utils/ZipFileOpener.kt @@ -35,7 +35,7 @@ class ZipFileOpener : FoxActivity() { super.onCreate(savedInstanceState) loading = build(this, R.string.loading, R.string.zip_unpacking) Thread(Runnable { - Timber.d("onCreate: %s", intent) + if (BuildConfig.DEBUG) Timber.d("onCreate: %s", intent) val zipFile: File val uri = intent.data if (uri == null) { @@ -103,7 +103,7 @@ class ZipFileOpener : FoxActivity() { } return@Runnable } else { - Timber.d("onCreate: Zip file is " + zipFile.length() + " bytes") + if (BuildConfig.DEBUG) Timber.d("onCreate: Zip file is " + zipFile.length() + " bytes") } var entry: ZipEntry? var zip: ZipFile? = null @@ -116,13 +116,13 @@ class ZipFileOpener : FoxActivity() { Timber.e("onCreate: Zip file is not a valid magisk module") if (BuildConfig.DEBUG) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - Timber.d( + if (BuildConfig.DEBUG) Timber.d( "onCreate: Zip file contents: %s", zip.stream().map { obj: ZipEntry -> obj.name } .reduce { a: String, b: String -> "$a, $b" }.orElse("empty") ) } else { - Timber.d("onCreate: Zip file contents cannot be listed on this version of android") + if (BuildConfig.DEBUG) Timber.d("onCreate: Zip file contents cannot be listed on this version of android") } } runOnUiThread { @@ -146,7 +146,7 @@ class ZipFileOpener : FoxActivity() { } return@Runnable } - Timber.d("onCreate: Zip file is valid") + if (BuildConfig.DEBUG) Timber.d("onCreate: Zip file is valid") var moduleInfo: String? try { moduleInfo = readModulePropSimple(zip.getInputStream(entry), "name") diff --git a/app/src/main/kotlin/com/fox2code/mmm/utils/io/Files.kt b/app/src/main/kotlin/com/fox2code/mmm/utils/io/Files.kt index 5651c9a..5f9649f 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/utils/io/Files.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/utils/io/Files.kt @@ -9,6 +9,7 @@ import android.net.Uri import android.os.Build import android.provider.OpenableColumns import android.util.Log +import com.fox2code.mmm.BuildConfig import com.fox2code.mmm.MainApplication import com.topjohnwu.superuser.io.SuFile import com.topjohnwu.superuser.io.SuFileInputStream @@ -235,7 +236,7 @@ enum class Files { throw IOException("Unable to create temp unzip dir") } // unzip - Timber.d("Unzipping module to %s", tempUnzipDir.absolutePath) + if (BuildConfig.DEBUG) Timber.d("Unzipping module to %s", tempUnzipDir.absolutePath) try { ZipFile(tempFile).use { zipFile -> var files = zipFile.entries @@ -293,7 +294,7 @@ enum class Files { Timber.e(e, "Unable to zip up module") } } else { - Timber.d("Module does not have a single folder in the top level, skipping") + if (BuildConfig.DEBUG) Timber.d("Module does not have a single folder in the top level, skipping") } } } catch (e: IOException) { diff --git a/app/src/main/kotlin/com/fox2code/mmm/utils/io/net/Http.kt b/app/src/main/kotlin/com/fox2code/mmm/utils/io/net/Http.kt index d489ff1..d563007 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/utils/io/net/Http.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/utils/io/net/Http.kt @@ -248,7 +248,7 @@ enum class Http {; 0, dot ).toInt() } - Timber.d( + if (BuildConfig.DEBUG) Timber.d( "Webview version: %s (%d)", webviewVersion, webviewVersionCode ) hasWebView = @@ -492,7 +492,7 @@ enum class Http {; throw HttpException(e.message, 0) } if (BuildConfig.DEBUG_HTTP) { - Timber.d("doHttpGet: request executed") + if (BuildConfig.DEBUG) Timber.d("doHttpGet: request executed") } // 200/204 == success, 304 == cache valid if (response != null) { @@ -513,7 +513,7 @@ enum class Http {; if (retryAfter != null) { try { val seconds = Integer.parseInt(retryAfter) - Timber.d("Sleeping for $seconds seconds") + if (BuildConfig.DEBUG) Timber.d("Sleeping for $seconds seconds") Thread.sleep(seconds * 1000L) } catch (e: NumberFormatException) { Timber.e(e, "Failed to parse Retry-After header") @@ -523,7 +523,7 @@ enum class Http {; } else {// start with one second and try up to five times if (limitedRetries < 5) { limitedRetries++ - Timber.d("Sleeping for 1 second") + if (BuildConfig.DEBUG) Timber.d("Sleeping for 1 second") try { Thread.sleep(1000L * limitedRetries) } catch (e: InterruptedException) { @@ -539,7 +539,7 @@ enum class Http {; } } if (BuildConfig.DEBUG_HTTP) { - Timber.d("doHttpGet: " + url.replace("=[^&]*".toRegex(), "=****") + " succeeded") + if (BuildConfig.DEBUG) Timber.d("doHttpGet: " + url.replace("=[^&]*".toRegex(), "=****") + " succeeded") } var responseBody = response?.body // Use cache api if used cached response @@ -551,7 +551,7 @@ enum class Http {; } if (BuildConfig.DEBUG_HTTP) { if (responseBody != null) { - Timber.d("doHttpGet: returning " + responseBody.contentLength() + " bytes") + if (BuildConfig.DEBUG) Timber.d("doHttpGet: returning " + responseBody.contentLength() + " bytes") } } return responseBody?.bytes() ?: ByteArray(0) @@ -566,7 +566,7 @@ enum class Http {; @Throws(IOException::class) private fun doHttpPostRaw(url: String, data: String, allowCache: Boolean): Any { - Timber.d("POST %s", url) + if (BuildConfig.DEBUG) Timber.d("POST %s", url) var response: Response? try { response = @@ -590,7 +590,7 @@ enum class Http {; } if (response.isRedirect) { // follow redirect with same method - Timber.d("doHttpPostRaw: following redirect: %s", response.header("Location")) + if (BuildConfig.DEBUG) Timber.d("doHttpPostRaw: following redirect: %s", response.header("Location")) response = (if (allowCache) getHttpClientWithCache() else getHttpClient())!!.newCall( Request.Builder().url( @@ -609,7 +609,7 @@ enum class Http {; if (retryAfter != null) { try { val seconds = Integer.parseInt(retryAfter) - Timber.d("Sleeping for $seconds seconds") + if (BuildConfig.DEBUG) Timber.d("Sleeping for $seconds seconds") Thread.sleep(seconds * 1000L) } catch (e: NumberFormatException) { Timber.e(e, "Failed to parse Retry-After header") @@ -619,7 +619,7 @@ enum class Http {; } else {// start with one second and try up to five times if (limitedRetries < 5) { limitedRetries++ - Timber.d("Sleeping for 1 second") + if (BuildConfig.DEBUG) Timber.d("Sleeping for 1 second") try { Thread.sleep(1000L * limitedRetries) } catch (e: InterruptedException) { @@ -672,7 +672,7 @@ enum class Http {; if (retryAfter != null) { try { val seconds = Integer.parseInt(retryAfter) - Timber.d("Sleeping for $seconds seconds") + if (BuildConfig.DEBUG) Timber.d("Sleeping for $seconds seconds") Thread.sleep(seconds * 1000L) } catch (e: NumberFormatException) { Timber.e(e, "Failed to parse Retry-After header") @@ -682,7 +682,7 @@ enum class Http {; } else {// start with one second and try up to five times if (limitedRetries < 5) { limitedRetries++ - Timber.d("Sleeping for 1 second") + if (BuildConfig.DEBUG) Timber.d("Sleeping for 1 second") try { Thread.sleep(1000L * limitedRetries) } catch (e: InterruptedException) { @@ -774,19 +774,19 @@ enum class Http {; val systemSaysYes = networkCapabilities != null && networkCapabilities.hasCapability( NetworkCapabilities.NET_CAPABILITY_INTERNET ) - Timber.d("System says we have internet: $systemSaysYes") + if (BuildConfig.DEBUG) Timber.d("System says we have internet: $systemSaysYes") // if we don't already have a listener, add one, so we can invalidate the cache when the network changes if (connectivityListener == null) { connectivityListener = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { super.onAvailable(network) - Timber.d("Network became available") + if (BuildConfig.DEBUG) Timber.d("Network became available") lastConnectivityCheck = 0 } override fun onLost(network: Network) { super.onLost(network) - Timber.d("Network became unavailable") + if (BuildConfig.DEBUG) Timber.d("Network became unavailable") lastConnectivityCheck = 0 } } @@ -803,7 +803,7 @@ enum class Http {; Timber.e(e, "Failed to check internet connection") false } - Timber.d("We say we have internet: $hasInternet") + if (BuildConfig.DEBUG) Timber.d("We say we have internet: $hasInternet") lastConnectivityCheck = System.currentTimeMillis() @Suppress("KotlinConstantConditions") lastConnectivityResult = 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 14e2ad5..c50fa23 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 @@ -18,6 +18,7 @@ import io.sentry.Breadcrumb import io.sentry.Hint import io.sentry.Sentry import io.sentry.SentryEvent +import io.sentry.SentryLevel import io.sentry.SentryOptions.BeforeBreadcrumbCallback import io.sentry.SentryOptions.BeforeSendCallback import io.sentry.android.core.SentryAndroid @@ -76,8 +77,8 @@ object SentryMain { } isSentryEnabled = sharedPreferences.getBoolean("pref_crash_reporting_enabled", false) // set sentryEnabled on preference change of pref_crash_reporting_enabled - sharedPreferences.registerOnSharedPreferenceChangeListener { sharedPreferences1: SharedPreferences, s: String -> - if (s == "pref_crash_reporting_enabled") { + sharedPreferences.registerOnSharedPreferenceChangeListener { sharedPreferences1: SharedPreferences, s: String? -> + if (s!== null && s == "pref_crash_reporting_enabled") { isSentryEnabled = sharedPreferences1.getBoolean(s, false) } } @@ -128,6 +129,16 @@ object SentryMain { return@BeforeSendCallback null } crashExceptionId = event?.eventId + // if debug build, log everything, but for release only log warnings and errors + if (!BuildConfig.DEBUG) { + if (event?.level == SentryLevel.DEBUG || event?.level == SentryLevel.INFO) { + return@BeforeSendCallback null + } + } + // remove all failed to fetch data messages + if (event?.message?.message?.contains("Failed to fetch") == true) { + return@BeforeSendCallback null + } event } // Filter breadcrumb content from crash report. diff --git a/app/src/main/res/drawable/search_bar_bg.xml b/app/src/main/res/drawable/search_bar_bg.xml new file mode 100644 index 0000000..53bd760 --- /dev/null +++ b/app/src/main/res/drawable/search_bar_bg.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ad3fbb5..e2e5436 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -401,4 +401,5 @@ 6 hours 12 hours Daily + experimental and may have issues. Compatibility with modules is not guaraunteed.]]> diff --git a/build.gradle.kts b/build.gradle.kts index 971f997..476e5d4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,7 +13,7 @@ buildscript { gradlePluginPortal() } dependencies { - classpath("com.android.tools.build:gradle:8.0.2") + classpath("com.android.tools.build:gradle:8.1.1") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.22") classpath("com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:10.8.3")