Mobile RUM - Android SDK

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.

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:

1android {
2    compileOptions {
3        coreLibraryDesugaringEnabled true
4    }
5}
6
7dependencies {
8    coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:2.1.5"
9}

Also ensure your application has the required Android permissions:

1<uses-permission android:name="android.permission.INTERNET" />
2<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.
  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:

1dependencies {
2    implementation 'io.github.middleware-labs:android-sdk:3.0.2'
3}

Sync your Gradle project to install the SDK.

3 Initialize Middleware#

Create or update your application's Application class:

1import android.app.Application;
2
3import io.middleware.android.sdk.Middleware;
4
5public class MyApplication extends Application {
6
7    @Override
8    public void onCreate() {
9        super.onCreate();
10
11        Middleware.builder()
12            .setTarget("https://<MW_UID>.middleware.io")
13            .setRumAccessToken("<MW_RUM_ACCESS_TOKEN>")
14            .setServiceName("my-android-app")
15            .setProjectName("Android-App")
16            .setDeploymentEnvironment("PROD")
17            .build(this);
18    }
19}

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:

1<application
2    android:name=".MyApplication"
3    ... >
4</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:

1import okhttp3.Call;
2import okhttp3.OkHttpClient;
3
4import io.middleware.android.sdk.Middleware;
5
6Call.Factory httpClient = Middleware.getInstance()
7    .createRumOkHttpCallFactory(new OkHttpClient());

Use the returned Call.Factory for network requests.

For Retrofit applications:

1Retrofit retrofit = new Retrofit.Builder()
2    .baseUrl("https://api.example.com/")
3    .callFactory(httpClient)
4    .build();

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

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

1Middleware.builder()
2    .setTarget("https://<MW_UID>.middleware.io")
3    .setRumAccessToken("<MW_RUM_ACCESS_TOKEN>")
4    .setServiceName("my-android-app")
5    .setProjectName("Android-App")
6    .disableCrashReporting()
7    .disableAnrDetection()
8    .disableNetworkMonitor()
9    .disableSlowRenderingDetection()
10    .build(this);

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

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

1RecordingOptions.Builder recordingOptions =
2    new RecordingOptions.Builder();
3
4recordingOptions.setFrequency(RecordingFrequency.STANDARD);
5recordingOptions.setQuality(RecordingQuality.STANDARD);
6recordingOptions.setMaskAllTextInputs(true);
7recordingOptions.setMaskAllImages(true);
8
9Middleware.builder()
10    .setTarget("https://<MW_UID>.middleware.io")
11    .setRumAccessToken("<MW_RUM_ACCESS_TOKEN>")
12    .setServiceName("my-android-app")
13    .setProjectName("Android-App")
14    .setRecordingOptions(recordingOptions.build())
15    .build(this);

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

Disable Session Replay#

To collect RUM telemetry without recording user sessions, add:

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

1final Middleware middleware = Middleware.getInstance();
2
3TextView sensitiveView = findViewById(R.id.some_text_view);
4
5middleware.addSanitizedElement(sensitiveView);

Mask a view using XML#

Add the mw-no-capture tag:

1<ImageView
2    android:id="@+id/card_scan_preview"
3    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:

1Text(
2    text = cardNumber,
3    modifier = Modifier.mwSessionReplayMask()
4)

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:

1Middleware.builder()
2    .setTarget("https://<MW_UID>.middleware.io")
3    .setRumAccessToken("<MW_RUM_ACCESS_TOKEN>")
4    .setServiceName("my-android-app")
5    .setTracePropagationTargets(Arrays.asList(
6        Pattern.compile("api\\.example\\.com"),
7        Pattern.compile("checkout\\.example\\.com")
8    ))
9    .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:

1Middleware.getInstance().addEvent(
2    "Checkout button clicked",
3    BUTTON_ATTRIBUTES
4);

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

Custom workflows#

Track a multi-step user flow:

1Span loginWorkflow = Middleware.getInstance()
2    .startWorkflow("User Login Flow");
3
4// Execute the workflow
5
6loginWorkflow.end();

Report handled exceptions#

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

1Middleware.getInstance().addException(
2    new RuntimeException("Payment request failed"),
3    Attributes.empty()
4);

Add custom logs#

Use the Middleware SDK to record application logs:

1Middleware logger = Middleware.getInstance();
2
3logger.d("Checkout", "Debug message");
4logger.i("Checkout", "Payment initiated");
5logger.w("Checkout", "Payment response delayed");
6logger.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:

1Middleware.builder()
2    .setTarget("https://<MW_UID>.middleware.io")
3    .setRumAccessToken("<MW_RUM_ACCESS_TOKEN>")
4    .setServiceName("my-android-app")
5    .setGlobalAttributes(
6        Attributes.builder()
7            .put("app.version", BuildConfig.VERSION_NAME)
8            .put("user.type", "premium")
9            .build()
10    )
11    .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:

1Middleware.getInstance().setScreenName("checkout");

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

Configuration reference#

MethodDescription
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 [email protected].

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

What did you think of this content?