---
title: Android and Android TV Monitoring Setup
description: Collect RUM and Error Tracking data from your Android projects.
breadcrumbs: >-
  Docs > RUM & Session Replay > Application Monitoring > Android and Android TV
  Monitoring > Android and Android TV Monitoring Setup
---

# Android and Android TV Monitoring Setup

## Overview{% #overview %}

This page describes how to instrument your applications for [Real User Monitoring (RUM)](https://docs.datadoghq.com/real_user_monitoring/) with the Android SDK. RUM includes Error Tracking by default, but if you have purchased Error Tracking as a standalone product, see the [Error Tracking setup guide](https://docs.datadoghq.com/error_tracking/frontend/mobile/android) for specific steps.

The Datadog Android SDK supports Android 6.0+ (API level 23) and Android TV.

## Setup{% #setup %}

**Choose your setup method:**

- **[Agentic Onboarding (in Preview)](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/agentic_onboarding/?tab=realusermonitoring)**: Use AI coding agents (Cursor, Claude Code) to automatically instrument your application with one prompt. The agent detects your project structure and configures the RUM SDK for you.
- **Manual setup** (below): Follow the step-by-step instructions to manually add and configure the SDK.

### 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.

```
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 [**Digital Experience** > **Add an Application**](https://app.datadoghq.com/rum/list).
1. Select `android` as the application type and enter an application name to generate a unique Datadog application ID and client token.
1. To instrument your web views, click the **Instrument your webviews** toggle. For more information, see [Web View Tracking](https://docs.datadoghq.com/real_user_monitoring/android/web_view_tracking/).
1. To disable automatic user data collection for either client IP or geolocation data, use the toggles for those settings. For more information, see [RUM Android Data Collected](https://docs.datadoghq.com/real_user_monitoring/android/data_collected/).

{% image
   source="https://datadog-docs.imgix.net/images/real_user_monitoring/android/android-new-application.fe329bfc1c6e54126fcc8822dff1d2f0.png?auto=format"
   alt="Create a RUM application for Android in Datadog" /%}

For more information about setting up a client token, see the [Client Token documentation](https://docs.datadoghq.com/account_management/api-app-keys/#client-tokens).

### 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/#rum--session-replay).

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/#initialization-parameters) to initialize the library.

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

{% tab title="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" %}

```
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" %}

```
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" %}

```
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" %}

```
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" %}

```
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" %}

```
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" %}

```
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" %}

```
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" %}

```
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" %}

```
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" %}

```
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" %}

```
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" %}

```
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 [Track Android Errors](https://docs.datadoghq.com/real_user_monitoring/error_tracking/android/#upload-your-mapping-file).

#### 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/#initialization-parameters). The sample rate is a percentage between 0 and 100. By default, `sessionSamplingRate` is set to 100 (keep all sessions).

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

#### Set tracking consent (GDPR compliance){% #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.

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

To enable the Android SDK to start sending data:

{% tab title="Kotlin" %}

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

{% /tab %}

{% tab title="Java" %}

```
RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId)
    .trackInteractions()
    .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/#automatically-track-views) to enable automatic tracking of all your views (activities, fragments, and more).

### Step 5 - Initialize the interceptor to track network events{% #step-5--initialize-the-interceptor-to-track-network-events %}

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/dd_libraries/android/).
1. Add the Gradle dependency to the `dd-sdk-android-okhttp` library in the module-level `build.gradle` file:

```
dependencies {
    implementation "com.datadoghq:dd-sdk-android-okhttp:x.x.x"
}
```
To track your OkHttp requests as resources, add the provided [interceptor](https://square.github.io/okhttp/features/interceptors/):
{% tab title="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" %}

```
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/#automatically-track-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" %}

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

{% /tab %}

{% tab title="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/#automatically-track-network-requests) for third-party providers and network requests.

#### Cronet{% #cronet %}

If you use Cronet instead of OkHttp, you can instrument your `CronetEngine` for RUM resource tracking and distributed tracing.

1. Add the Gradle dependencies in the module-level `build.gradle` file:

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

1. Instrument the `CronetEngine.Builder`:

   {% tab title="Kotlin" %}

   ```
   val tracedHostsWithHeaderType = mapOf(
       "example.com" to setOf(
           TracingHeaderType.DATADOG,
           TracingHeaderType.TRACECONTEXT),
       "example.eu" to setOf(
           TracingHeaderType.DATADOG,
           TracingHeaderType.TRACECONTEXT))
   val cronetEngine = CronetEngine.Builder(context)
       .configureDatadogInstrumentation(
           rumInstrumentationConfiguration = RumNetworkInstrumentationConfiguration(),
           apmInstrumentationConfiguration = ApmNetworkInstrumentationConfiguration(
               tracedHostsWithHeaderType
           )
       )
       .build()
   ```

   {% /tab %}

   {% tab title="Java" %}

   ```
   Map<String, Set<TracingHeaderType>> tracedHostsWithHeaderType = new HashMap<>();
   Set<TracingHeaderType> headerTypes = new HashSet<>(Arrays.asList(
       TracingHeaderType.DATADOG, TracingHeaderType.TRACECONTEXT));
   tracedHostsWithHeaderType.put("example.com", headerTypes);
   tracedHostsWithHeaderType.put("example.eu", headerTypes);
   CronetEngine.Builder builder = new CronetEngine.Builder(context);
   CronetEngine cronetEngine = CronetIntegrationPluginKt
       .configureDatadogInstrumentation(
           builder,
           new RumNetworkInstrumentationConfiguration(),
           new ApmNetworkInstrumentationConfiguration(tracedHostsWithHeaderType)
       )
       .build();
   ```

   {% /tab %}

**Known limitations**:

- Tracing headers are not propagated for redirected requests due to Cronet API limitations.
- Retries cannot be instrumented.

To filter out specific errors reported by `DatadogInterceptor`, you can configure a custom `EventMapper` in your `RumConfiguration`:

{% tab title="Kotlin" %}

```
val rumConfig = RumConfiguration.Builder(applicationId)
    .setErrorEventMapper { errorEvent ->
        if (errorEvent.shouldBeDiscarded()) {
            null
        } else {
            errorEvent
        }
    }
    .build();
```

{% /tab %}

{% tab title="Java" %}

```
RumConfiguration rumConfig = new RumConfiguration.Builder("applicationId")
             .setErrorEventMapper(errorEvent -> {
                 if (errorEvent.shouldBeDiscarded()) {
                     return null;
                 } else {
                     return errorEvent;
                 }
             })
             .build();

```

{% /tab %}

## 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" %}

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

{% /tab %}

{% tab title="Java" %}

```
RumConfiguration rumConfig = new RumConfiguration.Builder(applicationId)
  // …
  .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 %}

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

The Android SDK helps ensure 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.

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

### `Closeable` extension

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

```
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:

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

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

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

## Start monitoring{% #start-monitoring %}

Visualize the [data collected](https://docs.datadoghq.com/real_user_monitoring/android/data_collected/) in [dashboards](https://docs.datadoghq.com/real_user_monitoring/platform/dashboards/) or create a search query in the [RUM Explorer](https://app.datadoghq.com/rum/list).

Your application appears as pending on the Applications page until Datadog starts receiving data.

## Next steps{% #next-steps %}

See [Advanced Configuration](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/android/advanced_configuration/#initialization-parameters).

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

- [RUM Android Advanced Configuration](https://docs.datadoghq.com/real_user_monitoring/application_monitoring/android/advanced_configuration)
- [Source code for dd-sdk-android](https://github.com/DataDog/dd-sdk-android)
- [Explore Datadog RUM](https://docs.datadoghq.com/real_user_monitoring)
- [Upgrade RUM Mobile SDKs](https://docs.datadoghq.com/real_user_monitoring/guide/mobile-sdk-upgrade)

{% image
   source="https://datadog-docs.imgix.net/images/real_user_monitoring/android/android-new-application.fe329bfc1c6e54126fcc8822dff1d2f0.png?auto=format"
   alt="" /%}
