Skip to content

Commit 1001569

Browse files
committed
refactor(common): extract CrashReportService interface to :common
Create CrashReporter interface and CrashReportService delegate object in :common (package com.ichi2.anki) so all modules can report crashes without depending on the app module. Move runCatchingWithReport to :common. Rename the ACRA-backed implementation to AcraCrashReporter (internal) in :AnkiDroid. Wire up via CrashReportService.setReporter() in AnkiDroidApp.onCreate(). Existing call sites keep using CrashReportService.sendExceptionReport with the same package — no import changes needed for ~40 files. Only 7 files using ACRA-specific methods updated to AcraCrashReporter.
1 parent 75247c1 commit 1001569

File tree

7 files changed

+259
-82
lines changed

7 files changed

+259
-82
lines changed

AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/ACRATest.kt

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,18 @@ import androidx.test.annotation.UiThreadTest
2323
import androidx.test.ext.junit.runners.AndroidJUnit4
2424
import com.ichi2.anki.AnkiDroidApp
2525
import com.ichi2.anki.CrashReportService
26-
import com.ichi2.anki.CrashReportService.FEEDBACK_REPORT_ALWAYS
27-
import com.ichi2.anki.CrashReportService.FEEDBACK_REPORT_ASK
26+
import com.ichi2.anki.CrashReporter.Companion.FEEDBACK_REPORT_ALWAYS
27+
import com.ichi2.anki.CrashReporter.Companion.FEEDBACK_REPORT_ASK
28+
import com.ichi2.anki.CrashReporter.Companion.FEEDBACK_REPORT_KEY
29+
import com.ichi2.anki.CrashReporter.Companion.FEEDBACK_REPORT_NEVER
2830
import com.ichi2.anki.R
2931
import com.ichi2.anki.analytics.UsageAnalytics
32+
import com.ichi2.anki.getAcraCoreConfigBuilder
3033
import com.ichi2.anki.logging.ProductionCrashReportingTree
3134
import com.ichi2.anki.preferences.sharedPrefs
3235
import com.ichi2.anki.servicelayer.ThrowableFilterService
36+
import com.ichi2.anki.setDebugACRAConfig
37+
import com.ichi2.anki.setProductionACRAConfig
3338
import com.ichi2.anki.testutil.GrantStoragePermission
3439
import org.acra.ACRA
3540
import org.acra.builder.ReportBuilder
@@ -70,10 +75,10 @@ class ACRATest : InstrumentedTest() {
7075
@Throws(Exception::class)
7176
fun testDebugConfiguration() {
7277
// Debug mode overrides all saved state so no setup needed
73-
CrashReportService.setDebugACRAConfig(sharedPrefs)
78+
setDebugACRAConfig(sharedPrefs)
7479
assertArrayEquals(
7580
"Debug logcat arguments not set correctly",
76-
CrashReportService.acraCoreConfigBuilder
81+
getAcraCoreConfigBuilder()
7782
.build()
7883
.logcatArguments
7984
.toTypedArray(),
@@ -90,21 +95,21 @@ class ACRATest : InstrumentedTest() {
9095
)
9196
assertEquals(
9297
"ACRA feedback was not turned off correctly",
93-
CrashReportService.FEEDBACK_REPORT_NEVER,
98+
FEEDBACK_REPORT_NEVER,
9499
sharedPrefs
95-
.getString(CrashReportService.FEEDBACK_REPORT_KEY, "undefined"),
100+
.getString(FEEDBACK_REPORT_KEY, "undefined"),
96101
)
97102
}
98103

99104
@Test
100105
@Throws(Exception::class)
101106
fun testProductionConfigurationUserDisabled() {
102107
// set up as if the user had prefs saved to disable completely
103-
setReportConfig(CrashReportService.FEEDBACK_REPORT_NEVER)
108+
setReportConfig(FEEDBACK_REPORT_NEVER)
104109

105110
// ACRA initializes production logcat via annotation and we can't mock Build.DEBUG
106111
// That means we are restricted from verifying production logcat args and this is the debug case again
107-
CrashReportService.setProductionACRAConfig(sharedPrefs)
112+
setProductionACRAConfig(sharedPrefs)
108113
verifyDebugACRAPreferences()
109114
}
110115

@@ -115,7 +120,7 @@ class ACRATest : InstrumentedTest() {
115120
setReportConfig(FEEDBACK_REPORT_ASK)
116121

117122
// If the user is set to ask, then it's production, with interaction mode dialog
118-
CrashReportService.setProductionACRAConfig(sharedPrefs)
123+
setProductionACRAConfig(sharedPrefs)
119124
verifyACRANotDisabled()
120125

121126
assertToastMessage(R.string.feedback_for_manual_toast_text)
@@ -134,7 +139,7 @@ class ACRATest : InstrumentedTest() {
134139

135140
// If the user is set to always, then it's production, with interaction mode toast
136141
// will be useful with ACRA 5.2.0
137-
CrashReportService.setProductionACRAConfig(sharedPrefs)
142+
setProductionACRAConfig(sharedPrefs)
138143

139144
// The same class/method combo is only sent once, so we face a new method each time (should test that system later)
140145
val crash = Exception("testCrashReportSend at " + System.currentTimeMillis())
@@ -153,12 +158,12 @@ class ACRATest : InstrumentedTest() {
153158
val crashData =
154159
CrashReportDataFactory(
155160
testContext,
156-
CrashReportService.acraCoreConfigBuilder.build(),
161+
getAcraCoreConfigBuilder().build(),
157162
).createCrashData(ReportBuilder().exception(crash))
158163
assertTrue(
159164
LimitingReportAdministrator().shouldSendReport(
160165
testContext,
161-
CrashReportService.acraCoreConfigBuilder.build(),
166+
getAcraCoreConfigBuilder().build(),
162167
crashData,
163168
),
164169
)
@@ -167,19 +172,19 @@ class ACRATest : InstrumentedTest() {
167172
assertFalse(
168173
LimitingReportAdministrator().shouldSendReport(
169174
testContext,
170-
CrashReportService.acraCoreConfigBuilder.build(),
175+
getAcraCoreConfigBuilder().build(),
171176
crashData,
172177
),
173178
)
174179

175180
// Now let's clear data
176-
CrashReportService.deleteACRALimiterData(testContext)
181+
CrashReportService.deleteLimiterData(testContext)
177182

178183
// A third send should work again
179184
assertTrue(
180185
LimitingReportAdministrator().shouldSendReport(
181186
testContext,
182-
CrashReportService.acraCoreConfigBuilder.build(),
187+
getAcraCoreConfigBuilder().build(),
183188
crashData,
184189
),
185190
)
@@ -192,7 +197,7 @@ class ACRATest : InstrumentedTest() {
192197
setReportConfig(FEEDBACK_REPORT_ALWAYS)
193198

194199
// If the user is set to always, then it's production, with interaction mode toast
195-
CrashReportService.setProductionACRAConfig(sharedPrefs)
200+
setProductionACRAConfig(sharedPrefs)
196201
verifyACRANotDisabled()
197202

198203
assertToastMessage(R.string.feedback_auto_toast_text)
@@ -207,13 +212,13 @@ class ACRATest : InstrumentedTest() {
207212
setReportConfig(FEEDBACK_REPORT_ALWAYS)
208213

209214
// If the user is set to ask, then it's production, with interaction mode dialog
210-
CrashReportService.setProductionACRAConfig(sharedPrefs)
215+
setProductionACRAConfig(sharedPrefs)
211216
verifyACRANotDisabled()
212217

213218
assertDialogEnabledStatus("dialog should be disabled when status is ALWAYS", false)
214219
assertToastMessage(R.string.feedback_auto_toast_text)
215220

216-
setAcraReportingMode(FEEDBACK_REPORT_ASK)
221+
CrashReportService.setReportingMode(FEEDBACK_REPORT_ASK)
217222

218223
assertDialogEnabledStatus("dialog should be re-enabled after changed to ASK", true)
219224
assertToastMessage(R.string.feedback_for_manual_toast_text)
@@ -226,12 +231,12 @@ class ACRATest : InstrumentedTest() {
226231
setReportConfig(FEEDBACK_REPORT_ASK)
227232

228233
// If the user is set to ask, then it's production, with interaction mode dialog
229-
CrashReportService.setProductionACRAConfig(sharedPrefs)
234+
setProductionACRAConfig(sharedPrefs)
230235
verifyACRANotDisabled()
231236

232237
assertToastMessage(R.string.feedback_for_manual_toast_text)
233238

234-
setAcraReportingMode(FEEDBACK_REPORT_ALWAYS)
239+
CrashReportService.setReportingMode(FEEDBACK_REPORT_ALWAYS)
235240

236241
assertToastMessage(R.string.feedback_auto_toast_text)
237242
}
@@ -281,16 +286,12 @@ class ACRATest : InstrumentedTest() {
281286
)
282287
}
283288

284-
private fun setAcraReportingMode(feedbackReportAlways: String) {
285-
CrashReportService.setAcraReportingMode(feedbackReportAlways)
286-
}
287-
288289
@Throws(ACRAConfigurationException::class)
289290
private fun assertDialogEnabledStatus(
290291
message: String,
291292
isEnabled: Boolean,
292293
) {
293-
val config = CrashReportService.acraCoreConfigBuilder.build()
294+
val config = getAcraCoreConfigBuilder().build()
294295
for (configuration in config.pluginConfigurations) {
295296
// Make sure the dialog is set to pop up
296297
if (configuration.javaClass.toString().contains("Dialog")) {
@@ -301,7 +302,7 @@ class ACRATest : InstrumentedTest() {
301302

302303
@Throws(ACRAConfigurationException::class)
303304
private fun assertToastIsEnabled() {
304-
val config = CrashReportService.acraCoreConfigBuilder.build()
305+
val config = getAcraCoreConfigBuilder().build()
305306
for (configuration in config.pluginConfigurations) {
306307
if (configuration.javaClass.toString().contains("Toast")) {
307308
assertThat("Toast should be enabled", configuration.enabled(), equalTo(true))
@@ -313,7 +314,7 @@ class ACRATest : InstrumentedTest() {
313314
private fun assertToastMessage(
314315
@StringRes res: Int,
315316
) {
316-
val config = CrashReportService.acraCoreConfigBuilder.build()
317+
val config = getAcraCoreConfigBuilder().build()
317318
for (configuration in config.pluginConfigurations) {
318319
if (configuration.javaClass.toString().contains("Toast")) {
319320
assertEquals(
@@ -333,7 +334,7 @@ class ACRATest : InstrumentedTest() {
333334
}
334335

335336
private fun setReportConfig(feedbackReportAsk: String) {
336-
sharedPrefs.edit { putString(CrashReportService.FEEDBACK_REPORT_KEY, feedbackReportAsk) }
337+
sharedPrefs.edit { putString(FEEDBACK_REPORT_KEY, feedbackReportAsk) }
337338
}
338339

339340
private val sharedPrefs: SharedPreferences

0 commit comments

Comments
 (0)