---
title: Android Crash Reporting and Error Tracking
description: >-
  Set up Error Tracking for your Android applications to monitor crashes,
  exceptions, and application errors.
breadcrumbs: >-
  Docs > Error Tracking > Frontend Error Tracking > Mobile Crash Reporting >
  Android Crash Reporting and Error Tracking
---

# Android Crash Reporting and Error Tracking

## Overview{% #overview %}

Android [Error Tracking](https://docs.datadoghq.com/error_tracking.md) gives you comprehensive visibility into your mobile app's health by automatically capturing crashes, exceptions, and errors. With this feature, you can:

- Monitor app stability in real-time with instant crash alerts and error rate tracking across versions, devices, and user segments.
- Debug issues faster with deobfuscated stack traces and automatic ProGuard mapping file uploads for easier problem identification.
- Improve app quality by pinpointing crash-prone features, tracking error trends, and prioritizing fixes for better user satisfaction.
- Access aggregated Android crash dashboards and attributes.
- View deobfuscated Android crash reports with trend analysis.

The Datadog Android SDK supports Android 5.0+ (API level 21) and Android TV.

Your crash reports appear in [**Error Tracking**](https://app.datadoghq.com/rum/error-tracking).

## Setup{% #setup %}

If you have not set up the Android SDK yet, follow the [in-app setup instructions](https://app.datadoghq.com/rum/application/create) or see the [Android setup documentation](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/android/setup.md#setup).

### Step 1 - Declare the Android SDK as a dependency{% #step-1---declare-the-android-sdk-as-a-dependency %}

Declare [dd-sdk-android-rum](https://github.com/DataDog/dd-sdk-android/tree/develop/features/dd-sdk-android-rum) and the [Gradle plugin](https://github.com/DataDog/dd-sdk-android-gradle-plugin) as dependencies in your **application module's** `build.gradle` file:

```groovy
buildscript {
    dependencies {
        classpath("com.datadoghq:dd-sdk-android-gradle-plugin:x.x.x")
    }
}
plugins {
    id("com.datadoghq.dd-sdk-android-gradle-plugin")
    //(...)
}
android {
    //(...)
}
dependencies {
    implementation "com.datadoghq:dd-sdk-android-rum:x.x.x" 
    //(...)
}
```

### Step 2 - Specify application details in the UI{% #step-2---specify-application-details-in-the-ui %}

1. Navigate to [**Errors** > **Settings** > **Browser and Mobile** > **+ New Application**](https://app.datadoghq.com/error-tracking/settings/setup/client).
1. Select `android` as the application type and enter an application name to generate a unique Datadog application ID and client token.
1. Click **Create Application**.

### Step 3 - Initialize the Datadog SDK with application context{% #step-3---initialize-the-datadog-sdk-with-application-context %}

#### Update the initialization snippet{% #update-the-initialization-snippet %}

In the initialization snippet, set an environment name, service name, and version number. In the examples below, `APP_VARIANT_NAME` specifies the variant of the application that generates data. For more information, see [Using Tags](https://docs.datadoghq.com/getting_started/tagging/using_tags.md).

During initialization, you can also set the sample rate (RUM sessions) and set the tracking consent for GDPR compliance, as described below. See [other configuration options](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/android/advanced_configuration.md#initialization-parameters) to initialize the library.

{% callout %}
# Important note for users on the following Datadog sites: app.datadoghq.com



{% tab title="Kotlin" %}

```kotlin
class SampleApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        val configuration = Configuration.Builder(
            clientToken = <CLIENT_TOKEN>,
            env = <ENV_NAME>,
            variant = <APP_VARIANT_NAME>
        ).build()
        Datadog.initialize(this, configuration, trackingConsent)
    }
}
```

{% /tab %}

{% tab title="Java" %}

```java
public class SampleApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Configuration configuration =
                new Configuration.Builder(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>)
                        .build();
        Datadog.initialize(this, configuration, trackingConsent);
    }
}
```

{% /tab %}


{% /callout %}

{% callout %}
# Important note for users on the following Datadog sites: app.datadoghq.eu



{% tab title="Kotlin" %}

```kotlin
class SampleApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        val configuration = Configuration.Builder(
                clientToken = <CLIENT_TOKEN>,
                env = <ENV_NAME>,
                variant = <APP_VARIANT_NAME>
            )
            .useSite(DatadogSite.EU1)
            .build()
        Datadog.initialize(this, configuration, trackingConsent)
    }
}
```

{% /tab %}

{% tab title="Java" %}

```java
public class SampleApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Configuration configuration =
                new Configuration.Builder(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>)
                        .useSite(DatadogSite.EU1)
                        .build();
        Datadog.initialize(this, configuration, trackingConsent);
    }
}
```

{% /tab %}


{% /callout %}

{% callout %}
# Important note for users on the following Datadog sites: us3.datadoghq.com



{% tab title="Kotlin" %}

```kotlin
class SampleApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        val configuration = Configuration.Builder(
                clientToken = <CLIENT_TOKEN>,
                env = <ENV_NAME>,
                variant = <APP_VARIANT_NAME>
            )
            .useSite(DatadogSite.US3)
            .build()
        Datadog.initialize(this, configuration, trackingConsent)
    }
}
```

{% /tab %}

{% tab title="Java" %}

```java
public class SampleApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Configuration configuration =
                new Configuration.Builder(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>)
                        .useSite(DatadogSite.US3)
                        .build();
        Datadog.initialize(this, configuration, trackingConsent);
    }
}
```

{% /tab %}


{% /callout %}

{% callout %}
# Important note for users on the following Datadog sites: us5.datadoghq.com



{% tab title="Kotlin" %}

```kotlin
class SampleApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        val configuration = Configuration.Builder(
                clientToken = <CLIENT_TOKEN>,
                env = <ENV_NAME>,
                variant = <APP_VARIANT_NAME>
            )
            .useSite(DatadogSite.US5)
            .build()
        Datadog.initialize(this, configuration, trackingConsent)
    }
}
```

{% /tab %}

{% tab title="Java" %}

```java
public class SampleApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Configuration configuration =
                new Configuration.Builder(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>)
                        .useSite(DatadogSite.US5)
                        .build();
        Datadog.initialize(this, configuration, trackingConsent);
    }
}
```

{% /tab %}


{% /callout %}

{% callout %}
# Important note for users on the following Datadog sites: app.ddog-gov.com



{% tab title="Kotlin" %}

```kotlin
class SampleApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        val configuration = Configuration.Builder(
                clientToken = <CLIENT_TOKEN>,
                env = <ENV_NAME>,
                variant = <APP_VARIANT_NAME>
            )
            .useSite(DatadogSite.US1_FED)
            .build()
        Datadog.initialize(this, configuration, trackingConsent)
    }
}
```

{% /tab %}

{% tab title="Java" %}

```java
public class SampleApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Configuration configuration =
                new Configuration.Builder(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>)
                        .useSite(DatadogSite.US1_FED)
                        .build();
        Datadog.initialize(this, configuration, trackingConsent);
    }
}
```

{% /tab %}


{% /callout %}

{% callout %}
# Important note for users on the following Datadog sites: ap1.datadoghq.com



{% tab title="Kotlin" %}

```kotlin
class SampleApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        val configuration = Configuration.Builder(
                clientToken = <CLIENT_TOKEN>,
                env = <ENV_NAME>,
                variant = <APP_VARIANT_NAME>
            )
            .useSite(DatadogSite.AP1)
            .build()
        Datadog.initialize(this, configuration, trackingConsent)
    }
}
```

{% /tab %}

{% tab title="Java" %}

```java
public class SampleApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Configuration configuration =
                new Configuration.Builder(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>)
                        .useSite(DatadogSite.AP1)
                        .build();
        Datadog.initialize(this, configuration, trackingConsent);
    }
}
```

{% /tab %}


{% /callout %}

{% callout %}
# Important note for users on the following Datadog sites: ap2.datadoghq.com



{% tab title="Kotlin" %}

```kotlin
class SampleApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        val configuration = Configuration.Builder(
                clientToken = <CLIENT_TOKEN>,
                env = <ENV_NAME>,
                variant = <APP_VARIANT_NAME>
            )
            .useSite(DatadogSite.AP2)
            .build()
        Datadog.initialize(this, configuration, trackingConsent)
    }
}
```

{% /tab %}

{% tab title="Java" %}

```java
public class SampleApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Configuration configuration =
                new Configuration.Builder(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>)
                        .useSite(DatadogSite.AP2)
                        .build();
        Datadog.initialize(this, configuration, trackingConsent);
    }
}
```

{% /tab %}


{% /callout %}

The initialization credentials require your application's variant name and use the value of `BuildConfig.FLAVOR`. With the variant, the SDK can match the errors reported from your application to the mapping files uploaded by the Gradle plugin. If you do not have variants, the credentials use an empty string.

The Gradle plugin automatically uploads the appropriate ProGuard `mapping.txt` file at build time so you can view deobfuscated error stack traces. For more information, see the Upload your mapping file section.

#### Enable the feature to start sending data{% #enable-the-feature-to-start-sending-data %}

To enable the Android SDK to start sending data:

{% tab title="Kotlin" %}

```kotlin
val rumConfig = RumConfiguration.Builder(applicationId)
    .trackUserInteractions()
    .trackLongTasks(durationThreshold) // Not applicable to Error Tracking
    .useViewTrackingStrategy(strategy)
    .build()
Rum.enable(rumConfig)
```

{% /tab %}

{% tab title="Java" %}

```java
RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId)
    .trackUserInteractions()
    .trackLongTasks(durationThreshold) // Not applicable to Error Tracking
    .useViewTrackingStrategy(strategy)
    .build();
Rum.enable(rumConfig);
```

{% /tab %}

See [`ViewTrackingStrategy`](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/android/advanced_configuration.md#automatically-track-views) to enable automatic tracking of all your views (activities, fragments, and more).

#### Instrument your webviews (optional){% #instrument-your-webviews-optional %}

If your Android application uses WebViews to display web content, you can instrument them to track JavaScript errors and crashes that occur within the web content.

To instrument your web views:

1. Add the Gradle dependency by declaring the dd-sdk-android-webview as dependency in your build.gradle file:

   ```groovy
   dependencies {
    implementation "com.datadoghq:dd-sdk-android-webview:<latest_version>"
   }
   ```

1. Enable webview tracking for a given WebView instance by providing a list of hosts to track:

   ```kotlin
   WebViewTracking.enable(webView, hosts)
   ```

For more information, see [Web View Tracking](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/android/web_view_tracking.md).

### Step 4 - Add NDK crash reporting{% #step-4---add-ndk-crash-reporting %}

If your Android app uses native code (C/C++) through the Android NDK (Native Development Kit), you can track crashes that occur in this native code. Native code is often used for performance-critical operations, image processing, or when reusing existing C/C++ libraries.

Without NDK crash reporting, crashes in your native code do not appear in Error Tracking, making it difficult to debug issues in this part of your application.

To enable NDK crash reporting, use the Datadog NDK plugin:

1. Add the Gradle dependency by declaring the library as a dependency in your `build.gradle` file:

   ```kotlin
    dependencies {
        implementation("com.datadoghq:dd-sdk-android-ndk:x.x.x")
        //(...)
    }
   ```

1. Enable NDK crash collection after initializing the SDK:

   ```kotlin
   NdkCrashReports.enable()
   ```

### Step 5 - Add ANR reporting{% #step-5---add-anr-reporting %}

An "Application Not Responding" ([ANR](https://developer.android.com/topic/performance/vitals/anr)) is an Android-specific type of error that gets triggered when the application is unresponsive for too long. You can add ANR reporting to your RUM configuration to monitor these application responsiveness issues.

To enable ANR reporting, add the following to your RUM configuration:

{% tab title="Kotlin" %}

```kotlin
val rumConfig = RumConfiguration.Builder(applicationId)
    .trackUserInteractions()
    .trackLongTasks(durationThreshold)
    .trackNonFatalAnrs(true) // Enable non-fatal ANR reporting
    .useViewTrackingStrategy(strategy)
    .build()
Rum.enable(rumConfig)
```

{% /tab %}

{% tab title="Java" %}

```java
RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId)
    .trackUserInteractions()
    .trackLongTasks(durationThreshold)
    .trackNonFatalAnrs(true) // Enable non-fatal ANR reporting
    .useViewTrackingStrategy(strategy)
    .build();
Rum.enable(rumConfig);
```

{% /tab %}

ANRs are only reported through the SDK (not through Logs).

#### Reporting fatal ANRs{% #reporting-fatal-anrs %}

Fatal ANRs result in crashes. The application reports them when it's unresponsive, leading to the Android OS displaying a popup dialog to the user, who chooses to force quit the app through the popup.

{% image
   source="https://docs.dd-static.net/images/real_user_monitoring/error_tracking/rum-anr-fatal.439621648b84ea34b6919bec0a48c7fa.png?auto=format&fit=max&w=850 1x, https://docs.dd-static.net/images/real_user_monitoring/error_tracking/rum-anr-fatal.439621648b84ea34b6919bec0a48c7fa.png?auto=format&fit=max&w=850&dpr=2 2x"
   alt="A fatal crash report in Error Tracking." /%}

- In the **Error Tracking** page, fatal ANRs are grouped based on their similarity, which can result in several **individual issues** being created.
- By default, Datadog catches fatal ANRs through the [ApplicationExitInfo API](https://developer.android.com/reference/android/app/ApplicationExitInfo) (available since *[Android 30+](https://developer.android.com/tools/releases/platforms#11)*), which can be read on the next app launch.
- In *[Android 29](https://developer.android.com/tools/releases/platforms#10) and below*, reporting on fatal ANRs is not possible.

#### Reporting non-fatal ANRs{% #reporting-non-fatal-anrs %}

Non-fatal ANRs may or may not have led to the application being terminated (crashing).

{% image
   source="https://docs.dd-static.net/images/real_user_monitoring/error_tracking/rum-anr-non-fatal.0e1458ade0f537016c8bec9f383c96a6.png?auto=format&fit=max&w=850 1x, https://docs.dd-static.net/images/real_user_monitoring/error_tracking/rum-anr-non-fatal.0e1458ade0f537016c8bec9f383c96a6.png?auto=format&fit=max&w=850&dpr=2 2x"
   alt="A non-fatal crash report in Error Tracking." /%}

- In the **Error Tracking** page, non-fatal ANRs are grouped under a **single** issue due to their level of noise.
- By default, the reporting of non-fatal ANRs on *Android 30+* is **disabled** because it would create too much noise over fatal ANRs. On *Android 29* and below, however, the reporting of non-fatal ANRs is **enabled** by default, as fatal ANRs cannot be reported on those versions.

For any Android version, you can override the default setting for reporting non-fatal ANRs by setting `trackNonFatalAnrs` to `true` or `false` when initializing the SDK.

### Step 6 - Get deobfuscated stack traces{% #step-6---get-deobfuscated-stack-traces %}

When your Android app is built for production, the code is typically obfuscated using ProGuard or R8 to reduce app size and protect intellectual property. This obfuscation makes stack traces in crash reports unreadable, showing meaningless class and method names like `a.b.c()` instead of `com.example.MyClass.myMethod()`.

To make these stack traces readable for debugging, you need to upload your mapping files to Datadog. These files contain the mapping between obfuscated and original code, allowing Datadog to automatically deobfuscate stack traces in your error reports.

#### How it works{% #how-it-works %}

Datadog uses a unique build ID generated for each build to automatically match stack traces with the correct mapping files. This ensures that:

- Stack traces are always deobfuscated with the correct mapping file, regardless of when it was uploaded.
- You can upload mapping files during pre-production or production builds.
- The process works seamlessly across different build variants and environments.

The matching process depends on your [Android Gradle plugin](https://github.com/DataDog/dd-sdk-android-gradle-plugin) version:

- **Versions 1.13.0 and higher**: Uses the `build_id` field (requires Datadog Android SDK 2.8.0 or later)
- **Older versions**: Uses a combination of `service`, `version`, and `variant` fields

#### Upload your mapping file{% #upload-your-mapping-file %}

The Android Gradle plugin automates the mapping file upload process. After configuration, it automatically uploads the appropriate ProGuard/R8 mapping file for each build variant when you build your app.

**Note**: Re-uploading a mapping file does not override the existing one if the version has not changed. For information about file size limitations and other constraints, see the Limitations section.

#### Run the upload tasks{% #run-the-upload-tasks %}

After configuring the plugin, run the Gradle tasks to upload your Proguard/R8 mapping file and NDK symbol files to Datadog:

```bash
./gradlew uploadMappingRelease
./gradlew uploadNdkSymbolFilesRelease
```

For any given error, you can access the file path, line number, and a code snippet for each frame of the related stack trace.

{% tab title="US" %}

1. Add the [Android Gradle Plugin](https://github.com/DataDog/dd-sdk-android-gradle-plugin) to your Gradle project using the following code snippet.

   ```kotlin
   // In your app's build.gradle script
   plugins {
       id("com.datadoghq.dd-sdk-android-gradle-plugin") version "x.y.z"
   }
   ```

1. [Create a dedicated Datadog API key](https://app.datadoghq.com/organization-settings/api-keys) and export it as an environment variable named `DD_API_KEY` or `DATADOG_API_KEY`. Alternatively, pass it as a task property, or if you have `datadog-ci.json` file in the root of your project, it can be taken from an `apiKey` property there.

1. Optionally, configure the plugin to upload files to the EU region by configuring the plugin in your `build.gradle` script:

   ```kotlin
   datadog {
       site = "EU1"
   }
   ```

1. Run the upload task after your obfuscated APK builds:

   ```bash
   ./gradlew uploadMappingRelease
   ```

1. If running native code, run the NDK symbol upload task:

   ```bash
   ./gradlew uploadNdkSymbolFilesRelease
   ```

**Note**: If your project uses additional flavors, the plugin provides an upload task for each variant with obfuscation enabled. In this case, initialize the Android SDK with a proper variant name (the necessary API is available in versions `1.8.0` and later).
{% /tab %}

{% tab title="EU" %}

1. Add the [Android Gradle Plugin](https://github.com/DataDog/dd-sdk-android-gradle-plugin) to your Gradle project using the following code snippet.

   ```kotlin
   // In your app's build.gradle script
   plugins {
       id("com.datadoghq.dd-sdk-android-gradle-plugin") version "x.y.z"
   }
   ```

1. [Create a dedicated Datadog API key](https://app.datadoghq.com/organization-settings/api-keys) and export it as an environment variable named `DD_API_KEY` or `DATADOG_API_KEY`. Alternatively, pass it as a task property, or if you have `datadog-ci.json` file in the root of your project, it can be taken from an `apiKey` property there.

1. Configure the plugin to use the EU region by adding the following snippet in your app's `build.gradle` script file:

   ```kotlin
   datadog {
       site = "EU1"
   }
   ```

1. Run the upload task after your obfuscated APK builds:

   ```bash
   ./gradlew uploadMappingRelease
   ```

1. If running native code, run the NDK symbol upload task:

   ```bash
   ./gradlew uploadNdkSymbolFilesRelease
   ```

**Note**: If your project uses additional flavors, the plugin provides an upload task for each variant with obfuscation enabled. In this case, initialize the Android SDK with a proper variant name (the necessary API is available in versions `1.8.0` and later).
{% /tab %}

#### List uploaded mapping files{% #list-uploaded-mapping-files %}

See the [RUM Debug Symbols](https://app.datadoghq.com/source-code/setup/rum) page to view all uploaded symbols.

## Advanced Error Tracking features{% #advanced-error-tracking-features %}

{% collapsible-section #set-tracking-consent %}
#### Set tracking consent (GDPR compliance)

To be compliant with the GDPR regulation, the SDK requires the tracking consent value upon initialization.

Tracking consent can be one of the following values:

- `TrackingConsent.PENDING`: (Default) The SDK starts collecting and batching the data but does not send it to the collection endpoint. The SDK waits for the new tracking consent value to decide what to do with the batched data.
- `TrackingConsent.GRANTED`: The SDK starts collecting the data and sends it to the data collection endpoint.
- `TrackingConsent.NOT_GRANTED`: The SDK does not collect any data. You are not able to manually send any logs, traces, or events.

To **update the tracking consent** after the SDK is initialized, call `Datadog.setTrackingConsent(<NEW CONSENT>)`. The SDK changes its behavior according to the new consent. For example, if the current tracking consent is `TrackingConsent.PENDING` and you update it to:

- `TrackingConsent.GRANTED`: The SDK sends all current batched data and future data directly to the data collection endpoint.

- `TrackingConsent.NOT_GRANTED`: The SDK wipes all batched data and does not collect any future data.

{% /collapsible-section %}

{% collapsible-section #sample-session-rates %}
#### Sample session rates

To control the data your application sends to Datadog, you can specify a sample rate for sessions when [initializing RUM](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/android/advanced_configuration.md#initialization-parameters). The sample rate is a percentage between 0 and 100. By default, `sessionSamplingRate` is set to 100 (keep all sessions).

```kotlin
val rumConfig = RumConfiguration.Builder(applicationId)
        // Here 75% of the RUM sessions are sent to Datadog
        .setSessionSampleRate(75.0f)
        .build()
Rum.enable(rumConfig)
```

{% /collapsible-section %}

{% collapsible-section #interceptor %}
#### Initialize the interceptor to track network events

The network interceptor automatically tracks HTTP requests and responses, capturing network errors, timeouts, and performance issues that can help you correlate network problems with app crashes and user experience issues. To initialize an interceptor for tracking network events:

1. For distributed tracing, [add and enable the Trace feature](https://docs.datadoghq.com/tracing/trace_collection/automatic_instrumentation/dd_libraries/android.md).

1. Add the Gradle dependency to the `dd-sdk-android-okhttp` library in the module-level `build.gradle` file:

   ```groovy
   dependencies {
       implementation "com.datadoghq:dd-sdk-android-okhttp:x.x.x"
   }
   ```

1. To track your OkHttp requests as resources, add the provided [interceptor](https://square.github.io/okhttp/features/interceptors/):

{% tab title="Kotlin" %}

```kotlin
val tracedHostsWithHeaderType = mapOf(
    "example.com" to setOf(
        TracingHeaderType.DATADOG,
        TracingHeaderType.TRACECONTEXT),
    "example.eu" to setOf(
        TracingHeaderType.DATADOG,
        TracingHeaderType.TRACECONTEXT))
val okHttpClient = OkHttpClient.Builder()
    .addInterceptor(DatadogInterceptor.Builder(tracedHostsWithHeaderType).build())
    .build()
```

{% /tab %}

{% tab title="Java" %}

```java
Map<String, Set<TracingHeaderType>> tracedHostsWithHeaderType = new HashMap<>();
Set<TracingHeaderType> datadogAndW3HeadersTypes = new HashSet<>(Arrays.asList(TracingHeaderType.DATADOG, TracingHeaderType.TRACECONTEXT));
tracedHostsWithHeaderType.put("example.com", datadogAndW3HeadersTypes);
tracedHostsWithHeaderType.put("example.eu", datadogAndW3HeadersTypes);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
    .addInterceptor(new DatadogInterceptor.Builder(tracedHostsWithHeaderType).build())
    .build();
```

{% /tab %}

To automatically create RUM resources and spans for your OkHttp requests, use the `DatadogInterceptor` as an interceptor.

- This records each request processed by the `OkHttpClient` as a resource, with all the relevant information (URL, method, status code, and error) automatically filled in. Only the network requests that started when a view is active are tracked. To track requests when your application is in the background, [create a view manually](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/android/advanced_configuration.md#custom-views).

To monitor the network redirects or retries, you can use the `DatadogInterceptor` as a [network interceptor](https://square.github.io/okhttp/features/interceptors/#network-interceptors):

{% tab title="Kotlin" %}

```kotlin
val okHttpClient = OkHttpClient.Builder()
    .addNetworkInterceptor(DatadogInterceptor.Builder(tracedHostsWithHeaderType).build())
    .build()
```

{% /tab %}

{% tab title="Java" %}

```java
OkHttpClient okHttpClient = new OkHttpClient.Builder()
    .addNetworkInterceptor(new DatadogInterceptor.Builder(tracedHostsWithHeaderType).build())
    .build();
```

{% /tab %}

**Notes**:

- To use spans but not RUM resources, you can use the `TracingInterceptor` instead of `DatadogInterceptor` as described above.
- If you use multiple interceptors, add `DatadogInterceptor` first.

You can also add an `EventListener` for the `OkHttpClient` to [automatically track resource timing](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/android/advanced_configuration.md#automatically-track-network-requests) for third-party providers and network requests.
{% /collapsible-section %}

{% collapsible-section #track-background-events %}
#### Track background events

You can track events such as crashes and network requests when your application is in the background (for example, no active view is available).

Add the following snippet during configuration:

{% tab title="Kotlin" %}

```kotlin
.trackBackgroundEvents(true)
```

{% /tab %}

{% tab title="Java" %}

```java
.trackBackgroundEvents(true)
```

{% /tab %}

{% alert level="info" %}
Tracking background events may lead to additional sessions, which can impact billing. For questions, [contact Datadog support.](https://docs.datadoghq.com/help/)
{% /alert %}

{% /collapsible-section %}

{% collapsible-section #sending-data-device-offline %}
#### Sending data when device is offline

The Android SDK ensures availability of data when your user device is offline. In case of low-network areas, or when the device battery is too low, all events are first stored on the local device in batches.

Each batch follows the intake specification. Batches are sent as soon as the network is available, and the battery is high enough to ensure the Datadog SDK does not impact the end user's experience. If the network is not available while your application is in the foreground, or if an upload of data fails, the batch is kept until it can be sent successfully.

This means that even if users open your application while offline, no data is lost. To ensure the SDK does not use too much disk space, the data on the disk is automatically discarded if it gets too old.
{% /collapsible-section %}

{% collapsible-section #plugin-config-options %}
#### Plugin configuration options

There are several plugin properties that can be configured through the plugin extension. In case you are using multiple variants, you can set a property value for a specific flavor in the variant.

For example, for a `fooBarRelease` variant, you can use the following configuration:

```kotlin
datadog {
    foo {
        versionName = "foo"
    }
    bar {
        versionName = "bar"
    }
    fooBar {
        versionName = "fooBar"
    }
}
```

The task configuration for this variant is merged from all three flavor configurations provided in the following order:

1. `bar`
1. `foo`
1. `fooBar`

This resolves the final value for the `versionName` property as `fooBar`.

| Property name              | Description                                                                                                                                                                                                         |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `versionName`              | The version name of the application (by default, the version declared in the `android` block of your `build.gradle` script).                                                                                        |
| `serviceName`              | The service name of the application (by default, the package name of your application as declared in the `android` block of your `build.gradle` script).                                                            |
| `site`                     | The Datadog site to upload your data to (US1, US3, US5, EU1, US1_FED, AP1, or AP2).                                                                                                                                 |
| `remoteRepositoryUrl`      | The URL of the remote repository where the source code was deployed. If this is not provided, this value is resolved from your Git configuration during the task execution time.                                    |
| `checkProjectDependencies` | This property controls if the plugin should check if the Datadog Android SDK is included in the dependencies. If not, `none` is ignored, `warn` logs a warning, and `fail` fails the build with an error (default). |

{% /collapsible-section %}

{% collapsible-section #plugin-config-options %}
#### Integrate with a CI/CD pipeline

By default, the upload mapping task is independent from other tasks in the build graph. Run the task manually when you need to upload mapping.

If you want to run this task in a CI/CD pipeline, and the task is required as part of the build graph, you can set the upload task to run after the mapping file is generated.

For example:

```kotlin
tasks["minify${variant}WithR8"].finalizedBy { tasks["uploadMapping${variant}"] }
```

{% /collapsible-section %}

## Limitations{% #limitations %}

### File sizing{% #file-sizing %}

Mapping files are limited in size to **500 MB** each. If your project has a mapping file larger than this, use one of the following options to reduce the file size:

- Set the `mappingFileTrimIndents` option to `true`. This reduces your file size by 5%, on average.
- Set a map of `mappingFilePackagesAliases`: This replaces package names with shorter aliases. **Note**: Datadog's stacktrace uses the same alias instead of the original package name, so it's better to use this option for third party dependencies.

```kotlin
datadog {
    mappingFileTrimIndents = true
    mappingFilePackageAliases = mapOf(
        "kotlinx.coroutines" to "kx.cor",
        "com.google.android.material" to "material",
        "com.google.gson" to "gson",
        "com.squareup.picasso" to "picasso"
    )
}
```

### Collection{% #collection %}

When looking at RUM Crash Reporting behaviors for Android, consider the following:

- The crash can only be detected after the SDK is initialised. Given this, the recommendation is to initialize the SDK as soon as possible in your application's `onCreate` method.
- RUM crashes must be attached to a RUM view. If a crash occurs before a view is visible (typically an Activity or Fragment in an `onResume` state), or after the app is sent to the background by the end-user navigating away from it, the crash is muted and isn't reported for collection. To mitigate this, use the `trackBackgroundEvents()` [method](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/android/setup.md#track-background-events) in your `RumConfiguration` builder.
- Only crashes that occur in sampled sessions are kept. If a [session sampling rate is not 100%](https://app.datadoghq.com/source-code/setup/rum), some crashes are not reported.

## Test your implementation{% #test-your-implementation %}

To verify your Android Crash Reporting and Error Tracking configuration, you need to trigger a crash in your application and confirm that the error appears in Datadog.

To test your implementation:

1. Run your application on an Android emulator or a real device.

1. Execute some code containing an error or crash. For example:

   ```kotlin
   fun onEvent() {
       throw RuntimeException("Crash the app")
   }
   ```

1. After the crash happens, restart your application and wait for the Android SDK to upload the crash report in [**Error Tracking**](https://app.datadoghq.com/rum/error-tracking).

## Kotlin extensions{% #kotlin-extensions %}

### `Closeable` extension{% #closeable-extension %}

You can monitor `Closeable` instance usage with the `useMonitored` method, which reports errors to Datadog and closes the resource afterwards:

```kotlin
val closeable: Closeable = ...
closeable.useMonitored {
    // Your code here
}
```

### Track local assets as resources{% #track-local-assets-as-resources %}

You can track access to the assets by using `getAssetAsRumResource` extension method:

```kotlin
val inputStream = context.getAssetAsRumResource(fileName)
```

Usage of the local resources can be tracked by using `getRawResAsRumResource` extension method:

```kotlin
val inputStream = context.getRawResAsRumResource(id)
```

## Further Reading{% #further-reading %}

- [Frontend Error Tracking](https://docs.datadoghq.com/error_tracking/frontend.md)
- [Source code for dd-sdk-android](https://github.com/DataDog/dd-sdk-android)
- [Get started with Error Tracking](https://docs.datadoghq.com/real_user_monitoring/error_tracking.md)
- [Visualize Error Tracking data in the Explorer](https://docs.datadoghq.com/real_user_monitoring/error_tracking/explorer.md)
