All Products
Search
Document Center

Application Real-Time Monitoring Service:Report Android application data with OpenTelemetry

Last Updated:Jun 25, 2026

After you instrument your application and report trace data to Managed Service for OpenTelemetry, Managed Service for OpenTelemetry starts monitoring your application. You can then view monitoring data, such as application topology, traces, and analyses of errors, slow transactions, and SQL. This topic describes how to instrument an Android application with OpenTelemetry and report its data.

Prerequisites

Obtain an endpoint

  1. Log on to the Application Real-Time Monitoring Service (ARMS) console. In the left-side navigation pane, click Integration Center.

  2. On the Integration Center page, click the OpenTelemetry card in the Server-side Applications section.

  3. In the OpenTelemetry panel, click the Start Integration tab, and then select a region in which you want to report data.

    Note

    When you access a region for the first time, resources are automatically initialized there.

  4. Configure the Connection Type and Export Protocol parameters and copy an endpoint.

    • Connection Type: If your service is deployed on Alibaba Cloud and resides in the region that you selected, we recommend that you set this parameter to Alibaba Cloud VPC Network. Otherwise, set this parameter to Public Network.

    • Export Protocol: Set this parameter to HTTP (recommended) or gRPC based on the protocol that is supported by the client.

    75.jpg

Demo

This topic demonstrates how to use OpenTelemetry to report trace data from an Android application. This method applies to both Java and Kotlin applications.

Sample code repository: opentelemetry-android-demo

Step 1: Create and configure an application

  1. Create an application.

    1. In Android Studio, create a new application, select the Basic Views Activity template, and then click Next.

    2. Select Java or Kotlin as the language. Set the minimum SDK version to API 24: Android 7.0 (Nougat), and then click Finish.

  2. Add dependencies.

    In the module-level or project-level build.gradle file, add the following dependencies.

    This example uses OpenTelemetry Java SDK version 1.25.0. For other versions, see Opentelemetry Java Releases. For the complete build.gradle sample code, see build.gradle.

    implementation platform('io.opentelemetry:opentelemetry-bom:1.25.0')
    implementation "io.opentelemetry:opentelemetry-api"
    implementation "io.opentelemetry:opentelemetry-context"
    implementation 'io.opentelemetry:opentelemetry-exporter-otlp'
    implementation 'io.opentelemetry:opentelemetry-exporter-logging'
    implementation 'io.opentelemetry:opentelemetry-extension-kotlin'
    implementation 'io.opentelemetry:opentelemetry-sdk'
    implementation 'io.opentelemetry:opentelemetry-semconv'
  3. Configure network settings.

    1. In the app/res/xml directory, create a file named network_security_config.xml and add the following content.

      <!-- For the complete file content, see https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/res/xml/network_security_config.xml -->
      <?xml version="1.0" encoding="utf-8"?>
      <network-security-config>
        <domain-config cleartextTrafficPermitted="true">
          <!-- Replace the following domain with the endpoint obtained in the Prerequisites section. Do not include "http://", the port number, or the URL path. -->
          <domain includeSubdomains="true">tracing-analysis-dc-hz.aliyuncs.com</domain>
        </domain-config>
      </network-security-config>
    2. Modify the app/src/main/AndroidManifest.xml file and add the following two lines to enable network permissions for your application.

      <!-- For the complete file content, see https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/AndroidManifest.xml -->
      <?xml version="1.0" encoding="utf-8"?>
      <manifest ...>
        <!-- Add the following line to enable network permissions. -->
        <uses-permission android:name="android.permission.INTERNET" />
        <application
          ...
          <!-- Add the following line to apply the network configuration for the data reporting domain. -->
          android:networkSecurityConfig="@xml/network_security_config"
          ...>
          ...
        </application>
      </manifest>

Step 2: Initialize OpenTelemetry

  1. Create an OpenTelemetry utility class.

    In the same directory as MainActivity, create an OpenTelemetryUtil file and add the following content.

    • Option 1: Report trace data over gRPC

      /**
       For the complete code, visit the following link:
       https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/OpenTelemetryUtil.java
      */
      Resource otelResource = Resource.getDefault().merge(
          Resource.create(
              Attributes.of(
                  // Replace <your-service-name> with your application name.
              	ResourceAttributes.SERVICE_NAME, "<your-service-name>",
                  // Replace <your-host-name> with your host name.
              	ResourceAttributes.HOST_NAME, "<your-host-name>"
              )
          )
      );
      SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder()
          .addSpanProcessor(SimpleSpanProcessor.create(LoggingSpanExporter.create())) // Optional. Prints trace data to logs or the command line. Comment out this line if not needed.
          // Replace <gRPC-endpoint> with the endpoint and <gRPC-token> with the authentication token that you obtained in the Prerequisites section.
          .addSpanProcessor(BatchSpanProcessor.builder(
              OtlpGrpcSpanExporter.builder()
                   .setEndpoint("<gRPC-endpoint>") // Example: http://tracing-analysis-dc-hz.aliyuncs.com:8090
                   .addHeader("Authentication", "<gRPC-token>") // Example: xxxx@xxxx_xxxx@xxxx
                   .build()).build()
          )
          .setResource(otelResource)
          .build();
      OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
          .setTracerProvider(sdkTracerProvider)
          .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
          .buildAndRegisterGlobal();
      // Get a tracer to create spans.
      tracer = openTelemetry.getTracer("android-tracer", "1.0.0");
      /**
       For the complete code, visit the following link:
       https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/OpenTelemetryUtil.kt
      */
      val otelResource = Resource.getDefault().merge(
          Resource.create(
              Attributes.of(
                  ResourceAttributes.SERVICE_NAME, "<your-service-name>", // Replace <your-service-name> with your application name.
                  ResourceAttributes.HOST_NAME, "<your-host-name>"    // Replace <your-host-name> with your host name.
              )
          )
      )
      /* Report trace data over gRPC. */
      val sdkTracerProvider = SdkTracerProvider.builder()
          .addSpanProcessor(SimpleSpanProcessor.create(LoggingSpanExporter.create())) // Optional. Prints trace data to logs or the command line. Comment out this line if not needed.
      	// Replace <gRPC-endpoint> with the endpoint and <gRPC-token> with the authentication token that you obtained in the Prerequisites section.
          .addSpanProcessor(
              BatchSpanProcessor.builder(
                  OtlpGrpcSpanExporter.builder()
                      .setEndpoint("<gRPC-endpoint>") // Example: http://tracing-analysis-dc-hz.aliyuncs.com:8090
                      .addHeader("Authentication", "<gRPC-token>") // Example: xxxx@xxxx_xxxx@xxxx
                      .build()
              ).build()
          )
          .setResource(otelResource)
          .build()
      val openTelemetry: OpenTelemetry = OpenTelemetrySdk.builder()
          .setTracerProvider(sdkTracerProvider)
          .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
          .buildAndRegisterGlobal()
      // Get a tracer to create spans.
      tracer = openTelemetry.getTracer("android-tracer", "1.0.0")
    • Option 2: Report trace data over HTTP

      /**
       For the complete code, visit the following link:
       https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/OpenTelemetryUtil.java
      */
      Resource otelResource = Resource.getDefault().merge(
          Resource.create(
              Attributes.of(
                  // Replace <your-service-name> with your application name.
                  ResourceAttributes.SERVICE_NAME, "<your-service-name>",
                  // Replace <your-host-name> with your host name.
                  ResourceAttributes.HOST_NAME, "<your-host-name>"
              )
          )
      );
      SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder()
          .addSpanProcessor(SimpleSpanProcessor.create(LoggingSpanExporter.create())) // Optional. Prints trace data to logs or the command line. Comment out this line if not needed.
          // Replace <HTTP-endpoint> with the endpoint that you obtained in the Prerequisites section.
          .addSpanProcessor(BatchSpanProcessor.builder(
              OtlpHttpSpanExporter.builder()
                   .setEndpoint("<HTTP-endpoint>") // Example: http://tracing-analysis-dc-hz.aliyuncs.com/adapt_xxxx@xxxx_xxxx@xxxx/api/otlp/traces
                   .build()).build()
          )
          .setResource(otelResource)
          .build();
      OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
          .setTracerProvider(sdkTracerProvider)
          .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
          .buildAndRegisterGlobal();
      // Get a tracer to create spans.
      tracer = openTelemetry.getTracer("android-tracer", "1.0.0");
      /**
       For the complete code, visit the following link:
       https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/OpenTelemetryUtil.kt
      */
      val otelResource = Resource.getDefault().merge(
          Resource.create(
              Attributes.of(
                  ResourceAttributes.SERVICE_NAME, "<your-service-name>", // Replace <your-service-name> with your application name.
                  ResourceAttributes.HOST_NAME, "<your-host-name>"    // Replace <your-host-name> with your host name.
              )
          )
      )
      /* Report trace data over HTTP. */
      val sdkTracerProvider = SdkTracerProvider.builder()
          .addSpanProcessor(SimpleSpanProcessor.create(LoggingSpanExporter.create())) // Optional. Prints trace data to logs or the command line. Comment out this line if not needed.
      	// Replace <HTTP-endpoint> with the endpoint that you obtained in the Prerequisites section.
          .addSpanProcessor(BatchSpanProcessor.builder(
              OtlpHttpSpanExporter.builder()
                  .setEndpoint("<HTTP-endpoint>") // Example: http://tracing-analysis-dc-hz.aliyuncs.com/adapt_xxxx@xxxx_xxxx@xxxx/api/otlp/traces
                  .build()).build()
                           )
          .setResource(otelResource)
          .build();
      val openTelemetry: OpenTelemetry = OpenTelemetrySdk.builder()
          .setTracerProvider(sdkTracerProvider)
          .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
          .buildAndRegisterGlobal()
      // Get a tracer to create spans.
      tracer = openTelemetry.getTracer("android-tracer", "1.0.0")
  2. Initialize OpenTelemetry when the application starts.

    Call the OpenTelemetryUtil.init() method in the onCreate method of MainActivity.

    /**
     For the complete code, visit the following link:
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/MainActivity.java
    */
    ...
    public class MainActivity extends AppCompatActivity {
    	...
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // Add this line to initialize OpenTelemetry.
            OpenTelemetryUtil.init();
            ...
        }
        ...
    }
    /**
     For the complete code, visit the following link:
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/MainActivity.kt
    */
    ...
    class MainActivity : AppCompatActivity() {
        ...
        override fun onCreate(savedInstanceState: Bundle?) {
            WindowCompat.setDecorFitsSystemWindows(window, false)
            super.onCreate(savedInstanceState)
            // Add this line to initialize OpenTelemetry.
            OpenTelemetryUtil.init()
                ...
        }
    }

Step 3: Create spans to track traces

  1. Create a span.

    In the button click event listener of the FirstFragment file, create a span named First Fragment Button onClick.

    /**
     For the complete code, visit the following link:
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/FirstFragment.java
    */
    public void onClick(View view) {
        // Get the tracer.
        Tracer tracer = OpenTelemetryUtil.getTracer();
    	// Create a span.
        Span span = tracer.spanBuilder("First Fragment Button onClick").startSpan();
    	try (Scope scope = span.makeCurrent()) {
            // Get the traceId.
            System.out.println(span.getSpanContext().getTraceId());
            ...
        } finally {
            span.end();
        }
    }
    /**
     For the complete code, visit the following link:
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/FirstFragment.kt
    */
    binding.buttonFirst.setOnClickListener {
        // Get the tracer.
        val tracer: Tracer = OpenTelemetryUtil.getTracer()!!
        // Create a span.
        val span = tracer.spanBuilder("First Fragment Button onClick").startSpan()
        try {
            span.makeCurrent().use { scope ->
                // Get the traceId.
                println(span.spanContext.traceId)
                // Get the spanId.
                println(span.spanContext.spanId)
                findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
            }
        } catch (t: Throwable) {
            span.setStatus(StatusCode.ERROR, "Something wrong in onClick")
            throw t
        } finally {
            span.end()
        }
    }
  2. Set attributes and events for the span.

    /**
     For the complete code, visit the following link:
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/FirstFragment.java
    */
    // Set an attribute.
    span.setAttribute("key", "value");
    Attributes eventAttributes = Attributes.of(
        AttributeKey.stringKey("key"), "value",
        AttributeKey.longKey("result"), 0L);
    // Add an event.
    span.addEvent("onClick", eventAttributes);
    /**
     For the complete code, visit the following link:
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/FirstFragment.kt
    */
    // Set an attribute.
    span.setAttribute("key", "value")
    val eventAttributes =
        Attributes.of(
            AttributeKey.stringKey("key"), "value",
            AttributeKey.longKey("result"), 0L
        )
    // Add an event.
    span.addEvent("onClick", eventAttributes)
  3. Set the status for the span.

    /**
     For the complete code, visit the following link:
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/FirstFragment.java
    */
    ...
    try (Scope scope = span.makeCurrent()) {
        ...
    } catch (Throwable t) {
        // Set the span status.
        span.setStatus(StatusCode.ERROR, "Something wrong in onClick");
        throw t;
    } finally {
        span.end(); 
    }
    /**
     For the complete code, visit the following link:
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/FirstFragment.kt
    */
    ...
    try {
        ...
    } catch (t: Throwable) {
        // Set the span status.
        span.setStatus(StatusCode.ERROR, "Something wrong in onClick")
        throw t
    } finally {
        span.end()
    }
  4. Create nested spans.

    /**
     For the complete code, visit the following link:
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/FirstFragment.java
    */
    public void parentSpan() {
        // Get the tracer.
        Tracer tracer = OpenTelemetryUtil.getTracer();
        // Create a span.
        Span span = tracer.spanBuilder("Parent Span").startSpan();
        try (Scope scope = span.makeCurrent()) {
            // Get the traceId.
            System.out.println(span.getSpanContext().getTraceId());
            // Get the spanId.
            System.out.println(span.getSpanContext().getSpanId());
            childSpan();
        } finally {
            span.end();
        }
    }
    public void childSpan() {
        // Get the tracer.
        Tracer tracer = OpenTelemetryUtil.getTracer();
        // Create a span.
        Span span = tracer.spanBuilder("Child Span").startSpan();
        try (Scope scope = span.makeCurrent()) {
            // Get the traceId.
            System.out.println(span.getSpanContext().getTraceId());
            // Get the spanId.
            System.out.println(span.getSpanContext().getSpanId());
        } finally {
            span.end();
        }
    }
    /**
     For the complete code, visit the following link:
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/FirstFragment.kt
    */
    // Nested span.
    fun parentSpan() {
        // Get the tracer.
        val tracer: Tracer = OpenTelemetryUtil.getTracer()!!
        // Create a span.
        val span = tracer.spanBuilder("Parent Span").startSpan()
        try {
            span.makeCurrent().use { scope ->
                // Get the traceId.
                println(span.spanContext.traceId)
                // Get the spanId.
                println(span.spanContext.spanId)
                childSpan()
            }
        } finally {
            span.end()
        }
    }
    // Nested span.
    fun childSpan() {
        // Get the tracer.
        val tracer: Tracer = OpenTelemetryUtil.getTracer()!!
        // Create a span.
        val span = tracer.spanBuilder("Child Span").startSpan()
        try {
            span.makeCurrent().use { scope ->
                // Get the traceId.
                println(span.spanContext.traceId)
                // Get the spanId.
                println(span.spanContext.spanId)
            }
        } finally {
            span.end()
        }
    }

Step 4: Run and view trace data

  1. Run the project and click the button on the demo application page. After you run the project in Android Studio, the AndroidJavaDemo application starts in the emulator and displays the default First Fragment page, confirming that the project is configured correctly and running as expected.

    Check the logs in Logcat. You can see the span information exported by the LoggingSpanExporter.

    2023-xx-xx 15547-15547 System.out                com.example.androidjavademo    I  0c8b92db3d8b038ea3eedd0ec25a4abb
    2023-xx-xx 15547-15547 System.out                com.example.androidjavademo    I  9ecd666297f5d8f6
    2023-xx-xx 15547-15547 System.out                com.example.androidjavademo    I  0c8b92db3d8b038ea3eedd0ec25a4abb
    2023-xx-xx 15547-15547 System.out                com.example.androidjavademo    I  7e7eaffe7bd23cb8
    2023-xx-xx 15547-15547 System.out                com.example.androidjavademo    I  0c8b92db3d8b038ea3eedd0ec25a4abb
    2023-xx-xx 15547-15547 System.out                com.example.androidjavademo    I  98ef17d962ecf4d1
    2023-xx-xx 15547-15547 LoggingSpanExporter       com.example.androidjavademo    I  'Child Span' : 0c8b92db3d8b038ea3eedd0ec25a4abb 98ef17d962ecf4d1 INTERNAL [tracer: android-tracer:1.0.0]
    2023-xx-xx 15547-15547 LoggingSpanExporter       com.example.androidjavademo    I  'Parent Span' : 0c8b92db3d8b038ea3eedd0ec25a4abb 7e7eaffe7bd23cb8 INTERNAL [tracer: android-tracer:1.0.0]
    2023-xx-xx 15547-15547 LoggingSpanExporter       com.example.androidjavademo    I  'First Fragment Button onClick' : 0c8b92db3d8b038ea3eedd0ec25a4abb 9ecd666297f5d8f6 INTERNAL [tracer: android-tracer:1.0.0]
    2023-xx-xx 15547-15585 EGL_emulation             com.example.androidjavademo    D  app_time_stats: avg=460.19ms min=2.23ms max=3653.05ms count=8
  2. Log on to the ARMS console. In the left-side navigation pane, choose Application Monitoring > Applications. On the Applications page, click the name of the application. On the page that appears, view the trace data.

    Note

    If the image icon is displayed in the Language column, the application is connected to Application Monitoring. If a hyphen (-) is displayed, the application is connected to Managed Service for OpenTelemetry.

    On the trace details page, the summary shows the duration, number of applications, trace depth, and total number of spans. The span list displays a three-level hierarchy: the root span First Fragment Button onClick (6.835 ms), the child span Parent Span (2.998 ms), and the grandchild span Child Span (0.14 ms). The application name for all of these spans is otel-android-demo, and their statuses are normal.

Step 5: Correlate client and server traces

  1. Modify the trace propagation format in the header.

    • Different protocols use different HTTP headers to propagate the trace context. For example, OpenTelemetry uses the W3C Trace Context format by default, while Zipkin uses the B3 or B3 Multi format. You can also change the default format. For more information about propagation formats, see Specify the format to pass trace data.

    • Based on your backend application's protocol, set the matching propagation format (textPropagators) on the client to correlate traces between the Android client and the backend application.

      • If the backend application uses the default OpenTelemetry W3C Trace Context format, you do not need to set textPropagators on the client.

      • If the backend application uses Zipkin's B3 or B3 Multi format, the client's textPropagators must be set to B3Propagator.

        // Set the B3 propagation format.
        OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
                .setTracerProvider(sdkTracerProvider)
                .setPropagators(ContextPropagators.create(TextMapPropagator.composite(
                        B3Propagator.injectingMultiHeaders(),
                        B3Propagator.injectingSingleHeader())))
                .buildAndRegisterGlobal();
      • If the backend application uses the Jaeger protocol, the client's textPropagators must be set to JaegerPropagator.

        // Set the Jaeger propagation format.
        OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
                .setTracerProvider(sdkTracerProvider)
                .setPropagators(ContextPropagators.create(TextMapPropagator.composite(
                        JaegerPropagator.getInstance())))
                .buildAndRegisterGlobal();
      • You can also set multiple trace propagation formats at the same time.

        // Use W3C Trace Context, B3, and Jaeger trace propagation formats simultaneously.
        OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
                .setTracerProvider(sdkTracerProvider)
                .setPropagators(ContextPropagators.create(TextMapPropagator.composite(
                        W3CTraceContextPropagator.getInstance(),
                        B3Propagator.injectingMultiHeaders(),
                        B3Propagator.injectingSingleHeader()
                        JaegerPropagator.getInstance())))
                .buildAndRegisterGlobal();
  2. Import okhttp3 and opentelemetry-okhttp.

    opentelemetry-okhttp-3.0 is an OpenTelemetry auto-instrumentation plugin for OkHttp that automatically intercepts all network requests sent through OkHttp3 and creates traces.

    • Add the following two dependencies to build.gradle.

      dependencies {
          ...
          implementation 'io.opentelemetry.instrumentation:opentelemetry-okhttp-3.0:2.3.0-alpha'
          implementation 'com.squareup.okhttp3:okhttp:4.12.0'
      }
    • Create an OkHttpConfiguration.

      import io.opentelemetry.api.OpenTelemetry;
      import io.opentelemetry.instrumentation.okhttp.v3_0.OkHttpTelemetry;
      import okhttp3.Call;
      import okhttp3.OkHttpClient;
      public class OkHttpConfiguration {
          //Use this Call.Factory implementation for making standard http client calls.
          public Call.Factory createTracedClient(OpenTelemetry openTelemetry) {
              return OkHttpTelemetry.builder(openTelemetry).build().newCallFactory(createClient());
          }
          //your configuration of the OkHttpClient goes here:
          private OkHttpClient createClient() {
              return new OkHttpClient.Builder().build();
          }
      }
  3. Use OkHttp3 to send a network request to the backend application.

    private void callHttpService() throws IOException {
        Tracer tracer = OpenTelemetryUtil.getTracer();
        // Create a span.
        Span span = tracer.spanBuilder("AsyncRequestZipkinServer").startSpan();
        System.out.println("AsyncRequestZipkinServer TraceID: " + span.getSpanContext().getTraceId());
        System.out.println("AsyncRequestZipkinServer SpanID: " + span.getSpanContext().getSpanId());
        try (Scope scope = span.makeCurrent()) {
            // Make a network request, for example, using OkHttp.
            OkHttpConfiguration configuration = new OkHttpConfiguration();
            Call.Factory tracedClient = configuration.createTracedClient(GlobalOpenTelemetry.get());
            Request request = new Request.Builder().url("${Server_Address}").get().build();
            Call call = tracedClient.newCall(request);
            try (Response response = call.execute()) {
                // Handle the response.
                String responseBody = response.body().string();
                System.out.println(responseBody);
            } catch (IOException e) {
                // Handle errors.
                e.printStackTrace();
            }
        }  finally {
            span.end();
        }
    }

    Complete code

    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Looper;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import androidx.annotation.NonNull;
    import androidx.fragment.app.Fragment;
    import androidx.navigation.fragment.NavHostFragment;
    import com.example.androidjavademo.databinding.FragmentFirstBinding;
    import java.io.IOException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import io.opentelemetry.api.GlobalOpenTelemetry;
    import io.opentelemetry.api.common.AttributeKey;
    import io.opentelemetry.api.common.Attributes;
    import io.opentelemetry.api.trace.Span;
    import io.opentelemetry.api.trace.StatusCode;
    import io.opentelemetry.api.trace.Tracer;
    import io.opentelemetry.context.Scope;
    import okhttp3.Call;
    import okhttp3.Request;
    import okhttp3.Response;
    public class FirstFragment extends Fragment {
        private FragmentFirstBinding binding;
        @Override
        public View onCreateView(
                LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState
        ) {
            binding = FragmentFirstBinding.inflate(inflater, container, false);
            return binding.getRoot();
        }
        public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            binding.buttonFirst.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    // Get the tracer.
                    Tracer tracer = OpenTelemetryUtil.getTracer();
                    // Create a span.
                    Span span = tracer.spanBuilder("First Fragment Button onClick").startSpan();
                    try (Scope scope = span.makeCurrent()) {
                        // Get the traceId.
                        System.out.println(span.getSpanContext().getTraceId());
                        // Get the spanId.
                        System.out.println(span.getSpanContext().getSpanId());
                        // Set an attribute.
                        span.setAttribute("key", "value");
                        Attributes eventAttributes = Attributes.of(
                                AttributeKey.stringKey("key"), "value",
                                AttributeKey.longKey("result"), 0L);
                        // Add an event.
                        span.addEvent("onClick", eventAttributes);
                        parentSpan();
                        NavHostFragment.findNavController(FirstFragment.this)
                                .navigate(R.id.action_FirstFragment_to_SecondFragment);
                    } catch (Throwable t) {
                        span.setStatus(StatusCode.ERROR, "Something wrong in onClick");
                        throw t;
                    } finally {
                        span.end();
                    }
                }
            });
        }
        @Override
        public void onDestroyView() {
            super.onDestroyView();
            binding = null;
        }
        public void parentSpan() {
            ExecutorService executorService = Executors.newSingleThreadExecutor();
            Handler handler = new Handler(Looper.getMainLooper());
            // Get the tracer.
            Tracer tracer = OpenTelemetryUtil.getTracer();
            // Create a span.
            Span span = tracer.spanBuilder("Parent Span").startSpan();
            try (Scope scope = span.makeCurrent()) {
                // Get the traceId.
                System.out.println(span.getSpanContext().getTraceId());
                // Get the spanId.
                System.out.println(span.getSpanContext().getSpanId());
                executorService.execute(new Runnable() {
                    @Override
                    public void run() {
                        // Make the network request.
                        try {
                            callHttpService();
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                        // After execution, switch back to the main thread through the handler to process the result.
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                // Handle UI updates or other tasks.
                                childSpan();
                            }
                        });
                    }
                });
                executorService.shutdown();
            } finally {
                span.end();
            }
        }
        public void childSpan() {
            // Get the tracer.
            Tracer tracer = OpenTelemetryUtil.getTracer();
            // Create a span.
            Span span = tracer.spanBuilder("Child Span").startSpan();
            try (Scope scope = span.makeCurrent()) {
                // Get the traceId.
                System.out.println(span.getSpanContext().getTraceId());
                // Get the spanId.
                System.out.println(span.getSpanContext().getSpanId());
            } finally {
                span.end();
            }
        }
        private void callHttpService() throws IOException {
            Tracer tracer = OpenTelemetryUtil.getTracer();
            // Create a span.
            Span span = tracer.spanBuilder("AsyncRequestZipkinServer").startSpan();
            System.out.println("AsyncRequestZipkinServer TraceID: " + span.getSpanContext().getTraceId());
            System.out.println("AsyncRequestZipkinServer SpanID: " + span.getSpanContext().getSpanId());
            try (Scope scope = span.makeCurrent()) {
                // Make a network request, for example, using OkHttp.
                OkHttpConfiguration configuration = new OkHttpConfiguration();
                Call.Factory tracedClient = configuration.createTracedClient(GlobalOpenTelemetry.get());
                Request request = new Request.Builder().url("${Server_Address}").get().build();
                Call call = tracedClient.newCall(request);
                try (Response response = call.execute()) {
                    // Handle the response.
                    String responseBody = response.body().string();
                    System.out.println(responseBody);
                } catch (IOException e) {
                    // Handle errors.
                    e.printStackTrace();
                }
            }  finally {
                span.end();
            }
        }
    }
  4. On the Trace Explorer page, view the correlated end-to-end trace connecting the client and backend applications.

    In this example, AsyncRequestZipkinServer is the Android application, and zipkin-demo-server is the backend application.