240 lines
9.1 KiB
Markdown
Executable File
240 lines
9.1 KiB
Markdown
Executable File
# [Android Components](../../../README.md) > Libraries > Crash
|
||
|
||
A generic crash reporter component that can report crashes to multiple services.
|
||
|
||
Main features:
|
||
|
||
* Support for multiple crash reporting services (included is support for [Sentry](https://sentry.io) and [Socorro](https://wiki.mozilla.org/Socorro)).
|
||
* Support for crashes caused by uncaught exceptions.
|
||
* Support for native code crashes (currently primarily focused on GeckoView crashes).
|
||
* Can optionally prompt the user for confirmation before sending a crash report.
|
||
* Support for showing in-app confirmation UI for non-fatal crashes.
|
||
|
||
## Usage
|
||
|
||
### Setting up the dependency
|
||
|
||
Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](../../../README.md#maven-repository)):
|
||
|
||
```Groovy
|
||
implementation "org.mozilla.components:lib-crash:{latest-version}"
|
||
```
|
||
|
||
### Setting up crash reporting
|
||
|
||
In the `onCreate()` method of your Application class create a `CrashReporter` instance and call `install()`:
|
||
|
||
```Kotlin
|
||
CrashReporter(
|
||
services = listOf(
|
||
// List the crash reporting services you want to use
|
||
)
|
||
).install(this)
|
||
```
|
||
|
||
With this minimal setup the crash reporting library will capture "uncaught exception" crashes and "native code" crashes and forward them to the configured crash reporting services.
|
||
|
||
⚠️ Note: To avoid conflicting setups do not use any other crash reporting libraries/services independently from this library.
|
||
|
||
### Recording crash breadcrumbs to supported services
|
||
|
||
Using the `CrashReporter` instance to record crash breadcrumbs. These breadcrumbs will then be sent when a crash occurs to aid in debugging. Breadcrumbs are reported only if the underlying crash reporter service supports it.
|
||
|
||
⚠️ Note: Directly using Sentry's breadcrumb will not work as expected on Android 10 or above. Using the `CrashReporter` breadcrumb is preferred.
|
||
|
||
```Kotlin
|
||
crashReporter.recordCrashBreadcrumb(
|
||
CrashBreadcrumb("Settings button clicked", data, "UI", Level.INFO, Type.USER)
|
||
)
|
||
```
|
||
|
||
### Sending crash reports to Sentry
|
||
|
||
⚠️ Note: The crash reporter library is compiled against the Sentry SDK but it doesn't require it as a dependency. The app using the component is responsible for adding the Sentry dependency to its build files in order to use Sentry crash reporting.
|
||
|
||
Add a `SentryService` instance to your `CrashReporter` in order to upload crashes to Sentry:
|
||
|
||
```Kotlin
|
||
CrashReporter(
|
||
services = listOf(
|
||
SentryService(applicationContext, "your sentry DSN")
|
||
)
|
||
).install(applicationContext)
|
||
```
|
||
|
||
By default only the `DSN` is needed. But there are additional option configuration parameters:
|
||
|
||
```Kotlin
|
||
SentryService(
|
||
applicationContext,
|
||
"your sentry DSN",
|
||
|
||
// Optionally add tags that will be sent with every crash report
|
||
tags = mapOf(
|
||
"build_flavor" to BuildConfig.FLAVOR,
|
||
"build_type" to BuildConfig.BUILD_TYPE
|
||
),
|
||
|
||
// Send an event to Sentry for every native code crash. Native code crashes
|
||
// can't be uploaded to Sentry currently. But sending an event to Sentry
|
||
// gives you an idea about how often native code crashes. For sending native
|
||
// crash reports add additional services like Socorro.
|
||
sendEventForNativeCrashes = true
|
||
)
|
||
```
|
||
|
||
### Sending crash reports to Mozilla Socorro
|
||
|
||
[Socorro](https://wiki.mozilla.org/Socorro) is the name for the [Mozilla Crash Stats](https://crash-stats.mozilla.org/) project.
|
||
|
||
⚠️ Note: Socorro filters crashes by "app name". New app names need to be safelisted for the server to accept the crash. [File a bug](https://bugzilla.mozilla.org/enter_bug.cgi?product=Socorro) if you would like to get your app added to the safelist.
|
||
|
||
Add a `MozillaSocorroService` instance to your `CrashReporter` in order to upload crashes to Socorro:
|
||
|
||
```Kotlin
|
||
CrashReporter(
|
||
services = listOf(
|
||
MozillaSocorroService(applicationContext, "your app name")
|
||
)
|
||
).install(applicationContext)
|
||
```
|
||
|
||
`MozillaSocorroService` will report version information such as App version, Android Component version, Glean version, Application Services version, GeckoView version and Build ID
|
||
⚠️ Note: Currently only native code crashes get uploaded to Socorro. Socorro has limited support for "uncaught exception" crashes too, but it is recommended to use a more elaborate solution like Sentry for that.
|
||
|
||
### Sending crash reports to Glean
|
||
|
||
[Glean](https://docs.telemetry.mozilla.org/concepts/glean/glean.html) is a new way to collect telemetry by Mozilla.
|
||
This will record crash counts as a labeled counter with each label corresponding to a specific type of crash (`fatal_native_code_crash`, `nonfatal_native_code_crash`, `caught_exception`, `uncaught_exception`, currently).
|
||
The list of collected metrics is available in the [metrics.yaml file](metrics.yaml), with their documentation [living here](https://dictionary.telemetry.mozilla.org/apps/fenix/pings/crash).
|
||
Due to the fact that Glean can only be recorded to in the main process and lib-crash runs in a separate process when it runs to handle the crash,
|
||
lib-crash persists the data in a file format and then reads and records the data from the main process when the application is next run since the `GleanCrashReporterService`
|
||
constructor is loaded from the main process.
|
||
|
||
Add a `GleanCrashReporterService` instance to your `CrashReporter` in order to record crashes in Glean:
|
||
|
||
```Kotlin
|
||
CrashReporter(
|
||
services = listOf(
|
||
GleanCrashReporterService()
|
||
)
|
||
).install(applicationContext)
|
||
```
|
||
|
||
⚠️ Note: Applications using the `GleanCrashReporterService` are **required** to undergo [Data Collection Review](https://wiki.mozilla.org/Firefox/Data_Collection) for the crash counts that they will be collecting.
|
||
|
||
### Showing a crash reporter prompt
|
||
|
||
![](images/crash-dialog.png)
|
||
|
||
Optionally the library can show a prompt asking the user for confirmation before sending a crash report.
|
||
|
||
The behavior can be controlled using the `shouldPrompt` parameter:
|
||
|
||
```Kotlin
|
||
CrashReporter(
|
||
// Always prompt
|
||
shouldPrompt = CrashReporter.Prompt.ALWAYS,
|
||
|
||
// Or: Only prompt for native crashes
|
||
shouldPrompt = CrashReporter.Prompt.ONLY_NATIVE_CRASH,
|
||
|
||
// Or: Never show the prompt
|
||
shouldPrompt = CrashReporter.Prompt.NEVER,
|
||
|
||
// ..
|
||
).install(applicationContext)
|
||
```
|
||
|
||
#### Customizing the prompt
|
||
|
||
The crash reporter prompt can be customized by providing a `PromptConfiguration` object:
|
||
|
||
```Kotlin
|
||
CrashReporter(
|
||
promptConfiguration = CrashReporter.PromptConfiguration(
|
||
appName = "My App",
|
||
organizationName = "My Organization",
|
||
|
||
// An additional message that will be shown in the prompt
|
||
message = "We are very sorry!"
|
||
|
||
// Use a custom theme for the prompt (Extend Theme.Mozac.CrashReporter)
|
||
theme = android.R.style.Theme_Holo_Dialog
|
||
),
|
||
|
||
// ..
|
||
).install(applicationContext)
|
||
```
|
||
|
||
#### Handling non-fatal crashes
|
||
|
||
A native code crash can be non-fatal. In this situation a child process crashed but the main process (in which the application runs) is not affected. In this situation a crash can be handled more gracefully and instead of using the crash reporter prompt of the component an app may want to show an in-app UI for asking the user for confirmation.
|
||
|
||
![](images/crash-in-app.png)
|
||
|
||
Provide a `PendingIntent` that will be invoked when a non-fatal crash occurs:
|
||
|
||
```Kotlin
|
||
// Launch this activity when a crash occurs.
|
||
val pendingIntent = PendingIntent.getActivity(
|
||
context,
|
||
0,
|
||
Intent(this, MyActivity::class.java).apply {
|
||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||
},
|
||
PendingIntentUtils.defaultFlags
|
||
)
|
||
|
||
CrashReporter(
|
||
shouldPrompt = CrashReporter.Prompt.ALWAYS,
|
||
services = listOf(
|
||
// ...
|
||
),
|
||
nonFatalCrashIntent = pendingIntent
|
||
).install(this)
|
||
```
|
||
|
||
In your component that receives the Intent (e.g. `Activity`) you can use `Crash.fromIntent()` to receive the `Crash` object. Once the user has approved sending a report call `submitReport()` on your `CrashReporter` instance.
|
||
|
||
```Kotlin
|
||
// In your crash handling component (e.g. Activity)
|
||
if (Crash.isCrashIntent(intent) {
|
||
val crash = Crash.fromIntent(intent)
|
||
|
||
...
|
||
}
|
||
|
||
// Once the user has confirmed sending a crash report:
|
||
crashReporter.submitReport(crash)
|
||
```
|
||
|
||
⚠️ Note: `submitReport()` may block and perform I/O on the calling thread.
|
||
|
||
### Sending GeckoView crash reports
|
||
|
||
⚠️ Note: For sending GeckoView crash reports GeckoView **64.0** or higher is required!
|
||
|
||
Register `CrashHandlerService` as crash handler for GeckoView:
|
||
|
||
```Kotlin
|
||
val settings = GeckoRuntimeSettings.Builder()
|
||
.crashHandler(CrashHandlerService::class.java)
|
||
.build()
|
||
|
||
// Crashes of this runtime will be forwarded to the crash reporter component
|
||
val runtime = GeckoRuntime.create(applicationContext, settings)
|
||
|
||
// If you are using the browser-engine-gecko component then pass the runtime
|
||
// to your code initializing the engine:
|
||
val engine = GeckoEngine(applicationContext, defaultSettings, runtime)
|
||
```
|
||
|
||
ℹ️ You can force a child process crash (non fatal!) using a multi-process (E10S) GeckoView by loading the test URL `about:crashcontent`. Using a non-multi-process GeckoView you can use `about:crashparent` to force a fatal crash.
|
||
|
||
## License
|
||
|
||
This Source Code Form is subject to the terms of the Mozilla Public
|
||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||
file, You can obtain one at http://mozilla.org/MPL/2.0/
|