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.
This commit is contained in:
Nik Clayton 2023-12-12 23:25:09 +01:00 committed by GitHub
parent 098983f401
commit bf36837b04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 99 additions and 2 deletions

View File

@ -189,6 +189,8 @@ dependencies {
debugImplementation(libs.leakcanary) debugImplementation(libs.leakcanary)
orangeImplementation(libs.bundles.acra)
testImplementation(projects.core.testing) testImplementation(projects.core.testing)
testImplementation(libs.androidx.test.junit) testImplementation(libs.androidx.test.junit)
testImplementation(libs.robolectric) testImplementation(libs.robolectric)

View File

@ -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 <http://www.gnu.org/licenses>.
*/
package app.pachli
import android.app.Application
/** Do nothing in blue builds */
fun initCrashReporter(app: Application) {}

View File

@ -18,6 +18,7 @@
package app.pachli package app.pachli
import android.app.Application import android.app.Application
import android.content.Context
import androidx.core.content.edit import androidx.core.content.edit
import androidx.work.Constraints import androidx.work.Constraints
import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.ExistingPeriodicWorkPolicy
@ -56,6 +57,12 @@ class PachliApplication : Application() {
@Inject @Inject
lateinit var sharedPreferencesRepository: SharedPreferencesRepository lateinit var sharedPreferencesRepository: SharedPreferencesRepository
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
initCrashReporter(this)
}
override fun onCreate() { override fun onCreate() {
// Uncomment me to get StrictMode violation logs // Uncomment me to get StrictMode violation logs
// if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { // if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {

View File

@ -752,4 +752,16 @@
<string name="translation_provider_fmt">%1$s</string> <string name="translation_provider_fmt">%1$s</string>
<string name="janky_animation_title">You may need to restart your device</string> <string name="janky_animation_title">You may need to restart your device</string>
<string name="janky_animation_msg">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.</string> <string name="janky_animation_msg">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.</string>
</resources>
<string name="acra_dialog_title">%1$s crashed</string>
<string name="acra_dialog_text">Sorry about that. Click OK to prepare an e-mail to the developers with details</string>
<string name="acra_email_body">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
</string>
</resources>

View File

@ -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 <http://www.gnu.org/licenses>.
*/
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)
}
}
}

View File

@ -36,7 +36,8 @@ enum class PachliFlavor(
val appName: String = "Pachli", val appName: String = "Pachli",
val customLogoUrl: String = "", val customLogoUrl: String = "",
val customInstance: 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), blue(FlavorDimension.color),
orange( orange(
@ -73,6 +74,7 @@ fun configureFlavors(
buildConfigField("String", "CUSTOM_LOGO_URL", "\"${flavor.customLogoUrl}\"") buildConfigField("String", "CUSTOM_LOGO_URL", "\"${flavor.customLogoUrl}\"")
buildConfigField("String", "CUSTOM_INSTANCE", "\"${flavor.customInstance}\"") buildConfigField("String", "CUSTOM_INSTANCE", "\"${flavor.customInstance}\"")
buildConfigField("String", "SUPPORT_ACCOUNT_URL", "\"${flavor.supportAccountUrl}\"") buildConfigField("String", "SUPPORT_ACCOUNT_URL", "\"${flavor.supportAccountUrl}\"")
buildConfigField("String", "SUPPORT_EMAIL", "\"${flavor.supportEmail}\"")
} }
} }
} }

View File

@ -1,5 +1,6 @@
[versions] [versions]
aboutlibraries = "10.9.2" aboutlibraries = "10.9.2"
acra = "5.11.3"
agp = "8.2.0" agp = "8.2.0"
androidx-activity = "1.8.1" androidx-activity = "1.8.1"
androidx-appcompat = "1.6.1" androidx-appcompat = "1.6.1"
@ -90,6 +91,8 @@ pachli-android-room = { id = "pachli.android.room", version = "unspecified" }
[libraries] [libraries]
aboutlibraries-core = { module = "com.mikepenz:aboutlibraries-core", version.ref = "aboutlibraries" } aboutlibraries-core = { module = "com.mikepenz:aboutlibraries-core", version.ref = "aboutlibraries" }
aboutlibraries-legacy-ui = { module = "com.mikepenz:aboutlibraries", 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" } android-material = { module = "com.google.android.material:material", version.ref = "material" }
androidx-activity = { module = "androidx.activity:activity-ktx", version.ref = "androidx-activity" } androidx-activity = { module = "androidx.activity:activity-ktx", version.ref = "androidx-activity" }
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" } 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] [bundles]
aboutlibraries = ["aboutlibraries-core", "aboutlibraries-legacy-ui"] 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 = ["androidx-core-ktx", "androidx-appcompat", "androidx-fragment-ktx", "androidx-browser", "androidx-swiperefreshlayout",
"androidx-recyclerview", "androidx-exifinterface", "androidx-cardview", "androidx-preference-ktx", "androidx-sharetarget", "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", "androidx-emoji2-core", "androidx-emoji2-views-core", "androidx-emoji2-view-helper", "androidx-lifecycle-viewmodel-ktx",