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 411181a..514815f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,7 +2,6 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' -apply plugin: 'io.fabric' apply plugin: 'jacoco' def keystoreProperties = new Properties() @@ -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' @@ -42,6 +52,9 @@ android { versionName "0.8.2" 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 { @@ -95,7 +108,6 @@ dependencies { implementation 'com.commonsware.cwac:anddown:0.3.0' implementation 'com.google.firebase:firebase-core:17.2.3' implementation 'com.android.billingclient:billing:2.1.0' - implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1' implementation "androidx.core:core-ktx:1.2.0" implementation 'androidx.browser:browser:1.2.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" @@ -107,9 +119,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 169640c..7db59f2 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/MarkdownApplication.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/MarkdownApplication.kt @@ -1,27 +1,35 @@ package com.wbrawner.simplemarkdown import android.app.Application +import android.content.Context import android.os.StrictMode -import com.wbrawner.simplemarkdown.utility.CrashlyticsErrorHandler +import androidx.preference.PreferenceManager +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() { if (BuildConfig.DEBUG) { StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder() .detectAll() - .penaltyDeath() + .penaltyLog() .build()) StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder() .detectAll() .penaltyLog() - .penaltyDeath() .build()) } super.onCreate() } + + override fun attachBaseContext(base: Context?) { + super.attachBaseContext(base) + val enableErrorLogging = PreferenceManager.getDefaultSharedPreferences(this) + .getBoolean(getString(R.string.pref_key_error_reports_enabled), true) + if (enableErrorLogging) 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 63f5e43..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,33 +1,56 @@ package com.wbrawner.simplemarkdown.utility -import android.content.Context +import android.app.Application import android.util.Log -import com.crashlytics.android.Crashlytics +import com.evernote.android.job.JobRequest import com.wbrawner.simplemarkdown.BuildConfig -import io.fabric.sdk.android.Fabric +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 init(context: Context) + fun init(application: Application) fun reportException(t: Throwable, message: String? = null) } -class CrashlyticsErrorHandler : ErrorHandler { +class AcraErrorHandler : ErrorHandler { private val isInitialized = AtomicBoolean(false) - override fun init(context: Context) { + override fun init(application: Application) { + if (BuildConfig.ACRA_URL.isBlank() + || BuildConfig.ACRA_USER.isBlank() + || BuildConfig.ACRA_PASS.isBlank()) { + return + } if (!isInitialized.getAndSet(true)) { - Fabric.with(context, Crashlytics()) + 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 } if (!isInitialized.get()) return - Crashlytics.logException(t) + ACRA.getErrorReporter().handleException(t) } } \ 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 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/build.gradle b/build.gradle index 7a828b3..18ca95c 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,6 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.6.1' classpath 'com.google.gms:google-services:4.3.3' - classpath 'io.fabric.tools:gradle:1.31.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } }