---
title: "Android"
description: "Set up Middleware RUM for Android apps to track user interactions and monitor mobile performance."
section: "RUM"
breadcrumb: "RUM > Mobile > Android"
canonical: "https://docs.middleware.io/get-started/rum/android"
---
# Android

This guide walks you through setting up Real User Monitoring (RUM) in an Android application. These instructions can also be found on the Installation page in your Middleware account. A sample application is available in the [GitHub repository](https://github.com/middleware-labs/middleware-android/#middleware-android-sdk).

## Overview

The Middleware Android RUM SDK collects user activity, performance data, and errors from Android applications. It helps you investigate startup delays, crashes, unresponsive screens, and slow network requests.

The SDK captures app startup times, crashes, Application Not Responding (ANR) errors, slow or frozen frames, and instrumented network requests. Session Replay shows the activity leading up to a problem, such as a checkout screen becoming unresponsive.

## Prerequisites

Before installing the SDK, make sure you have:

- Android 5.0 (API level 21) or later.
- `compileSdk` 35 or later.
- Kotlin Gradle Plugin (KGP) 2.0 or later.
- A Gradle project with `mavenCentral()` enabled.
- Core library desugaring enabled.
- A Middleware account and RUM application credentials.
- Internet connectivity to your Middleware ingestion endpoint.

### Enable core library desugaring

Add the following configuration to your app-level `build.gradle`:

```gradle
android {
    compileOptions {
        coreLibraryDesugaringEnabled true
    }
}

dependencies {
    coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:2.1.5"
}
```

Also ensure your application has the required Android permissions:

```xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
```

## Installation

#### 1 Create a RUM application

1. Log in to Middleware.
2. Go to [Installation → RUM](https://app.middleware.io/installation/rum/android).
3. Select **Android** as the platform.
4. Click **New Application**.
5. Enter your application name and click **Create Application**.
6. Copy the generated RUM credentials and target URL.

#### 2 Install the Android SDK

Add the Middleware Android SDK dependency to your app-level `build.gradle`:

```gradle
dependencies {
    implementation 'io.github.middleware-labs:android-sdk:3.2.2'
}
```

Sync your Gradle project to install the SDK.

#### 3 Initialize Middleware

Create or update your application's `Application` class:

```java
import android.app.Application;

import io.middleware.android.sdk.Middleware;

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        Middleware.builder()
            .setTarget("https://<MW_UID>.middleware.io")
            .setRumAccessToken("<MW_RUM_ACCESS_TOKEN>")
            .setServiceName("my-android-app")
            .setProjectName("Android-App")
            .setDeploymentEnvironment("PROD")
            .build(this);
    }
}
```

Replace the placeholders with your Middleware account details.

Initialize the SDK as early as possible in `Application.onCreate()` to capture app startup and early lifecycle events.

#### 4 Register the Application class

If you created a custom `Application` class, register it in `AndroidManifest.xml`:

```xml
<application
    android:name=".MyApplication"
    ... >
</application>
```

This ensures Middleware initializes when the application process starts.

#### 5 Configure HTTP instrumentation

The Android SDK automatically collects UI and system telemetry, but **HTTP requests require additional instrumentation**.

If your application uses OkHttp, wrap your existing client using Middleware:

```java
import okhttp3.Call;
import okhttp3.OkHttpClient;

import io.middleware.android.sdk.Middleware;

Call.Factory httpClient = Middleware.getInstance()
    .createRumOkHttpCallFactory(new OkHttpClient());
```

Use the returned `Call.Factory` for network requests.

For Retrofit applications:

```java
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.example.com/")
    .callFactory(httpClient)
    .build();
```

This enables Middleware to capture HTTP request methods, URLs, status codes, and timings.

> **Warning:** **Important:** Requests made through a plain `OkHttpClient` are not instrumented. Use the Middleware-wrapped `Call.Factory` for every network client you want to monitor.

Supported clients include OkHttp and libraries built on it, such as Retrofit, when configured with the wrapped factory. Other HTTP clients, including Ktor, Volley, Cronet, and `HttpURLConnection`, are not automatically instrumented.

#### 6 Run and verify

Build and run your Android application on an emulator or physical device.

1. Open the application.
2. Navigate between screens and trigger a few network requests.
3. Go to **RUM → Session Explorer** in Middleware.
4. Verify that your application sessions appear.

Read more about [RUM explorer](https://docs.middleware.io/features/rum/session-explorer) and see what data to monitor for frontend performance.

Telemetry should begin appearing after the application generates activity.

## Optional configuration

### Enable or disable monitoring features

Crash reporting, ANR detection, network change monitoring, and slow rendering detection are enabled by default.

You can disable individual features during initialization:

```java
Middleware.builder()
    .setTarget("https://<MW_UID>.middleware.io")
    .setRumAccessToken("<MW_RUM_ACCESS_TOKEN>")
    .setServiceName("my-android-app")
    .setProjectName("Android-App")
    .disableCrashReporting()
    .disableAnrDetection()
    .disableNetworkMonitor()
    .disableSlowRenderingDetection()
    .build(this);
```

Only include the `disable...()` methods for features you do not want to collect.

| Method | Description |
| --- | --- |
| `disableCrashReporting()` | Disables automatic crash reporting |
| `disableAnrDetection()` | Disables ANR detection |
| `disableNetworkMonitor()` | Disables network connectivity monitoring |
| `disableSlowRenderingDetection()` | Disables slow and frozen frame detection |
| `setSlowRenderingDetectionPollInterval(Duration)` | Changes the rendering detection interval; default is 1,000 ms |

## Configure Session Replay

Session Replay is enabled by default and starts when the SDK initializes. No additional lifecycle hooks are required with SDK 3.x.

You can configure recording frequency, quality, and privacy settings:

```java
RecordingOptions.Builder recordingOptions =
    new RecordingOptions.Builder();

recordingOptions.setFrequency(RecordingFrequency.STANDARD);
recordingOptions.setQuality(RecordingQuality.STANDARD);
recordingOptions.setMaskAllTextInputs(true);
recordingOptions.setMaskAllImages(true);

Middleware.builder()
    .setTarget("https://<MW_UID>.middleware.io")
    .setRumAccessToken("<MW_RUM_ACCESS_TOKEN>")
    .setServiceName("my-android-app")
    .setProjectName("Android-App")
    .setRecordingOptions(recordingOptions.build())
    .build(this);
```

Recording frequency and quality support `LOW`, `STANDARD`, and `HIGH`.

### Disable Session Replay

To collect RUM telemetry without recording user sessions, add:

```java
.disableSessionRecording()
```

### Session recording limits

- Maximum duration: 4 hours per session.
- Idle timeout: 15 minutes.
- Default: Session Replay enabled.

A new session starts when the user resumes activity after the idle timeout.

## Mask sensitive information

The SDK masks text inputs and images by default. You can also exclude specific views from Session Replay.

#### Mask an Android view

```java
final Middleware middleware = Middleware.getInstance();

TextView sensitiveView = findViewById(R.id.some_text_view);

middleware.addSanitizedElement(sensitiveView);
```

### Mask a view using XML

Add the `mw-no-capture` tag:

```xml
<ImageView
    android:id="@+id/card_scan_preview"
    android:tag="mw-no-capture" />
```

You can also use:

- `mw-no-capture` — Always mask the view.
- `mw-no-mask` — Exclude the view from masking.

### Mask Jetpack Compose elements

For Jetpack Compose applications, use the Session Replay modifiers:

```kotlin
Text(
    text = cardNumber,
    modifier = Modifier.mwSessionReplayMask()
)
```

**Privacy recommendation**: Review payment screens, authentication forms, OTP fields, and other sensitive UI elements before enabling Session Replay in production.

## Configure distributed tracing

Distributed tracing connects Android network requests with backend APM traces.

When enabled, the SDK injects W3C `traceparent` headers into requests sent through the instrumented OkHttp client.

### Prerequisites

- Your Android application must use the Middleware-wrapped OkHttp `Call.Factory`.
- Backend services must have APM instrumentation enabled.
- Backend services must support W3C Trace Context propagation.

#### 1 Restrict trace propagation targets

By default, instrumented HTTP requests can include trace headers.

To restrict propagation to your backend domains, add:

```java
Middleware.builder()
    .setTarget("https://<MW_UID>.middleware.io")
    .setRumAccessToken("<MW_RUM_ACCESS_TOKEN>")
    .setServiceName("my-android-app")
    .setTracePropagationTargets(Arrays.asList(
        Pattern.compile("api\\.example\\.com"),
        Pattern.compile("checkout\\.example\\.com")
    ))
    .build(this);
```

Requests to other domains remain monitored but do not receive trace propagation headers.

#### 2 Verify trace correlation

1. Open your application and trigger a backend API request.
2. Go to **RUM → Session Explorer**.
3. Open the session and select the network event.
4. Check for `http.request.header.traceparent`.
5. Follow the correlated backend trace when available.

If the header is missing, verify that the request uses the instrumented OkHttp client.

## Add custom events, errors, and logs

### Custom events

Record application-specific interactions:

```java
Middleware.getInstance().addEvent(
    "Checkout button clicked",
    BUTTON_ATTRIBUTES
);
```

Use custom events to track actions such as checkout, onboarding, or subscription changes.

### Custom workflows

Track a multi-step user flow:

```java
Span loginWorkflow = Middleware.getInstance()
    .startWorkflow("User Login Flow");

// Execute the workflow

loginWorkflow.end();
```

### Report handled exceptions

Crashes are captured automatically. For exceptions handled by your application, report them manually:

```java
Middleware.getInstance().addException(
    new RuntimeException("Payment request failed"),
    Attributes.empty()
);
```

### Add custom logs

Use the Middleware SDK to record application logs:

```java
Middleware logger = Middleware.getInstance();

logger.d("Checkout", "Debug message");
logger.i("Checkout", "Payment initiated");
logger.w("Checkout", "Payment response delayed");
logger.e("Checkout", "Payment failed");
```

These logs provide additional context when investigating user sessions and application errors.

## Add custom attributes

Use global attributes to associate telemetry with application releases, environments, or user groups.

For example:

```java
Middleware.builder()
    .setTarget("https://<MW_UID>.middleware.io")
    .setRumAccessToken("<MW_RUM_ACCESS_TOKEN>")
    .setServiceName("my-android-app")
    .setGlobalAttributes(
        Attributes.builder()
            .put("app.version", BuildConfig.VERSION_NAME)
            .put("user.type", "premium")
            .build()
    )
    .build(this);
```

Prefer stable, non-sensitive attributes that are useful for filtering and grouping sessions.

### Set a custom screen name

By default, the SDK identifies screens using their `Activity` class names.

To override the name:

```java
Middleware.getInstance().setScreenName("checkout");
```

This is useful when multiple screens share the same `Activity` or when using custom navigation.

## Configuration reference

| Method | Description |
| --- | --- |
| `setTarget(String)` | Sets the Middleware ingestion URL |
| `setRumAccessToken(String)` | Sets the RUM access token |
| `setServiceName(String)` | Sets the application service name |
| `setProjectName(String)` | Sets the project name |
| `setDeploymentEnvironment(String)` | Sets the deployment environment |
| `setGlobalAttributes(Attributes)` | Adds custom attributes to telemetry |
| `setTracePropagationTargets(List<Pattern>)` | Restricts trace propagation to selected URLs |
| `setRecordingOptions(...)` | Configures Session Replay |
| `disableSessionRecording()` | Disables Session Replay |
| `disableCrashReporting()` | Disables crash reporting |
| `disableAnrDetection()` | Disables ANR detection |
| `disableNetworkMonitor()` | Disables network change monitoring |
| `disableSlowRenderingDetection()` | Disables slow and frozen frame detection |

## Troubleshooting

### No RUM data appears

If your application is running but telemetry does not appear:

- Verify that the SDK dependency is installed.
- Confirm that `Middleware.builder().build(this)` is called from `Application.onCreate()`.
- Check that the RUM access token and target URL are correct.
- Verify that the device can connect to Middleware over HTTPS.
- Review Android Logcat for initialization or export errors.

### HTTP requests are missing

If sessions appear but network requests do not:

- Confirm that your application uses OkHttp.
- Verify that requests pass through `createRumOkHttpCallFactory()`.
- For Retrofit, check that `.callFactory(httpClient)` uses the wrapped factory.
- Make sure other networking clients are not bypassing the instrumented client.

### Backend traces are not correlated

If network requests appear but backend traces are missing:

- Check the network event for `http.request.header.traceparent`.
- Verify that backend APM instrumentation is enabled.
- Confirm that your backend accepts W3C Trace Context.
- Check `setTracePropagationTargets()` for incorrect host patterns.

### Session Replay is missing

If sessions appear without recordings:

- Verify that `disableSessionRecording()` is not enabled.
- Check the application's consent and privacy configuration.
- Confirm that recording initialization completes successfully.
- Review SDK logs for recording or upload errors.

### App crashes or ANRs are not reported

- Verify that crash reporting and ANR detection have not been disabled.
- Confirm that the SDK initializes early in the application lifecycle.
- Check that the device has network connectivity.
- For ANRs, verify that the main thread is blocked long enough to trigger detection.

### Slow or frozen frames are not reported

- Confirm that slow rendering detection is enabled.
- Verify that the application generates UI activity.
- Check the configured detection interval.

Slow frames are reported above 16 ms, and frozen frames above 700 ms.

### Network requests fail on Android 9+

Android 9 (API 28) and later block cleartext HTTP traffic by default.

- Use HTTPS for your backend APIs and Middleware ingestion endpoint.
- For local development using HTTP, configure a scoped Android Network Security Configuration for the required development hosts.

If the issue persists, contact Middleware Support at support@middleware.io.

Need assistance or want to learn more about Middleware? Get in touch with us via our Contact Us page or join our Slack channel.
