diff --git a/app/src/main/kotlin/com/fox2code/mmm/CrashHandler.kt b/app/src/main/kotlin/com/fox2code/mmm/CrashHandler.kt index 4e4596d..0052ebb 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/CrashHandler.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/CrashHandler.kt @@ -53,7 +53,11 @@ class CrashHandler : FoxActivity() { } // force sentry to send all events Sentry.flush(2000) - val lastEventId = MainApplication.getSharedPreferences("sentry")?.getString("lastEventId", "") + var lastEventId = intent.getStringExtra("lastEventId") + // if event id is all zeros, set it to "". test this by matching the regex ^0+$ (all zeros) + if (lastEventId?.matches("^0+$".toRegex()) == true) { + lastEventId = "" + } Timber.d( "CrashHandler.onCreate: lastEventId=%s, crashReportingEnabled=%s", lastEventId, @@ -65,9 +69,11 @@ class CrashHandler : FoxActivity() { val email = findViewById(R.id.feedback_email) val description = findViewById(R.id.feedback_message) val submit = findViewById(R.id.feedback_submit) - if (lastEventId == "" && crashReportingEnabled) { + 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.") + submit.visibility = View.GONE + findViewById(R.id.feedback_text).setText(R.string.no_sentry_id) } else { // if lastEventId is not null, enable the feedback name, email, message, and submit button email.isEnabled = true @@ -135,7 +141,7 @@ class CrashHandler : FoxActivity() { finish() startActivity(packageManager.getLaunchIntentForPackage(packageName)) } - } else { + } else if (!crashReportingEnabled) { // set feedback_text to "Crash reporting is disabled" (findViewById(R.id.feedback_text) as MaterialTextView).setText(R.string.sentry_enable_nag) submit.setOnClickListener { _: View? -> diff --git a/app/src/main/kotlin/com/fox2code/mmm/MainApplication.kt b/app/src/main/kotlin/com/fox2code/mmm/MainApplication.kt index 0f4dc45..f5d91b0 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/MainApplication.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/MainApplication.kt @@ -54,7 +54,6 @@ import java.text.SimpleDateFormat import java.util.Date import java.util.Random import kotlin.math.abs -import kotlin.math.max @Suppress("unused", "MemberVisibilityCanBePrivate") class MainApplication : FoxApplication(), Configuration.Provider { @@ -129,7 +128,7 @@ class MainApplication : FoxApplication(), Configuration.Provider { markwonThemeContext = FoxThemeWrapper(this, managerThemeResId) contextThemeWrapper = markwonThemeContext } - val markwon = + this.markwon = Markwon.builder(contextThemeWrapper!!).usePlugin(HtmlPlugin.create()).usePlugin( ImagesPlugin.create().addSchemeHandler( OkHttpNetworkSchemeHandler.create( @@ -337,6 +336,7 @@ class MainApplication : FoxApplication(), Configuration.Provider { Timber.w("ANDROIDACY_CLIENT_ID is empty, disabling AndroidacyRepoData 1") editor.apply() } + getMarkwon() } private val intent: Intent? @@ -538,44 +538,12 @@ class MainApplication : FoxApplication(), Configuration.Provider { val mContext: Context? = INSTANCE name += "x" if (mSharedPrefs == null) { - Timber.d("Creating shared prefs map") mSharedPrefs = HashMap() } - /* - this part is only here because with added encryption, parts of code that were previously calling this over and over again or on each invocation of a method are causing performance issues. - */ - if (BuildConfig.DEBUG) { - // get file, function, and line number - val stackTrace = Thread.currentThread().stackTrace - // get the caller of this method - val caller = stackTrace[3] - Timber.d( - "Shared prefs file: %s, caller: %s:%d in %s", - name, - caller.fileName, - caller.lineNumber, - caller.methodName - ) - // add the caller to an array. if the last 3 callers are the same, then we are in a loop, log at error level - callers.add(name + ":" + caller.lineNumber + ":" + caller.methodName) - // get the last 3 callers - val last3: List = callers.subList(max(callers.size - 3, 0), callers.size) - // if the last 3 callers are the same, then we are in a loop, log at error level - if (((last3.size == 3) && last3[0] == last3[1]) && last3[1] == last3[2]) { - Timber.e( - "Shared prefs loop detected. File: %s, caller: %s:%d", - name, - caller.methodName, - caller.lineNumber - ) - } - } if (mSharedPrefs!!.containsKey(name)) { - Timber.d("Returning cached shared prefs") return mSharedPrefs!![name] as SharedPreferences? } return try { - Timber.d("Creating encrypted shared prefs") val masterKey = MasterKey.Builder(mContext!!).setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build() @@ -594,6 +562,10 @@ class MainApplication : FoxApplication(), Configuration.Provider { } } + fun clearCachedSharedPrefs() { + mSharedPrefs = null + } + fun checkSecret(intent: Intent?): Boolean { return intent != null && intent.getLongExtra("secret", secret.inv()) == secret } diff --git a/app/src/main/kotlin/com/fox2code/mmm/markdown/MarkdownActivity.kt b/app/src/main/kotlin/com/fox2code/mmm/markdown/MarkdownActivity.kt index e82eb9c..60b69ed 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/markdown/MarkdownActivity.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/markdown/MarkdownActivity.kt @@ -108,7 +108,7 @@ class MarkdownActivity : FoxActivity() { Timber.i("Done!") runOnUiThread { footer?.minimumHeight = this.navigationBarHeight - MainApplication.INSTANCE!!.markwon!!.setMarkdown( + MainApplication.INSTANCE!!.markwon?.setMarkdown( textView, MarkdownUrlLinker.urlLinkify(markdown) ) 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 51ffcbf..ffd3089 100644 --- a/app/src/main/kotlin/com/fox2code/mmm/repo/RepoManager.kt +++ b/app/src/main/kotlin/com/fox2code/mmm/repo/RepoManager.kt @@ -207,7 +207,10 @@ class RepoManager private constructor(mainApplication: MainApplication) : SyncMa Timber.e(e) } updatedModules++ - updateListener.update(STEP1 + STEP2 / (if (moduleToUpdate != 0) moduleToUpdate else 1) * updatedModules) + // update the update listener with step1 + computed step 2 (which is updated modules / total modules / total repos) + updateListener.update( + STEP1 + (STEP2 / (moduleToUpdate / updatedModules) / repoDatas.size) + ) } for (repoModule in repoUpdaters[i]!!.toApply()!!) { if (repoModule.moduleInfo.flags and ModuleInfo.FLAG_METADATA_INVALID == 0) { @@ -268,11 +271,11 @@ class RepoManager private constructor(mainApplication: MainApplication) : SyncMa } repoLastErrorName = repoUpdaters[i]!!.repoData.name } - updateListener.update(STEP1 + STEP2 + STEP3 / repoDatas.size * (i + 1)) + updateListener.update(STEP1 + (STEP2 * (i / repoUpdaters.size))) } } Timber.i("Got " + modules.size + " modules!") - updateListener.update(1.0) + updateListener.update(STEP1 + STEP2 + STEP3) } fun updateEnabledStates() { 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 1bdc66e..133f1c2 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 @@ -29,6 +29,7 @@ import com.fox2code.mmm.installer.InstallerInitializer.Companion.peekMagiskPath import com.fox2code.mmm.installer.InstallerInitializer.Companion.peekMagiskVersion import com.fox2code.mmm.utils.io.Files.Companion.makeBuffer import com.google.net.cronet.okhttptransport.CronetInterceptor +import io.sentry.android.okhttp.SentryOkHttpInterceptor import okhttp3.Cache import okhttp3.Dns import okhttp3.HttpUrl.* @@ -351,6 +352,9 @@ enum class Http {; httpclientBuilder.addInterceptor(loggingInterceptor) } + // add sentry interceptor + httpclientBuilder.addInterceptor(SentryOkHttpInterceptor()) + // Add cronet interceptor // init cronet try { 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 b80e0f0..be2356a 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 @@ -5,7 +5,6 @@ package com.fox2code.mmm.utils.sentry import android.annotation.SuppressLint -import android.content.Context import android.content.Intent import android.content.SharedPreferences import android.net.Uri @@ -25,6 +24,7 @@ import io.sentry.android.core.SentryAndroid import io.sentry.android.core.SentryAndroidOptions import io.sentry.android.fragment.FragmentLifecycleIntegration import io.sentry.android.timber.SentryTimberIntegration +import io.sentry.protocol.SentryId import org.matomo.sdk.extra.TrackHelper import timber.log.Timber @@ -32,6 +32,7 @@ object SentryMain { const val IS_SENTRY_INSTALLED = true private var isCrashing = false private var isSentryEnabled = false + private var crashExceptionId: SentryId? = null /** * Initialize Sentry @@ -42,6 +43,7 @@ object SentryMain { fun initialize(mainApplication: MainApplication) { Thread.setDefaultUncaughtExceptionHandler { _: Thread?, throwable: Throwable -> isCrashing = true + MainApplication.clearCachedSharedPrefs() TrackHelper.track().exception(throwable).with(MainApplication.INSTANCE!!.tracker) // open crash handler and exit val intent = Intent(mainApplication, CrashHandler::class.java) @@ -55,6 +57,12 @@ object SentryMain { intent.putExtra("crashReportingEnabled", isSentryEnabled) // add isCrashing to intent intent.putExtra("isCrashing", isCrashing) + // add crashExceptionId to intent + if (crashExceptionId != null) { + intent.putExtra("lastEventId", crashExceptionId!!.toString()) + } else { + intent.putExtra("lastEventId", "") + } intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) Timber.e("Starting crash handler") mainApplication.startActivity(intent) @@ -119,15 +127,7 @@ object SentryMain { if (!isSentryEnabled) { return@BeforeSendCallback null } - // store eventid in prefs - val editor = - MainApplication.INSTANCE!!.getSharedPreferences( - "sentry", - Context.MODE_PRIVATE - ) - .edit() - editor.putString("lastEventId", event!!.eventId.toString()) - editor.commit() // commit so we immediately cache if crashing + crashExceptionId = event?.eventId event } // Filter breadcrumb content from crash report. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c1a9e81..e0672cc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -387,4 +387,5 @@ Error in opening module notes. Logs may have the reason. Submit feedback Potential SSL interception detected. + Unable to sumbit feedback - no event ID from Sentry. The last event may not have sent.