From bf36837b04a8a9e071a863632949b50fb758b3d9 Mon Sep 17 00:00:00 2001 From: Nik Clayton Date: Tue, 12 Dec 2023 23:25:09 +0100 Subject: [PATCH] feat: Allow the user to report crashes in orange builds (#317) Add a dependency on ACRA (in orange builds only), and catch crashes. The user is given the option to e-mail the crash report data to the support address, and can view and edit/redact the data before doing so. --- app/build.gradle.kts | 2 + .../blue/kotlin/app/pachli/CrashReporter.kt | 23 +++++++++ .../main/java/app/pachli/PachliApplication.kt | 7 +++ app/src/main/res/values/strings.xml | 14 +++++- .../orange/kotlin/app/pachli/CrashReporter.kt | 47 +++++++++++++++++++ .../main/kotlin/app/pachli/PachliFlavor.kt | 4 +- gradle/libs.versions.toml | 4 ++ 7 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 app/src/blue/kotlin/app/pachli/CrashReporter.kt create mode 100644 app/src/orange/kotlin/app/pachli/CrashReporter.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f3f2d199e..2f7e13995 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -189,6 +189,8 @@ dependencies { debugImplementation(libs.leakcanary) + orangeImplementation(libs.bundles.acra) + testImplementation(projects.core.testing) testImplementation(libs.androidx.test.junit) testImplementation(libs.robolectric) diff --git a/app/src/blue/kotlin/app/pachli/CrashReporter.kt b/app/src/blue/kotlin/app/pachli/CrashReporter.kt new file mode 100644 index 000000000..b7273aeb0 --- /dev/null +++ b/app/src/blue/kotlin/app/pachli/CrashReporter.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2023 Pachli Association + * + * This file is a part of Pachli. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * Pachli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Pachli; if not, + * see . + */ + +package app.pachli + +import android.app.Application + +/** Do nothing in blue builds */ +fun initCrashReporter(app: Application) {} diff --git a/app/src/main/java/app/pachli/PachliApplication.kt b/app/src/main/java/app/pachli/PachliApplication.kt index d492601e3..e0093bfde 100644 --- a/app/src/main/java/app/pachli/PachliApplication.kt +++ b/app/src/main/java/app/pachli/PachliApplication.kt @@ -18,6 +18,7 @@ package app.pachli import android.app.Application +import android.content.Context import androidx.core.content.edit import androidx.work.Constraints import androidx.work.ExistingPeriodicWorkPolicy @@ -56,6 +57,12 @@ class PachliApplication : Application() { @Inject lateinit var sharedPreferencesRepository: SharedPreferencesRepository + override fun attachBaseContext(base: Context?) { + super.attachBaseContext(base) + + initCrashReporter(this) + } + override fun onCreate() { // Uncomment me to get StrictMode violation logs // if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f656cdb9d..cfb3ac77b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -752,4 +752,16 @@ %1$s You may need to restart your device This version of Pachli may trigger an Android bug on some devices, and show broken animations.\n\nFor example, when tapping a post to view a thread.\n\nIf you see this you will need to restart your device.\n\nYou only need to do this once.\n\nThis is Android bug, there is nothing Pachli can do. - \ No newline at end of file + + %1$s crashed + Sorry about that. Click OK to prepare an e-mail to the developers with details + This data will be sent to the developers.\n\n + +Please check to make sure it does not include anything you don\'t want to share, and please describe what you were doing when the crash happened.\n\n + +----\n +Your description here:\n\n + +----\n + + diff --git a/app/src/orange/kotlin/app/pachli/CrashReporter.kt b/app/src/orange/kotlin/app/pachli/CrashReporter.kt new file mode 100644 index 000000000..0ffc35cef --- /dev/null +++ b/app/src/orange/kotlin/app/pachli/CrashReporter.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2023 Pachli Association + * + * This file is a part of Pachli. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * Pachli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Pachli; if not, + * see . + */ + +package app.pachli + +import android.app.Application +import org.acra.config.dialog +import org.acra.config.mailSender +import org.acra.data.StringFormat +import org.acra.ktx.initAcra + +/** + * Initialise ACRA. + */ +fun initCrashReporter(app: Application) { + app.initAcra { + buildConfigClass = BuildConfig::class.java + reportFormat = StringFormat.KEY_VALUE_LIST + + dialog { + title = app.getString(R.string.acra_dialog_title, app.getString(R.string.app_name)) + text = app.getString(R.string.acra_dialog_text) + resIcon = R.mipmap.ic_launcher + resTheme = android.R.style.Theme_Material_Light_Dialog_Alert + } + + mailSender { + mailTo = BuildConfig.SUPPORT_EMAIL + reportAsFile = false + body = app.getString(R.string.acra_email_body) + } + } +} diff --git a/build-logic/convention/src/main/kotlin/app/pachli/PachliFlavor.kt b/build-logic/convention/src/main/kotlin/app/pachli/PachliFlavor.kt index 1d0565714..99f7f82be 100644 --- a/build-logic/convention/src/main/kotlin/app/pachli/PachliFlavor.kt +++ b/build-logic/convention/src/main/kotlin/app/pachli/PachliFlavor.kt @@ -36,7 +36,8 @@ enum class PachliFlavor( val appName: String = "Pachli", val customLogoUrl: String = "", val customInstance: String = "", - val supportAccountUrl: String = "https://mastodon.social/@Pachli" + val supportAccountUrl: String = "https://mastodon.social/@Pachli", + val supportEmail: String = "team@pachli.app", ) { blue(FlavorDimension.color), orange( @@ -73,6 +74,7 @@ fun configureFlavors( buildConfigField("String", "CUSTOM_LOGO_URL", "\"${flavor.customLogoUrl}\"") buildConfigField("String", "CUSTOM_INSTANCE", "\"${flavor.customInstance}\"") buildConfigField("String", "SUPPORT_ACCOUNT_URL", "\"${flavor.supportAccountUrl}\"") + buildConfigField("String", "SUPPORT_EMAIL", "\"${flavor.supportEmail}\"") } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c0d851b3c..bc6294bbd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,6 @@ [versions] aboutlibraries = "10.9.2" +acra = "5.11.3" agp = "8.2.0" androidx-activity = "1.8.1" androidx-appcompat = "1.6.1" @@ -90,6 +91,8 @@ pachli-android-room = { id = "pachli.android.room", version = "unspecified" } [libraries] aboutlibraries-core = { module = "com.mikepenz:aboutlibraries-core", version.ref = "aboutlibraries" } aboutlibraries-legacy-ui = { module = "com.mikepenz:aboutlibraries", version.ref = "aboutlibraries" } +acra-dialog = { module = "ch.acra:acra-dialog", version.ref = "acra" } +acra-mail = { module = "ch.acra:acra-mail", version.ref = "acra" } android-material = { module = "com.google.android.material:material", version.ref = "material" } androidx-activity = { module = "androidx.activity:activity-ktx", version.ref = "androidx-activity" } androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" } @@ -190,6 +193,7 @@ ksp-gradlePlugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.g [bundles] aboutlibraries = ["aboutlibraries-core", "aboutlibraries-legacy-ui"] +acra = ["acra-dialog", "acra-mail"] androidx = ["androidx-core-ktx", "androidx-appcompat", "androidx-fragment-ktx", "androidx-browser", "androidx-swiperefreshlayout", "androidx-recyclerview", "androidx-exifinterface", "androidx-cardview", "androidx-preference-ktx", "androidx-sharetarget", "androidx-emoji2-core", "androidx-emoji2-views-core", "androidx-emoji2-view-helper", "androidx-lifecycle-viewmodel-ktx",