diff --git a/app/.gitignore b/app/.gitignore index ebc6b31..659dd9f 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -1,3 +1,4 @@ /build *.apk /release +acra.properties diff --git a/app/build.gradle b/app/build.gradle index 06acb88..134d805 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,7 +3,6 @@ apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' apply plugin: 'jacoco' -apply plugin: 'com.google.firebase.crashlytics' def keystoreProperties = new Properties() try { @@ -17,6 +16,17 @@ try { keystoreProperties['storePassword'] = "" } +def acraProperties = new Properties() +try { + def acraPropertiesFile = project.file("acra.properties") + acraProperties.load(new FileInputStream(acraPropertiesFile)) +} catch (FileNotFoundException ignored) { + logger.warn("Unable to load ACRA properties. Error reporting won't be available") + acraProperties['url'] = "" + acraProperties['user'] = "" + acraProperties['pass'] = "" +} + android { configurations.all { resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1' @@ -45,6 +55,9 @@ android { versionName "0.8.3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" buildConfigField "boolean", "ENABLE_CUSTOM_CSS", "false" + buildConfigField "String", "ACRA_URL", "\"${acraProperties['url']}\"" + buildConfigField "String", "ACRA_USER", "\"${acraProperties['user']}\"" + buildConfigField "String", "ACRA_PASS", "\"${acraProperties['pass']}\"" } signingConfigs { release { @@ -97,10 +110,8 @@ dependencies { implementation 'com.google.android.material:material:1.1.0' implementation 'androidx.legacy:legacy-support-v13:1.0.0' implementation 'com.commonsware.cwac:anddown:0.3.0' + implementation 'com.google.firebase:firebase-core:17.4.1' implementation 'com.android.billingclient:billing:2.2.0' - implementation 'com.google.firebase:firebase-core:17.3.0' - implementation 'com.google.firebase:firebase-crashlytics:17.0.0-beta04' - implementation 'com.google.firebase:firebase-analytics:17.3.0' implementation "androidx.core:core-ktx:1.2.0" implementation 'androidx.browser:browser:1.2.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" @@ -112,9 +123,14 @@ dependencies { implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" kapt "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" implementation 'eu.crydee:syllable-counter:4.0.2' + + def acraVersion = '5.2.0-rc1' + implementation "ch.acra:acra-http:$acraVersion" + implementation "ch.acra:acra-advanced-scheduler:$acraVersion" } apply plugin: 'com.google.gms.google-services' + repositories { mavenCentral() } diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/MarkdownApplication.kt b/app/src/main/java/com/wbrawner/simplemarkdown/MarkdownApplication.kt index 9de53cc..e4060b1 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/MarkdownApplication.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/MarkdownApplication.kt @@ -1,13 +1,14 @@ package com.wbrawner.simplemarkdown import android.app.Application +import android.content.Context import android.os.StrictMode -import com.wbrawner.simplemarkdown.utility.CrashlyticsErrorHandler +import com.wbrawner.simplemarkdown.utility.AcraErrorHandler import com.wbrawner.simplemarkdown.utility.ErrorHandler class MarkdownApplication : Application() { val errorHandler: ErrorHandler by lazy { - CrashlyticsErrorHandler() + AcraErrorHandler() } override fun onCreate() { @@ -23,4 +24,9 @@ class MarkdownApplication : Application() { } super.onCreate() } + + override fun attachBaseContext(base: Context?) { + super.attachBaseContext(base) + errorHandler.init(this) + } } diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/utility/ErrorHandler.kt b/app/src/main/java/com/wbrawner/simplemarkdown/utility/ErrorHandler.kt index 4ee20dd..bb18cb9 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/utility/ErrorHandler.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/utility/ErrorHandler.kt @@ -1,27 +1,56 @@ package com.wbrawner.simplemarkdown.utility +import android.app.Application import android.util.Log -import com.google.firebase.crashlytics.FirebaseCrashlytics +import com.evernote.android.job.JobRequest import com.wbrawner.simplemarkdown.BuildConfig +import org.acra.ACRA +import org.acra.config.CoreConfigurationBuilder +import org.acra.config.HttpSenderConfigurationBuilder +import org.acra.config.SchedulerConfigurationBuilder +import org.acra.data.StringFormat +import org.acra.sender.HttpSender +import java.util.concurrent.atomic.AtomicBoolean interface ErrorHandler { - fun enable(enable: Boolean) + fun init(application: Application) fun reportException(t: Throwable, message: String? = null) } -class CrashlyticsErrorHandler : ErrorHandler { - private val crashlytics = FirebaseCrashlytics.getInstance() +class AcraErrorHandler : ErrorHandler { + private val isInitialized = AtomicBoolean(false) - override fun enable(enable: Boolean) { - crashlytics.setCrashlyticsCollectionEnabled(enable) + override fun init(application: Application) { + if (BuildConfig.ACRA_URL.isBlank() + || BuildConfig.ACRA_USER.isBlank() + || BuildConfig.ACRA_PASS.isBlank()) { + return + } + if (!isInitialized.getAndSet(true)) { + val builder = CoreConfigurationBuilder(application) + .setBuildConfigClass(BuildConfig::class.java) + .setReportFormat(StringFormat.JSON) + builder.getPluginConfigurationBuilder(HttpSenderConfigurationBuilder::class.java) + .setUri(BuildConfig.ACRA_URL) + .setHttpMethod(HttpSender.Method.POST) + .setBasicAuthLogin(BuildConfig.ACRA_USER) + .setBasicAuthPassword(BuildConfig.ACRA_PASS) + .setEnabled(true) + builder.getPluginConfigurationBuilder(SchedulerConfigurationBuilder::class.java) + .setRequiresNetworkType(JobRequest.NetworkType.UNMETERED) + .setRequiresBatteryNotLow(true) + .setEnabled(true) + ACRA.init(application, builder) + } } override fun reportException(t: Throwable, message: String?) { @Suppress("ConstantConditionIf") if (BuildConfig.DEBUG) { - Log.e("CrashlyticsErrorHandler", "Caught exception: $message", t) + Log.e("AcraErrorHandler", "Caught exception: $message", t) return } - crashlytics.recordException(t) + if (!isInitialized.get()) return + ACRA.getErrorReporter().handleException(t) } } \ No newline at end of file diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/MainActivity.kt b/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/MainActivity.kt index ba7a2ba..78a6825 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/MainActivity.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/MainActivity.kt @@ -20,7 +20,6 @@ import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.lifecycle.Observer import androidx.preference.PreferenceManager -import com.wbrawner.simplemarkdown.MarkdownApplication import com.wbrawner.simplemarkdown.R import com.wbrawner.simplemarkdown.utility.hideKeyboard import com.wbrawner.simplemarkdown.view.adapter.EditPagerAdapter @@ -70,17 +69,6 @@ class MainActivity : AppCompatActivity(), ActivityCompat.OnRequestPermissionsRes } } - override fun onStart() { - super.onStart() - launch { - withContext(Dispatchers.IO) { - val enableErrorReports = PreferenceManager.getDefaultSharedPreferences(this@MainActivity) - .getBoolean(getString(R.string.error_reports_enabled), true) - (application as MarkdownApplication).errorHandler.enable(enableErrorReports) - } - } - } - override fun onUserLeaveHint() { super.onUserLeaveHint() launch { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 499ba52..e32611c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -34,7 +34,7 @@ Lock Swiping Select Privacy - crashlytics.enable + acra.enable Enable automated error reports Error reports will not be sent Error reports will be sent diff --git a/app/src/main/res/xml/pref_general.xml b/app/src/main/res/xml/pref_general.xml index 98aa6b3..be5bde3 100644 --- a/app/src/main/res/xml/pref_general.xml +++ b/app/src/main/res/xml/pref_general.xml @@ -19,7 +19,7 @@ android:title="@string/title_dark_mode" /> diff --git a/build.gradle b/build.gradle index f3727a0..239791a 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,6 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.6.3' classpath 'com.google.gms:google-services:4.3.3' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0-beta04' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } }