> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flashcat.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Android Error Reporting

> Master Android RUM SDK error capture mechanisms, including Java/Kotlin crashes, NDK crashes, ANR reporting, manual reporting, and symbolication configuration

This document covers the error capture mechanisms of the Android RUM SDK, helping you monitor and diagnose crashes and errors in Android applications.

<Info>
  The SDK supports automatic capture of Java/Kotlin crashes, NDK native crashes, and ANR (Application Not Responding), while also providing manual error reporting and symbolicated stack trace features.
</Info>

## Error Types

Android RUM can monitor the following types of errors:

### Java/Kotlin Crashes

The SDK automatically captures unhandled Java/Kotlin exceptions, including:

* Runtime exceptions (e.g., `NullPointerException`, `IndexOutOfBoundsException`)
* Uncaught exceptions
* Application crashes

### NDK Crashes (Native Crash)

If your application uses native code (C/C++), the SDK supports capturing NDK crashes and including them in error tracking.

### ANR (Application Not Responding)

The SDK can detect and report ANR issues, helping you identify user experience problems caused by main thread blocking.

### Custom Errors

In addition to automatically captured exceptions, you can use the RUM SDK to manually report custom errors for tracking business logic errors and other specific issues.

## Configure Crash Reporting

### Basic Configuration

<Note>
  Crash reporting is enabled by default. After completing basic SDK integration following the [SDK Integration Guide](/en/rum/sdk/android/sdk-integration), the SDK will automatically capture unhandled exceptions in your application.
</Note>

### Add NDK Crash Reporting

If your application contains native code (C/C++), you need to add the NDK crash reporting module to capture native crashes.

<Steps>
  <Step title="Add Dependency">
    Add the NDK crash reporting dependency in your app module's `build.gradle` file:

    ```groovy build.gradle theme={null}
    dependencies {
        implementation "cloud.flashcat:dd-sdk-android-ndk:<latest-version>"
    }
    ```
  </Step>

  <Step title="Enable NDK Crash Reporting">
    Enable NDK crash reporting after SDK initialization:

    ```kotlin theme={null}
    import com.datadog.android.ndk.NdkCrashReports

    // Call after Datadog.initialize()
    NdkCrashReports.enable()
    ```
  </Step>
</Steps>

### Add ANR Reporting

ANR (Application Not Responding) occurs when the application's main thread is blocked for more than a certain time, causing the application to become unresponsive to user input.

#### Enable ANR Detection

Enable ANR detection in the RUM configuration:

```kotlin theme={null}
import com.datadog.android.rum.RumConfiguration

val rumConfig = RumConfiguration.Builder(applicationId)
    .trackNonFatalAnrs(true) // Track non-fatal ANRs
    .build()
```

<Tip>
  ANR detection monitors main thread responsiveness. When the main thread is blocked beyond the threshold, the SDK automatically records an ANR event.
</Tip>

## Manual Error Reporting

Using the `addError` API, you can manually report handled exceptions, custom errors, or other errors not automatically captured.

### Error Reporting Example

```kotlin theme={null}
import com.datadog.android.rum.GlobalRumMonitor
import com.datadog.android.rum.RumErrorSource

// Report an error with context
try {
    riskyOperation()
} catch (e: Exception) {
    GlobalRumMonitor.get().addError(
        message = "Operation failed",
        source = RumErrorSource.SOURCE,
        throwable = e,
        attributes = mapOf(
            "operation" to "riskyOperation",
            "userId" to "12345"
        )
    )
}
```

### Error Source Types

`RumErrorSource` options:

| Value                    | Description   |
| ------------------------ | ------------- |
| `RumErrorSource.NETWORK` | Network error |
| `RumErrorSource.SOURCE`  | Source error  |
| `RumErrorSource.CONSOLE` | Console error |
| `RumErrorSource.LOGGER`  | Logger error  |
| `RumErrorSource.AGENT`   | Agent error   |
| `RumErrorSource.WEBVIEW` | WebView error |
| `RumErrorSource.CUSTOM`  | Custom error  |

### Network Error Reporting Example

```kotlin theme={null}
import com.datadog.android.rum.GlobalRumMonitor
import com.datadog.android.rum.RumErrorSource

fun onNetworkError(url: String, statusCode: Int, error: Throwable) {
    GlobalRumMonitor.get().addError(
        message = "Network request failed: $url",
        source = RumErrorSource.NETWORK,
        throwable = error,
        attributes = mapOf(
            "url" to url,
            "status_code" to statusCode,
            "method" to "GET"
        )
    )
}
```

## Get Deobfuscated Stack Traces

If your application has code obfuscation enabled (ProGuard/R8), reported crash stacks will be obfuscated. By uploading mapping files, you can restore obfuscated stacks to original class names, method names, and line numbers.

### Configure Gradle Plugin

<Steps>
  <Step title="Add Plugin">
    Add the Flashcat Android Gradle plugin in your app module's `build.gradle` file:

    ```groovy build.gradle theme={null}
    plugins {
        id("cloud.flashcat.android-gradle-plugin") version "1.1.0"
    }
    ```
  </Step>

  <Step title="Configure Plugin">
    Configure the application identity and upload target. When fields are not set, the plugin reads the app version and package name from the Android build configuration:

    ```groovy build.gradle theme={null}
    flashcat {
        site = "CN"                        // Optional values: CN, STAGING. Default: CN
        serviceName = "<SERVICE_NAME>"     // Optional, defaults to the application ID
        versionName = "1.0.0"              // Optional, defaults to android.defaultConfig.versionName
    }
    ```

    <Note>
      Provide the API key through the `FC_API_KEY` / `FLASHCAT_API_KEY` environment variables, Gradle properties with the same names, or `flashcat-ci.json` in the project root. For all options, see [Source Mapping - Upload Android Symbol Files](/en/rum/error-tracking/source-mapping#upload-android-symbol-files).
    </Note>
  </Step>
</Steps>

### Upload Mapping Files

After configuration, run the upload task after the build completes, or add it to your CI release workflow:

```bash theme={null}
./gradlew uploadMapping<Variant>
```

For example, for the `release` variant:

```bash theme={null}
./gradlew uploadMappingRelease
```

### Upload NDK Symbol Files

If you're using NDK crash reporting, you also need to upload NDK symbol files to get readable native stacks:

```bash theme={null}
./gradlew uploadNdkSymbolFiles<Variant>
```

### Plugin Configuration Options

| Property                         | Description                                                                                                                |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `versionName`                    | App version name. Defaults to the Android build configuration's `versionName`                                              |
| `serviceName`                    | Service name. Defaults to the application ID                                                                               |
| `site`                           | Upload site. Options: `CN`, `STAGING`. Default: `CN`                                                                       |
| `mappingFilePath`                | Custom ProGuard/R8 mapping file path. Defaults to the current variant's Android build output                               |
| `nonDefaultObfuscation`          | Set to `true` when using DexGuard or another non-default obfuscator. The plugin creates upload tasks for all variants      |
| `additionalSymbolFilesLocations` | Extra NDK symbol directories. Directory structure should look like `/path/to/location/obj/{arch}/libname.so`               |
| `checkProjectDependencies`       | Controls whether the plugin checks Flashcat SDK dependencies. Options: `none`, `warn`, `fail`; when unset, no check is run |

### Mapping File Size Limits

Mapping file size is limited to **500 MB**. If the file is too large, you can use the following options to reduce file size:

```groovy build.gradle theme={null}
flashcat {
    mappingFileTrimIndents = true  // Remove indentation, reduces file size by ~5% on average

    mappingFilePackageAliases = [
        "kotlinx.coroutines": "kx.cor",
        "com.google.android.material": "material",
        "com.google.gson": "gson"
    ]
}
```

<Tip>
  When using `mappingFilePackageAliases`, stacks in Flashcat error tracking will use aliases instead of original package names. It's recommended to only use this option for third-party dependencies.
</Tip>

## Track Background Events

By default, only crashes that occur when a view is active are tracked. If you want to track crashes that occur when the app is in the background, enable background event tracking:

```kotlin theme={null}
import com.datadog.android.rum.RumConfiguration

val rumConfig = RumConfiguration.Builder(applicationId)
    .trackBackgroundEvents(true)
    .build()
```

<Warning>
  Tracking background events may generate additional sessions, which could affect billing. If you have questions, please contact the Flashcat support team.
</Warning>

## Limitations and Considerations

### Crash Detection Limitations

* **SDK Initialization Timing**: Crashes can only be detected after SDK initialization. It's recommended to initialize the SDK as early as possible in `Application.onCreate()`.
* **View Association**: Crashes must be associated with a RUM view. Crashes that occur before a view is displayed or after the app is backgrounded may not be reported. This can be mitigated with `trackBackgroundEvents(true)`.
* **Sampling Rate Impact**: Only crashes in sampled sessions are retained. If the session sampling rate is not 100%, some crashes may not be reported.

### Symbolication Limitations

* Ensure mapping files are correctly uploaded with each new version release.
* Different build variants (e.g., debug/release) require separate mapping file uploads.
* NDK symbol files must contain debug information for proper symbolication.

## Testing and Verification

### Verify Java/Kotlin Crashes

1. Add test code to trigger a crash in your app:

```kotlin theme={null}
fun onEvent() {
    throw RuntimeException("Test crash")
}
```

2. Run the app and trigger the crash
3. Restart the app and wait for the SDK to upload the crash report
4. View the crash report in the Flashcat console's Error Tracking module

### Verify NDK Crashes

1. Add a test crash in native code:

```cpp theme={null}
void crash() {
    int* ptr = nullptr;
    *ptr = 42;  // Trigger null pointer crash
}
```

2. Call this native method from Java/Kotlin code
3. Restart the app and wait for the SDK to upload the crash report
4. Confirm the stack is properly symbolicated (showing function names, file names, and line numbers)

### Verify ANR

1. Execute a time-consuming operation on the main thread:

```kotlin theme={null}
fun blockMainThread() {
    Thread.sleep(10000)  // Block main thread for 10 seconds
}
```

2. Trigger this operation and try to interact with the app
3. Check if the Flashcat console received the ANR report

## Error Data Structure

Each error record contains the following attributes:

| Attribute        | Type    | Description                                                     |
| ---------------- | ------- | --------------------------------------------------------------- |
| `error.source`   | string  | Error source (e.g., `source`, `network`, `custom`)              |
| `error.type`     | string  | Error type or code (e.g., `NullPointerException`)               |
| `error.message`  | string  | Error message                                                   |
| `error.stack`    | string  | Error stack trace                                               |
| `error.is_crash` | boolean | Whether it's a crash                                            |
| `context`        | Object  | Custom context information passed via `addError`'s `attributes` |

## Best Practices

1. **Initialize SDK Early**: Initialize the SDK in `Application.onCreate()` to capture as many crashes as possible.

2. **Enable Background Event Tracking**: If your app has significant background operations, consider enabling `trackBackgroundEvents`.

3. **Properly Upload Symbol Files**:

   * Upload corresponding mapping files for each release version
   * If using NDK, also upload NDK symbol files
   * Integrate symbol file upload into your CI/CD pipeline

4. **Enrich Error Context**: When manually reporting errors, attach business-related context information (e.g., user ID, operation type).

5. **Filter Irrelevant Errors**: Use `setErrorEventMapper` to filter third-party SDK or irrelevant errors to reduce noise.

## Next Steps

<CardGroup cols={2}>
  <Card title="View Errors" icon="eye" href="../error-viewing">
    Learn how to view and analyze errors in the Error Tracking module
  </Card>

  <Card title="Android SDK Advanced Configuration" icon="sliders" href="/en/rum/sdk/android/advanced-config">
    Learn about advanced SDK configuration options
  </Card>
</CardGroup>
