All Products
Search
Document Center

Alibaba Cloud DNS:Android OkHttp guide for retrieving DNS query time and Local DNS results

Last Updated:Dec 04, 2025

This document describes how to obtain DNS resolution time when using the okhttp library for network requests on Android.

1. Overview

When using the okhttp library for network requests on Android, you can obtain DNS resolution time through EventListener. EventListener provides multiple callback methods to track network requests at various stages, including DNS resolution, connection establishment, data transmission, and more.

On Android, you can use the InetAddress.getAllByName(String host) method to obtain the resolution results from the local DNS. You can compare these results with expected resolution results to determine if there is any hijacking.

2. Methods for obtaining DNS resolution time

The following are steps for using okhttp and EventListener to obtain DNS resolution time:

Step 1: Import the okhttp library

Ensure that you add the build.gradle dependency for okhttp in your file:

implementation 'com.squareup.okhttp3:okhttp:4.9.3'

Step 2: Create a custom EventListener

You need to create a custom EventListener class to monitor and record DNS resolution time:

import okhttp3.EventListener;
import okhttp3.Call;
import okhttp3.HttpUrl;

public class DnsTimingEventListener extends EventListener {
    private long dnsStartTime;
    private long dnsEndTime;

    @Override
    public void dnsStart(Call call, String domainName) {
        super.dnsStart(call, domainName);
        dnsStartTime = System.currentTimeMillis();
    }

    @Override
    public void dnsEnd(Call call, String domainName, List<InetAddress> inetAddressList) {
        super.dnsEnd(call, domainName, inetAddressList);
        dnsEndTime = System.currentTimeMillis();
        long dnsDuration = dnsEndTime - dnsStartTime;
        System.out.println("DNS resolution time: " + dnsDuration + " milliseconds");
    }
}

Step 3: Create an OkHttpClient instance and set EventListener.Factory

You can set the custom EventListener factory to the OkHttpClient instance:

import okhttp3.OkHttpClient;

// Create OkHttpClient instance
OkHttpClient client = new OkHttpClient.Builder()
        .eventListenerFactory(new EventListener.Factory() {
            @Override
            public EventListener create(Call call) {
                return new DnsTimingEventListener();
            }
        })
        .build();

Step 4: Execute network requests

You can use the configured OkHttpClient instance to execute network requests:

import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;

public void executeNetworkRequest() {
    // Create Request object
    Request request = new Request.Builder()
    // Configure the actual URL address in .url()
            .url("https://www.example.com")
            .build();

    try {
        // Execute the request
        Response response = client.newCall(request).execute();
        // Process the response
        if (response.isSuccessful()) {
            System.out.println("Request successful");
            // You can process response data here
        } else {
            System.out.println("Request failed, status code: " + response.code());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

You can use the above method to obtain DNS resolution time and process it accordingly. This helps you understand the time consumption of network requests and can be used for performance optimization and monitoring.

You can implement the OkHttp DNS interface to use the HTTPDNS service. If you implement the OkHttp DNS interface and use HTTPDNS, the resolution time that you obtain from the preceding method is the HTTPDNS resolution time. If you do not implement the OkHttp DNS interface, OkHttp uses the system's default DNS service, InetAddress. In this case, the resolution time that you obtain is the resolution time of the system's DNS service.

You can refer to the following code to implement the DNS interface of OkHttp:

  public class OkHttpDns implements Dns {

    private static OkHttpDns instance;
    private static Object lock = new Object();
    private DNSResolver mDNSResolver = DNSResolver.getInstance();

    private OkHttpDns() {
    }

    public static OkHttpDns getInstance() {
        if (null == instance) {
            synchronized (lock) {
                if (instance == null) {
                    instance = new OkHttpDns();
                }
            }
        }
        return instance;
    }

    @Override
    public List<InetAddress> lookup(@NonNull String hostname) throws UnknownHostException {
        // Call the API provided by the HTTPDNS Android SDK for domain name resolution
        String ip = null;
        String[] ipv4Array = mDNSResolver.getIpv4ByHostFromCache(hostname,true);
        if (ipv4Array != null && ipv4Array.length > 0) {
            ip = ipv4Array[0];
        }else {
            ip = mDNSResolver.getIPV4ByHost(hostname);
        }

        if (ip != null) {
            // If the IP is not null, use it directly for the network request
            Log.d(TAG, "mDnsCache IP: " + ip);
            return Arrays.asList(InetAddress.getAllByName(ip));
        }
        // If null is returned, use the system DNS service to resolve the domain name
        return Dns.SYSTEM.lookup(hostname);
    }
}

3. Obtaining LocalDNS resolution results and performing hijacking detection comparison

You can obtain LocalDNS resolution results using the following code:

public List<String> getIPAddresses(String domain) {
    List<String> ipAddresses = new ArrayList<>();
    try {
        InetAddress[] addresses = InetAddress.getAllByName(domain);
        for (InetAddress address : addresses) {
            ipAddresses.add(address.getHostAddress());
        }
    } catch (UnknownHostException e) {
        e.printStackTrace();
    }
    return ipAddresses;
}

You can refer to the following code to compare the obtained LocalDNS resolution results with your expected resolution results to determine if there is any hijacking:

public boolean isDnsHijacked(String domain, List<String> expectedIps) {
      List<String> localIps = getIPAddresses(domain);
      if (localIps.isEmpty()) {
          return false; // Unable to resolve domain name
      }
      for (String localIp : localIps) {
          if (!expectedIps.contains(localIp)) {
              return true; // Found mismatched IP, DNS hijacking may exist
          }
      }
      return false; // All resolution results match
  }