From 1cc0063b1599296583902ed6ab924c7e7758da31 Mon Sep 17 00:00:00 2001 From: William Brawner Date: Wed, 10 Jun 2020 10:16:53 -0700 Subject: [PATCH] Replace Crashlytics with Sentry Signed-off-by: William Brawner --- .gitignore | 1 + app/build.gradle | 9 ++++-- app/src/main/AndroidManifest.xml | 5 +++- app/src/main/assets/Privacy Policy.md | 19 ++++++------ .../simplemarkdown/MarkdownApplication.kt | 8 +++-- .../simplemarkdown/utility/ErrorHandler.kt | 29 +++++++++++++++---- .../view/activity/SettingsActivity.kt | 5 +--- app/src/main/res/values/strings.xml | 2 +- build.gradle | 4 +-- gradle/wrapper/gradle-wrapper.properties | 4 +-- sentry.properties.sample | 4 +++ 11 files changed, 59 insertions(+), 31 deletions(-) create mode 100644 sentry.properties.sample diff --git a/.gitignore b/.gitignore index 07544b8..6a955c3 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ *.log keystore.properties *.jks +sentry.properties diff --git a/app/build.gradle b/app/build.gradle index a5fb7f6..e9a91d7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' apply plugin: 'jacoco' -apply plugin: 'com.google.firebase.crashlytics' +apply plugin: 'io.sentry.android.gradle' def keystoreProperties = new Properties() try { @@ -44,6 +44,9 @@ android { versionCode 26 versionName "0.8.4" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + manifestPlaceholders = [ + sentryDsn: "https://399270639b2e4b10a028a2be9192d1d3@sentry.brawner.dev/2" + ] buildConfigField "boolean", "ENABLE_CUSTOM_CSS", "false" } signingConfigs { @@ -99,11 +102,10 @@ dependencies { implementation 'com.commonsware.cwac:anddown:0.3.0' 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" + implementation 'io.sentry:sentry-android:2.1.6' def coroutines_version = "1.3.0-RC2" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" @@ -117,6 +119,7 @@ dependencies { apply plugin: 'com.google.gms.google-services' repositories { mavenCentral() + jcenter() } jacoco { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 44868d3..46a1d34 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -67,7 +67,10 @@ + diff --git a/app/src/main/assets/Privacy Policy.md b/app/src/main/assets/Privacy Policy.md index a542f31..b631fca 100644 --- a/app/src/main/assets/Privacy Policy.md +++ b/app/src/main/assets/Privacy Policy.md @@ -1,13 +1,12 @@ ## Privacy Policy First and foremost, Simple Markdown DOES NOT collect any personally identifiable information. The - internet access permission is requested primarily for retrieving images from the internet in - case you embed them in your markdown, but it also allows me to send automated error and crash - reports to myself whenever the app runs into an issue. These error reports are opt-out, and are - powered by [Firebase Crashlytics] (https://firebase.google.com/docs/crashlytics/), which is a - free error reporting solution provided by Google. These error reports are used exclusively for - fixing problems that occur while you're using the app, along with some analytics info like how - long you use the app for, how often, and which features of the app you use. This helps me to - determine how to spend my very limited time on building out new features. I'll have to defer to - [Google's Privacy Policy](https://policies.google.com/privacy) to explain how they handle the - data. As for me, I don't knowingly or willingly sell or trade your data. +internet access permission is requested primarily for retrieving images from the internet in +case you embed them in your markdown, but it also allows me to send automated error and crash +reports to myself whenever the app runs into an issue. These automated reports are powered by my own +self-hosted version of [Sentry] (https://sentry.io/), which is a free and open source error +reporting solution. These error reports are used exclusively for fixing problems that occur while +you're using the app. For more information on the kinds of data that may be sent in these automated +error reports, please see the [relevant documentation](https://docs.sentry.io/platforms/android/#context) +on Sentry's website. If you would like to opt-out of these error reports, please visit the in-app +settings page to disable the toggle for error reports. diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/MarkdownApplication.kt b/app/src/main/java/com/wbrawner/simplemarkdown/MarkdownApplication.kt index 9de53cc..ab44f35 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/MarkdownApplication.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/MarkdownApplication.kt @@ -2,15 +2,19 @@ package com.wbrawner.simplemarkdown import android.app.Application import android.os.StrictMode -import com.wbrawner.simplemarkdown.utility.CrashlyticsErrorHandler +import androidx.preference.PreferenceManager import com.wbrawner.simplemarkdown.utility.ErrorHandler +import com.wbrawner.simplemarkdown.utility.SentryErrorHandler class MarkdownApplication : Application() { val errorHandler: ErrorHandler by lazy { - CrashlyticsErrorHandler() + SentryErrorHandler() } override fun onCreate() { + val enableErrorReports = PreferenceManager.getDefaultSharedPreferences(this) + .getBoolean(getString(R.string.error_reports_enabled), true) + errorHandler.init(this, enableErrorReports) if (BuildConfig.DEBUG) { StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder() .detectAll() 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..fbdd3d5 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,44 @@ package com.wbrawner.simplemarkdown.utility +import android.content.Context import android.util.Log -import com.google.firebase.crashlytics.FirebaseCrashlytics import com.wbrawner.simplemarkdown.BuildConfig +import io.sentry.android.core.SentryAndroid +import io.sentry.core.Sentry +import java.util.concurrent.atomic.AtomicBoolean interface ErrorHandler { + fun init(context: Context, enable: Boolean) fun enable(enable: Boolean) fun reportException(t: Throwable, message: String? = null) } -class CrashlyticsErrorHandler : ErrorHandler { - private val crashlytics = FirebaseCrashlytics.getInstance() +class SentryErrorHandler : ErrorHandler { + private lateinit var enabled: AtomicBoolean + + override fun init(context: Context, enable: Boolean) { + enabled = AtomicBoolean(enable) + SentryAndroid.init(context) { options -> + options.setBeforeSend { event, _ -> + if (enabled.get()) { + event + } else { + null + } + } + } + } override fun enable(enable: Boolean) { - crashlytics.setCrashlyticsCollectionEnabled(enable) + enabled.set(enable) } override fun reportException(t: Throwable, message: String?) { @Suppress("ConstantConditionIf") if (BuildConfig.DEBUG) { - Log.e("CrashlyticsErrorHandler", "Caught exception: $message", t) + Log.e("SentryErrorHandler", "Caught exception: $message", t) return } - crashlytics.recordException(t) + Sentry.captureException(t) } } \ No newline at end of file diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/SettingsActivity.kt b/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/SettingsActivity.kt index 1cb3b05..a76d449 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/SettingsActivity.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/SettingsActivity.kt @@ -3,7 +3,6 @@ package com.wbrawner.simplemarkdown.view.activity import android.os.Bundle import android.view.MenuItem import androidx.appcompat.app.AppCompatActivity - import com.wbrawner.simplemarkdown.R class SettingsActivity : AppCompatActivity() { @@ -12,9 +11,7 @@ class SettingsActivity : AppCompatActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_settings) setSupportActionBar(findViewById(R.id.toolbar)) - if (supportActionBar != null) { - supportActionBar!!.setDisplayHomeAsUpEnabled(true) - } + supportActionBar?.setDisplayHomeAsUpEnabled(true) } override fun onOptionsItemSelected(item: MenuItem): Boolean { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 499ba52..9c19fa9 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 + errors.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 f3727a0..7ba4586 100644 --- a/build.gradle +++ b/build.gradle @@ -7,9 +7,9 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.6.3' + classpath 'com.android.tools.build:gradle:4.0.0' classpath 'com.google.gms:google-services:4.3.3' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0-beta04' + classpath 'io.sentry:sentry-android-gradle-plugin:1.7.34' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1da66c8..7730d7d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Mar 19 08:56:07 CST 2020 +#Wed Jun 10 07:53:53 MST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip diff --git a/sentry.properties.sample b/sentry.properties.sample new file mode 100644 index 0000000..243594f --- /dev/null +++ b/sentry.properties.sample @@ -0,0 +1,4 @@ +defaults.url=https://sentry.brawner.dev/ +defaults.project=simplemarkdown +defaults.org=wbrawner +auth.token=