All Products
Search
Document Center

Alibaba Cloud DNS:Android SDK development guide

Last Updated:Mar 19, 2026

This document describes how to integrate the HTTPDNS Android SDK.

Overview

The Android SDK is a Java wrapper for the DoH JSON API of HTTPDNS. It provides Java interfaces for Android apps to resolve domain names and includes an efficient local cache that uses TTL and LRU policies. Developers can integrate HTTPDNS into their Android apps to resolve domain name resolution errors and achieve precise, low-cost scheduling.

The SDK offers the following advantages:

  • Simple to use

    You only need to integrate the provided SDK to access the HTTPDNS service. The integration method is straightforward and delivers an effortless, convenient resolution experience.

  • Zero latency

    The SDK implements an LRU cache that stores resolved IP addresses locally. It proactively refreshes expired TTL-based cache entries to keep cached data current and effective. This enables zero-latency domain name resolution.

For implementation guidance, refer to the alidns_android_demo sample project source code.

Integrate the SDK

Integrate the SDK

Integrate using Gradle with Maven

Add the following code to your build.gradle file:

allprojects {
  repositories {
    maven {
      url 'https://maven.aliyun.com/repository/public/'
    }
    mavenLocal()
    mavenCentral()
  }
}

Add the information for the file you want to reference:

dependencies {
     implementation 'com.alibaba.pdns:alidns-android-sdk:2.3.0'
     implementation 'com.google.code.gson:gson:2.8.5'
}

Integrate using an AAR file

Refer to SDK Download to obtain the alidns_android_sdk.aar file and integrate it into the `libs` directory of your project.

Note

You can choose either integration method for your project.

Initialize the SDK

Important

Initialize the SDK as early as possible to avoid failures when resolving IP addresses.

First, identify your Account ID in the console and create keys to obtain your AccessKey ID and AccessKey Secret. Then integrate and initialize the SDK. For specific initialization instructions, see the code examples in the Application section.

public class DnsCacheApplication extends Application{

    private String accountId = "Your Account ID"; // Set the Account ID that you use to access the SDK in the console.
    private String accessKeyId = "Your AccessKey ID"; // Set the AccessKey ID that you use to access the SDK in the console.
    private String accessKeySecret = "Your AccessKey secret"; // Set the AccessKey secret that you use to access the SDK in the console.

    @Override
    public void onCreate() {
       super.onCreate();
       DNSResolver.Init(this,accountId,accessKeyId,accessKeySecret); // Set the Account ID, AccessKey ID, and AccessKey secret that you use to access the SDK in the console.
       // Note: If you configure domain names to be kept in the cache, resolution is automatically initiated when 75% of the TTL elapses. This ensures that the resolution of configured domain names always hits the cache. However, if you use a CDN, the TTL value may be small. This results in many resolution requests and increases costs. Use this method with caution.
       DNSResolver.setKeepAliveDomains(new String[]{"The domain name to be kept in the cache 1","The domain name to be kept in the cache 2",...});
       DNSResolver.getInstance().preLoadDomains(DNSResolver.QTYPE_IPV4,new String[]{"The domain name to be pre-resolved 1","The domain name to be pre-resolved 2",...}); // Set the specified domain names of the IPv4 type for pre-resolution. Replace the pre-resolution domain names with the domain names that you want to resolve using Alibaba Cloud DNS.
    }
}
Note

DNSResolver is the core class of the HTTPDNS SDK. It encapsulates the DoH JSON API provided by HTTPDNS to resolve a user’s target domain name into the corresponding IP address. When integrating the HTTPDNS SDK, we recommend integrating it in the Application child class.

Your Android app must also declare the following permissions:

<!--Required permissions-->
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
   <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

Authenticate the SDK

Starting from version 2.0, this SDK supports authentication to protect user identity security and prevent unauthorized third-party misuse. To enable authentication, refer to Create Keys to create an AccessKey ID and an AccessKey Secret in the console. If you do not configure authentication parameters during SDK initialization, HTTPDNS rejects domain name resolution requests without authentication. This disables domain name resolution functionality and affects your business operations. Therefore, you must configure authentication parameters when initializing the HTTPDNS SDK.

Set authentication parameters as follows:

DNSResolver.Init(this,accountId,accessKeyId,accessKeySecret);
Warning
  • To prevent sensitive parameters such as Account ID, AccessKey ID, or AccessKey secret—or data generated during app runtime—from appearing in logs, disable SDK debug logging in production builds.

  • Because all users integrate the same SDK, you must set the Account ID, AccessKey ID, and AccessKey secret in your code. These parameters are tied to metering and billing. To prevent malicious decompilation from exposing them, enable obfuscation and reinforce your app before publishing.

Common SDK integration issues

Android 9.0 throws "cleartext HTTP traffic not permitted" when sending HTTP requests

Cause: Starting with Android 9.0 (API level 28), Android blocks cleartext network traffic by default and allows only HTTPS URLs.

Solution

Add the following line to the <application> element in your AndroidManifest.xml file:

android:usesCleartextTraffic="true"

<application
        android:name=".DnsCacheApplication"
        android:icon="@mipmap/ic_launcher"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:usesCleartextTraffic="true">

Android 9.0 throws "Didn't find class BasicHttpParams"

Cause: Apache HTTP client is deprecated.

Google removed support for the Apache HTTP client in Android 6.0. Starting with Android 9.0, org.apache.http.legacy is removed from the bootclasspath.

This change does not affect most applications with a taskVersion less than 9.0. For applications with a taskVersion greater than 9.0, an Apache HTTP interface not found exception will occur if the Apache HTTP interface is used, either directly or by a referenced lib package.

Solution

Add the following line to the <application> element in your AndroidManifest.xml file:

<uses-library android:name="org.apache.http.legacy" android:required="false"/>

This SDK introduces JNI starting from version 2.1.9. Configure NDK in your app project

  • Add the NDK installation path to the local.properties file in your app project root directory:

ndk.dir=...\\ndk\\21.4.7075529; // ... is the local NDK installation path
  • Add the following configuration to the gradle.properties file in your app project root directory:

android.useDeprecatedNdk = true;

If your app project already has NDK configured, skip this step. For best results, compile your app using JDK 1.8 and NDK 21.4.7075529.

API reference

Common settings

1. Initialize using the Init method

Call the Init method when initializing the SDK in your Application class.

DNSResolver.Init(this,Account ID,AccessKey ID,AccessKey Secret);

2. Set pre-resolved domain names

When initializing your program, we strongly recommend pre-registering the domain names you plan to use with the HTTPDNS SDK. This allows the SDK to resolve the domain names in advance and reduces the latency of subsequent resolution requests. Call the following method to set the domain names for pre-resolution:

  • Specify IPv4 or IPv6 pre-resolution

// Set the specified domain name type for pre-resolution. Replace the pre-resolution domain names with the domain names that you want to resolve using Alibaba Cloud DNS.
DNSResolver.getInstance().preLoadDomains(DNSResolver.QTYPE_IPV4,new String[]{...});

// DNSResolver.QTYPE_IPV4: The IPv4 record type for pre-resolution.
// DNSResolver.QTYPE_IPV6: The IPv6 record type for pre-resolution.
// DNSResolver.QTYPE_IPV4_IPV6: The IPv4 and IPv6 record types for pre-resolution.
  • Auto-detect the current network environment. In dual-stack networks, pre-resolve both IPv4 and IPv6 domain names.

DNSResolver.getInstance().preLoadDomains(domains);
Important

The pre-resolution interface triggers asynchronous network requests in real time. Ensure all required initialization steps complete before calling this interface.

3. Set domains for cache keep-alive

The SDK automatically resolves configured domains when 75% of their TTL elapses. This ensures resolution requests always hit the cache and improves resolution efficiency. Limit this to no more than 10 domains. This setting is independent of pre-resolution.

DNSResolver.setKeepAliveDomains(new String[]{"User-specified domain name 1", "User-specified domain name 2"});
Note

Benefits

1. Records update before the TTL expires.

2. When used with preloading, initial parsing latency can be reduced to 0 ms.

Disadvantages

1. Re-resolving at 75% TTL incurs additional fees.

4. Enable or disable IPv6 server addresses

HTTPDNS supports dual-stack IPv4 and IPv6 address access. Use the DNSResolver.setEnableIPv6(boolean enable) method to configure whether to use server-side IPv6 addresses. When this parameter is set to true, the service uses IPv6 addresses to access the server-side interface. When set to false, it uses IPv4 addresses. If you do not explicitly configure this setting, the service defaults to IPv4. Additionally, if you enable IPv6 and the HTTPDNS service is unreachable, Automatic Failover switches to IPv4 addresses and supports one retry.

5. Set maximum cache size

DNSResolver.getInstance().setMaxCacheSize(CACHE_MAX_NUMBER); // Sets the maximum number of cache entries. The default is 100.

You can customize the maximum count.

6. Set protocol for server access

The SDK supports configuring the HTTP request protocol type for DNS resolution, allowing you to choose between HTTP and HTTPS. The SDK uses HTTPS for DNS resolution by default because it provides better security.HTTPDNS Billing is based on HTTP resolution requests, where HTTPS resolution is billed at five times the HTTP traffic. Select the HTTP request protocol type based on your business needs.

DNSResolver.setSchemaType(DNSResolver.HTTPS); // The default access mode is HTTPS.

DNSResolver.HTTP: Access server-side interfaces over HTTP.

DNSResolver.HTTPS: Access server-side interfaces over HTTPS.

7. Set port number for IP speed testing

DNSResolver.setSpeedPort(DNSResolver.PORT_80);

You can set the port number for socket-based IP probing. The default is 80.

Other advanced settings

1. Enable or disable SDK debug logging

DNSResolver.setEnableLogger(true); // SDK debug logs are disabled by default

Set to true to enable debug logs or false to disable them.

2. Set whether to enable HTTPDNS automatically downgrade to local DNS for fallback resolution when parsing fails

DNSResolver.setEnableLocalDns(true); // By default, automatic fallback to LocalDNS resolution is enabled when HTTPDNS resolution fails.

3. Enable or disable short mode

The DoH JSON API of HTTPDNS returns data in two formats: the full JSON format and the simple IP array format. You can call DNSResolver.setEnableShort(boolean enable) to enable or disable the short mode. If you do not configure DNSResolver.setEnableShort(boolean enable), the short mode is disabled by default. as follows:

DNSResolver.setEnableShort(true); // The default value is false. You do not need to set this parameter.
Important

In short mode, the SDK calls the HTTPDNS service and returns a simpler IP address array. This reduces response data volume and is suitable for scenarios where network traffic is sensitive.

4. Enable or disable non-expiring cache

DNSResolver.setImmutableCacheEnable(false); // By default, the immutable cache (cache that never expires) is disabled
Important

The SDK provides three cache update mechanisms:

  • Cache Never Expires: After you enable this feature, the cache is always treated as valid while the app is running. Cache expiration checks and updates are not performed. You do not need to call setKeepAliveDomains to manually refresh the cache. This minimizes the number of DNS resolution requests.

    How to set: DNSResolver.setImmutableCacheEnable(boolean var0)

    Parameter description: When the parameter var0 is true, the cache never expires feature is enabled. When var0 is false, the feature is disabled.

  • Active cache update: When the TTL of a keep-alive domain drops to 75% of its original value, the SDK triggers a new resolution to update the cache. This reduces latency and keeps records current when authoritative zones change. Maximum 10 domain names.

    How to set: DNSResolver.setKeepAliveDomains(String[] var1)

    Metric description: var1 is an array of domain name strings to be actively refreshed.

  • Passive cache update:

    When you call the following two methods to retrieve parsing results, the cache is updated automatically:

    • getIPsV4ByHost(String hostName) retrieves the array of IPv4 records for hostName. If the cache is not empty and within the TTL validity period, it returns the cached result. Otherwise, it retrieves the latest parsing result via a network request, returns the result, and updates the cache. This method is commonly used in scenarios where high parsing accuracy is required.

    • getIpv4ByHostFromCache(String hostName, boolean isAllowExp) retrieves an array of IPv4 records corresponding to hostName from the cache. This method determines whether to return expired DNS records from the cache based on the value of the isAllowExp parameter. We recommend using this method together with the preload method at app startup to ensure the latest DNS records are cached when the app starts.

      Description: If isAllowExp is true, the method returns stale records even if the cache has expired (or null if the cache is empty) and asynchronously updates the cache. If it is false, the method returns null when the cache is expired or empty and asynchronously updates the cache.

    Recommended pattern:

    String[] IPArray = mDNSResolver.getIpv4ByHostFromCache(hostname,true);
            if (IPArray == null || IPArray.length == 0){
                IPArray = mDNSResolver.getIPsV4ByHost(hostname);
            }

5. Enable or disable caching

DNSResolver.setEnableCache(true); // The cache is enabled by default.

Set to true to enable caching or false to disable it.

6. Enable or disable IP speed testing

DNSResolver.setEnableSpeedTest(false); // IP speed testing is disabled by default.

Set to true to enable IP speed testing or false to disable it.

7. Enable or disable ISP-based domain name caching

DNSResolver.setIspEnable(true);//Enables ISP-based domain name caching by default.

When enabled, each network environment (ISP) maintains its own cache. When disabled, all network environments share a single cache.

8. Set maximum TTL for negative cache

DNSResolver.setMaxNegativeCache(MAX_NEGATIVE_CACHE);// Set the maximum TTL for negative cache, default is 30 seconds

Negative cache stores responses for domain names with no IP address configured. Set the maximum TTL for these invalid cache entries.

9. Set maximum TTL for cache

DNSResolver.setMaxTtlCache(MAX_TTL_CACHE);// Sets the maximum TTL for the cache. The default value is 3600 seconds.

Set the maximum TTL for cached entries. If set, cached entries will not exceed this TTL. The default is 3600 seconds.

10. Set client subnet information

DNSResolver.setEdnsSubnet("1.2.XX.XX/24");

The setEdnsSubnet method supports the EDNS Client Subnet (ECS) feature (RFC 7871). It passes subnet information to the authoritative DNS server for more accurate resolution and traffic rerouting. Longer masks give more precise address information. Shorter masks improve privacy. We recommend /24.

Note

This parameter is specifically designed for scenarios where a DNS proxy uses the DoH JSON API—that is, users send DNS queries to the DNS proxy, and the DNS proxy forwards the user's subnet information using this parameter to HTTPDNS, and finally to authoritative DNS servers.

For example, DNSResolver.setEdnsSubnet("1.2.XX.XX/24") causes the authoritative server to receive prefix information based on the 1.2.XX.XX/24 prefix to help you select a DNS path.

11. Set domain name resolution timeout

timeout specifies the timeout period for domain name resolution. The default timeout period is 3 seconds. You can customize the timeout period, and we recommend setting it to a value between 2 and 5 seconds.

DNSResolver.setTimeout(3);

12. Get SessionId for troubleshooting

The sessionId parameter is generated when an application starts and remains unchanged throughout the application lifecycle. All HTTPDNS resolution requests within the same application lifecycle carry the same sessionId, and the server records this parameter and generates an index. The sessionId is used to track the application lifecycle and troubleshoot issues in application scenarios.

public static String getSessionId()

13. Logging callback

Logs generated by the callback SDK.

HttpDnsLog.setLogger(new ILogger() {
  @Override
  public void log(String msg) {
      Log.d("HttpDnsLogger:", msg);
  }
});

Obfuscation configuration

   -keep class com.alibaba.pdns.** {*;}

Service APIs

  /**
   * Pre-loads domain names based on the automatically detected network environment (IPv4-only, IPv6-only, or dual-stack).
   * In a dual-stack network environment, both IPv4 and IPv6 resolution results are pre-loaded. You can call this method during SDK initialization when the application starts.
   * This method pre-stores the resolution results in the cache to reduce the latency of subsequent domain name resolutions.
   *
   * @param domains The domain names to be pre-loaded.
   */
   public void preLoadDomains(final String[] domains)

    /**
     * Pre-loads specified domain names for IPv4 or IPv6 resolution.
     * You can call this method during SDK initialization when the application starts. This method pre-stores the resolution results in the cache to reduce the latency of subsequent domain name resolutions.
     *
     * @param qType Specify whether to pre-load domain names for IPv4 or IPv6 resolution.
     * @param domains The domain names to be pre-loaded.
     */
    public void preLoadDomains(String qType, final String[] domains)
   /**
   * Obtains the resolution data for the domain name based on the automatically detected network environment (IPv4-only, IPv6-only, or dual-stack).
   * If the resolution result exists in the cache and has not expired, the result from the cache is returned.
   * If the cache is empty or the cached result has expired, a synchronous network request is sent to the server to obtain the recursive resolution result. The result is then returned to you and stored in the cache.
   *
   * @param host The domain name that you want to resolve.
   * @return The optimal IP address array based on the current network environment.
   */
    public String[] getIpsByHost(String host)

/**
    * Obtains the array of IPv4 records that correspond to the hostname.
    * If the resolution result exists in the cache and has not expired, the result from the cache is returned.
    * If the cache is empty or the cached result has expired, a synchronous network request is sent to the server to obtain the recursive resolution result. The result is then returned to you and stored in the cache.
    *
    * @param hostName The hostname, such as www.taobao.com.
    * @return The array of IPv4 addresses that correspond to the hostname.
    */
  public  String[] getIPsV4ByHost(String hostName) 

   /**
    * Obtains the array of IPv6 records that correspond to the hostname.
    * @param hostName The hostname, such as www.taobao.com.
    * @return The array of IPv6 addresses that correspond to the hostname.
    */
  public String[] getIPsV6ByHost(String hostName) 

  

  /**
   * Obtains the IP address array for the resolved domain name from the cache based on the automatically detected network environment (IPv4-only, IPv6-only, or dual-stack).
   * If the cache is empty, this method returns null and initiates an asynchronous query. The query result is then stored in the cache.
   * If a resolution result exists in the cache and you allow returning expired results, the expired IP addresses are returned, and the cache is updated asynchronously.
   * If you do not allow returning expired results and the cached result has expired, this method returns null and then asynchronously updates the cache.
   *
   * @param host The domain name that you query, such as www.taobao.com.
   * @param isAllowExp Specify whether to return the resolution result of the expired domain name.
   * @return The IP address array for the resolved host from the cache.
   */
   public String[] getIpsByHostFromCache(String host, boolean isAllowExp)
   
    /**
     * Obtains the IP address array of the IPv4 record type for the resolved domain name from the cache.
     * If the cache is empty, this method returns null and initiates an asynchronous query. The query result is then stored in the cache.
     * If a resolution result exists in the cache and you allow returning expired results, the expired IP addresses are returned, and the cache is updated asynchronously.
     * If you do not allow returning expired results and the cached result has expired, this method returns null and then asynchronously updates the cache.
     *
     * @param host The domain name that you query, such as www.taobao.com.
     * @param isAllowExp Specify whether to return the resolution result of the expired domain name.
     * @return Obtain the IP address array of the IPv4 record type from the cache after the host field is resolved.
     */
    private String[] getIpv4ByHostFromCache(String host , boolean isAllowExp)

    /**
     * Obtains the IP address array of the IPv6 record type for the resolved domain name from the cache.
     * If the cache is empty, this method returns null and initiates an asynchronous query. The query result is then stored in the cache.
     * If a resolution result exists in the cache and you allow returning expired results, the expired IP addresses are returned, and the cache is updated asynchronously.
     * If you do not allow returning expired results and the cached result has expired, this method returns null and then asynchronously updates the cache.
     *
     * @param host The domain name that you query, such as www.taobao.com.
     * @param isAllowExp Specify whether to return the resolution result of the expired domain name.
     * @return Obtain the IP address array of the IPv6 record type from the cache after the host field is resolved.
     */
    private String[] getIpv6ByHostFromCache(String host , boolean isAllowExp)

  /**
  * Obtains the DomainInfo object array in the IPv4 records that correspond to the URL.
  * If the resolution result exists in the cache and has not expired, the result from the cache is returned.
  * If the cache is empty or the cached result has expired, a synchronous network request is sent to the server to obtain the recursive resolution result. The result is then returned to you and stored in the cache.
  *
  * @param url The URL, such as http://www.taobao.com.
  * @return Obtain the DomainInfo object array in the IPv4 records that correspond to the URL.
  */
  public DomainInfo[] getIPsV4DInfoByUrl(String url) 

  Note: The URL in the DomainInfo object is the URL in which the host field is automatically replaced by a specific IP address. You do not need to manually replace the host field in the URL.

  /**
   * Obtains the DomainInfo object array in the IPv6 records that correspond to the URL.
   * If the resolution result exists in the cache and has not expired, the result from the cache is returned.
   * If the cache is empty or the cached result has expired, a synchronous network request is sent to the server to obtain the recursive resolution result. The result is then returned to you and stored in the cache.
   * 
   * @param url The URL, such as http://m.taobao.com.
   * @return Obtain the DomainInfo object array in the IPv6 records that correspond to the URL.
   */
   public DomainInfo[] getIPsV6DInfoByUrl(String url) 

  /**
    * Obtains a DomainInfo object in the IPv4 records that correspond to a specific URL.
    * If the resolution result exists in the cache and has not expired, the result from the cache is returned.
    * If the cache is empty or the cached result has expired, a synchronous network request is sent to the server to obtain the recursive resolution result. The result is then returned to you and stored in the cache.
    *
    * @param url The URL, such as http://m.taobao.com.
    * @return Obtain a DomainInfo object in the IPv4 records that correspond to the URL.
    */
    public DomainInfo getIPV4DInfoByUrl(String url) 


  /**
    * Obtains a DomainInfo object in the IPv6 records that correspond to a specific URL.
    * If the resolution result exists in the cache and has not expired, the result from the cache is returned.
    * If the cache is empty or the cached result has expired, a synchronous network request is sent to the server to obtain the recursive resolution result. The result is then returned to you and stored in the cache.
    *
    * @param url The URL, such as http://www.taobao.com.
    * @return Obtain a DomainInfo object in the IPv6 records that correspond to the URL.
    */
   public DomainInfo getIPV6DInfoByUrl(String url) 

   Note: The returned DomainInfo object encapsulates the following properties.

  /**
   * The auto-increment ID of the endpoint.
    */
    public String id = null;

   /**
    * The URL that can be directly used. The host in the URL is replaced by an IP address.
    */
     public String url = null;

    /**
    * The service name that needs to be included in the header of the HTTP request.
    */
    public String host = "";

   /**
    * The returned content body.
    */
   public String data = null;

   /**
    * The time when the request starts.
    */
   public String startTime = null;

   /**
    * The time when the request ends. If the request times out, this value is null.
    */
   public String stopTime = null; 

   /**
   * The returned server status code, such as 200, 404, or 500.
   */
   public String code = null;

  /**
    * Obtains the IPv4 record that corresponds to the hostname.
    * If the resolution result exists in the cache and has not expired, the result from the cache is returned.
     * If the cache is empty or the cached result has expired, a synchronous network request is sent to the server to obtain the recursive resolution result. The result is then returned to you and stored in the cache.
  
    * @param hostName The hostname, such as www.taobao.com.
    * @return A random IPv4 address in the set of IPv4 addresses that correspond to the hostname is returned. If connection speed testing of IP addresses is enabled, the optimal IPv4 address is returned.
    */
  public String getIPV4ByHost(String hostName) 

   /**
    * Obtains the IPv6 record that corresponds to the hostname.
    * If the resolution result exists in the cache and has not expired, the result from the cache is returned.
    * If the cache is empty or the cached result has expired, a synchronous network request is sent to the server to obtain the recursive resolution result. The result is then returned to you and stored in the cache.
  
    * @param hostName The hostname, such as www.taobao.com.
    * @return Obtain a random IPv6 address in the set of IPv6 addresses that correspond to the hostname. If connection speed testing of IP addresses is enabled, the optimal IPv6 address is returned.
    */
   public String getIPV6ByHost(String hostName) 
      

    /**
     * Obtains the statistics on successful and failed requests for HTTPDNS.
     *
     * @return Obtain the JSON array string of the resolution statistics on all domain names.
     */
    public String getRequestReportInfo()
    
     /**
     * Sets the cache reserve for domain names. The resolution of a configured domain name is automatically initiated when 75% of the TTL elapses. This ensures that the resolution of the configured domain name always hits the cache and improves the resolution efficiency of the SDK.
     * We recommend that you do not configure an excessive number of domain names for this feature. The current limit is 10 domain names. This feature is configured independently of the pre-resolution feature.
     *
     * @param persistentCacheDomains
     */
    public synchronized static void setKeepAliveDomains(String[] persistentCacheDomains) {
    
     /**
     * Purges the cache of specified domain names. If the hostname is null, the cache of all domain names is purged.
     *
     * @param domains The array of domain names whose cache you want to purge.
     */
    public void clearHostCache(String[] domains){

API usage examples

URL: Input endpoint, for example http://www.taobao.com.

 String hostname = "www.taobao.com";
 String url = "http://www.taobao.com";

1. Get optimal IP data for the current network environment

String[] ip = DNSResolver.getInstance().getIpsByHost(hostname); // Get the optimal IP address from domain name resolution for the current network.

2. Preload domain name resolution for the current network environment

DNSResolver.getInstance().preLoadDomains(domains); // Pre-resolves domain names. Replace `domains` with the domain names that you want Alibaba Cloud DNS to resolve.

3. Retrieve cached domain name resolutions for the current network environment

String[] ip = DNSResolver.getInstance().getIpsByHostFromCache(hostname,true);// Get domain name resolution data from the cache for the current network environment.

4. Get an IPv4 address

String IPV4 = DNSResolver.getInstance().getIPV4ByHost(hostname); // Get the IPv4 address from domain name resolution.

5. Get an IPv6 address

String IPV6 =  DNSResolver.getInstance().getIPV6ByHost(hostname); // Get the IPv6 address from domain name resolution.

6. Retrieve the resolved IPv4 address from the cache

String[] IPV4 =  DNSResolver.getInstance().getIpv4ByHostFromCache(hostname , true); // Get the resolved IPv4 address from the cache.

7. Retrieve the resolved IPv6 address from the cache

String[] IPV6 =  DNSResolver.getInstance().getIpv6ByHostFromCache(hostname , true); // Get the resolved IPv6 address from the cache.

8. Retrieve the DomainInfo object by URL

DomainInfo dinfo = DNSResolver.getInstance().getIPV4DInfoByUrl(url); // Get the replaced URL.

9. Clear the resolution cache for a specific domain name

DNSResolver.getInstance().clearHostCache(hostName); // Clear the cache for a specified domain name. Set hostName to null to clear the cache for all domain names.

10. Retrieve statistics for successful and failed Alibaba Cloud DNS requests

String reportInfo = DNSResolver.getInstance().getRequestReportInfo(); // Get statistics about successful and failed requests.

The fields in the JSON string array of domain name resolution statistics are described as follows:

 [
      {
         "avgRtt":"1",                         // Average domain name resolution time, in milliseconds (ms)
         "degradeLocalDnsCount": 0,            // Number of times degraded to Local DNS
         "domainName":"www.example.com",       // Domain name being resolved
         "hitDnsCacheCount": 1,                // Number of cache hits
         "httpabnormalCount": 0,               // Number of failed recursive queries
         "isp": "China Mobile",                // ISP name
         "localDnsResolveErrCount": 0,         // Number of Local DNS resolution failures
         "maxRtt": 8.0,                        // Maximum domain name resolution time, in milliseconds (ms)
         "nonetworkCount": 0,                  // Number of times with no network connectivity
         "permissionErrCount": 0,              // Number of user authentication failures
         "queryType": 1,                       // IP type. 1 indicates IPv4. 28 indicates IPv6
         "recursiveReqCount": 1,               // Number of recursive queries
         "reqParameterErrCount": 0,            // Number of request parameter format errors
         "reqPathErrCount": 0,                 // Number of URL errors
         "reqServerErrCount": 0,               // Number of DNS server-side errors
         "reqTimeoutCount": 0,                 // Number of DNS service timeout errors
         "resolveSuccessCount": 1,             // Number of successful resolutions
         "timeoutCount": 0,                    // Number of network timeout errors
         "utfNetWorkErroNum": 0                // Number of data reporting timeout errors
      }
         ......
 ]
Important

Statistics for domain name resolution requests to HTTPDNS are aggregated by the statistical dimensions of network environment, domain name, and request type.

Examples

public class MainActivity extends AppCompatActivity {
   private Button button;
   private TextView tvInfo;
   private TextView tvResult;
   private String hostUrl = "http://www.taobao.com"; // Replace this with the hostUrl that you want to resolve.
   private String hostName = "www.taobao.com"; // Replace this with the hostName that you want to resolve.
   private static final String TAG = "PDnsDemo";
   private static ExecutorService pool = Executors.newSingleThreadExecutor();
   private static final String PDNS_RESULT = "pdns_result";
   private static final int SHOW_CONSOLE_TEXT = 10000;
   private Handler mHandler;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.demo_activity_main);
       init();
       initHandler();
   }
 private void init() {
       tvInfo = findViewById(R.id.tv_respons_info);
       tvResult = findViewById(R.id.tv_respons);
       button = findViewById(R.id.btn_onclik);
       button.setOnClickListener(new View.OnClickListener() {
           public void onClick(View view) {
               new Thread(new Runnable() {
                      @Override
                      public void  run() {
                      // Call the getIPV4ByHost method from the HTTPDNS SDK to obtain the resolved IP address of the target domain name.
                      String ip = DNSResolver.getInstance().getIPV4ByHost(hostName);
                      if(ip != null){
                         tvInfo.setText("The resolved IP for the domain is: "+ ip);
                      }
                      // Call the getIPV4DInfoByUrl method from the HTTPDNS SDK to obtain a DomainInfo object. The URL in this object is the original URL with its host replaced by the resolved IP address.
                      DomainInfo dinfo = DNSResolver.getInstance().getIPV4DInfoByUrl(hostUrl);
                      if (dinfo != null) {
                           showResponse(dinfo);
                      }
                   }
               }).start();
           }
       });
   }
   private void initHandler() {
       mHandler = new Handler() {
           @Override
           public void handleMessage(Message msg) {
               switch (msg.what)  {
                   case SHOW_CONSOLE_TEXT:
                       tvResult.setText(msg.getData().getString(PDNS_RESULT) + "\n");
                       break;
               }
           }
       };
   }
   private void showResponse(final DomainInfo dinfo) {
                // Send an HTTP request
               String requestUrl = dinfo.url;
               HttpURLConnection conn = null;
               try {
                   URL url = new URL(requestUrl);
                   conn = (HttpURLConnection) url.openConnection();
                   // When accessing using an IP address, you must set the host field in the HTTP request header to the resolved domain name.
                   conn.setRequestProperty("Host", url.getHost()); // Set the host field in the HTTP request header.
                   DataInputStream dis = new DataInputStream(conn.getInputStream());
                   int len;
                   byte[] buff = new byte[4096];
                   StringBuilder response = new StringBuilder();
                   while ((len = dis.read(buff)) != -1) {
                       response.append(new String(buff, 0, len));
                   }
                   Log.d(TAG, "Response: " + response.toString());
                   dis.close();
                   sendMessage(response.toString());
               } catch (IOException e) {
                   e.printStackTrace();
               } finally {
                   if (conn != null) {
                       conn.disconnect();
                   }
               }
           }
   private void sendMessage(String message) {
       if (mHandler != null) {
               Message msg = mHandler.obtainMessage();
               Bundle bundle = new Bundle();
               bundle.putString(PDNS_RESULT, message);
               msg.setData(bundle);
               msg.what = SHOW_CONSOLE_TEXT;
               mHandler.sendMessage(msg);
       }
   }
}

public class DnsCacheApplication extends Application {
    
    private String Account ID = "your Account ID"; // Set your Account ID for SDK integration in the console.
    private String AccessKey ID = "your AccessKey ID"; // Set your AccessKey ID for SDK integration in the console.
    private String AccessKey Secret = "your AccessKey secret"; // Set your AccessKey secret for SDK integration in the console.

    @Override
    public void onCreate() {
       super.onCreate();
       DNSResolver.Init(this, Account ID, AccessKey ID, AccessKey Secret); // Configure the Account ID, AccessKey ID, and AccessKey secret for SDK integration in the console.
       DNSResolver.setKeepAliveDomains(new String[]{"domain-name-1", "domain-name-2", ...}); // Configure domain names for cache reserve. These domain names are automatically resolved at 75% of their TTL to ensure cache hits during domain name resolution.
       DNSResolver.getInstance().preLoadDomains(DNSResolver.QTYPE_IPV4, new String[]{"domain-name-to-preload-1", "domain-name-to-preload-2", ...}); // Pre-resolve IPv4 domain names. Replace the preloaded domain names with the domain names you want to resolve using Alibaba Cloud DNS.
    }
}

Best practices for domain name resolution

Pre-resolution + Allow expired replies = Best performance

In high-performance network scenarios, combining pre-resolution with allowing expired replies significantly improves DNS resolution speed—even achieving zero-latency resolution.

Thanks to the SDK’s built-in caching, after pre-resolution, subsequent requests for the same domain name hit the cache directly. This avoids network round trips and greatly improves user experience.

1. Pre-resolution

Enable caching and pre-resolve critical domain names (recommended at app startup).

In the Application class, parse the domain names used in your business logic in advance in the onCreate() method, and cache the results in local memory.

1. For IPv4-only environments

// ******** For scenarios that support IPv4 only *******
public class DnsCacheApplication extends Application{
    private String Account ID = "your Account ID"; // Set your Account ID for SDK integration in the console
    private String AccessKey ID = "your AccessKey ID"; // Set your AccessKey ID for SDK integration in the console
    private String AccessKey Secret = "your AccessKey secret "; // Set your AccessKey secret for SDK integration in the console

    @Override
    public void onCreate() {
       super.onCreate();
       DNSResolver.Init(this,Account ID,AccessKey ID,AccessKey Secret); // Set your Account ID, AccessKey ID, and AccessKey secret for SDK integration in the console
       DNSResolver.setEnableCache(true); // Enable caching. Default value: true
       // IPv4 record type for pre-resolution    
       DNSResolver.getInstance().preLoadDomains(DNSResolver.QTYPE_IPV4,new String[]{"example-domain-1.com","example-domain-2.com",...}); // Pre-resolve domain names of the specified IPv4 type. Replace the sample domain names with the domain names you want to resolve using Alibaba Cloud DNS.
    }
}

2. For IPv6-enabled environments

//********This applies to scenarios that require IPv6 support.*******
public class DnsCacheApplication extends Application{
    private String accountID = "your_account_id"; // Set the Account ID for accessing the SDK from the console.
    private String accessKeyID = "your_accesskey_id"; // Set the AccessKey ID for accessing the SDK from the console.
    private String accessKeySecret = "your_accesskey_secret"; // Set the AccessKey secret for accessing the SDK from the console.

    @Override
    public void onCreate() {
       super.onCreate();
       // Set the Account ID, AccessKey ID, and AccessKey secret for accessing the SDK from the console.
       DNSResolver.Init(this, accountID, accessKeyID, accessKeySecret);
       // Specify whether to enable caching. This feature is enabled by default.
       DNSResolver.setEnableCache(true);
       // Specify whether to enable domain name resolution over an IPv6 network. This feature is disabled by default.
       DNSResolver.setEnableIPv6(true);  
       // Specify whether to enable IP speed testing. This feature is disabled by default.
       DNSResolver.setEnableSpeedTest(true); 
       // Pre-resolve domain names into IPv4 and IPv6 addresses.
       // Pre-resolve the specified domain names of the IPv4 and IPv6 types. Replace the sample domain names with the domain names that you want to resolve using Alibaba Cloud DNS.
       DNSResolver.getInstance().preLoadDomains(DNSResolver.QTYPE_IPV4_IPV6,new String[]{"your_domain_to_preload_1","your_domain_to_preload_2",...});
    }
}

2. Allow expired replies

Use cached results first (allow expired IPs). Before sending a network request, get the IP address from the cache and allow using expired but still usable cache entries. This delivers immediate results—even after TTL expiry—as long as the cache entry exists. This achieves zero wait time.

1. For IPv4-only environments

    //********Applicable to scenarios that support only IPv4*******
    @Override
    public List<InetAddress> lookup(@NonNull String hostname) throws UnknownHostException {
        // Prioritize retrieving IP addresses from the cache (second parameter set to true allows returning expired but active records)
        String[] IPArray = mDNSResolver.getIpv4ByHostFromCache(hostname,true);
        if (IPArray == null || IPArray.length == 0){
            // Cache miss, initiate asynchronous resolution
            IPArray = mDNSResolver.getIPsV4ByHost(hostname);
        }
        if (IPArray != null && IPArray.length > 0) {
            List<InetAddress> inetAddresses = new ArrayList<>();
            InetAddress address;
            for (String ip : IPArray) {
                address = InetAddress.getByName(ip);
                inetAddresses.add(address);
            }
            if (!inetAddresses.isEmpty()) {
                return inetAddresses;
            }
        }
        return okhttp3.Dns.SYSTEM.lookup(hostname);
    }

2. For IPv6-enabled environments

    //********Applies to scenarios that require IPv6 support*******
    @Override
    public List<InetAddress> lookup(@NonNull String hostname) throws UnknownHostException {
        // First retrieve IP addresses from the cache (the second parameter is set to true to allow returning expired but active records)
        String[] IPArray = mDNSResolver.getIpsByHostFromCache(hostname,true);
        if (IPArray == null || IPArray.length == 0){
            // Cache miss: initiate asynchronous resolution
            IPArray = mDNSResolver.getIpsByHost(hostname);
        }
        if (IPArray != null && IPArray.length > 0) {
            List<InetAddress> inetAddresses = new ArrayList<>();
            InetAddress address;
            for (String ip : IPArray) {
                address = InetAddress.getByName(ip);
                inetAddresses.add(address);
            }
            if (!inetAddresses.isEmpty()) {
                return inetAddresses;
            }
        }
        return okhttp3.Dns.SYSTEM.lookup(hostname);
    }

Usage notes

  1. After obtaining the IP address of the domain name through HTTPDNS, the client can use this IP to send business requests, and the Host field in the HTTP request header must be set to the original domain name.

  2. To ensure normal operation of your business, when the HTTPDNS SDK returns an empty IP address for domain name resolution, application developers must use the original domain-based request URL for fallback requests. The following example code shows this:

    String ip = DNSResolver.getInstance().getIPV4ByHost("domain name");
    if (ip != null) {
    	// Replace the host in the URL with the IP address to make the API request.
    }else {
    	// Make a fallback request using the request URL with the original domain name.
    }
  3. To help you get started with the HTTPDNS SDK more quickly, we provide developers with a demo program that you can download locally for reference. Click here to download the demo program.

  4. After you complete SDK integration, check the Traffic Analysis section of the console to verify that the integration is successful. If no traffic is generated, verify that the Account ID, AccessKey ID, and AccessKey Secret parameters are configured correctly.

On-premises DNS

Starting with v2.3.0, the HTTPDNS Android SDK supports on-premises DNS deployments.

On-premises DNS is suitable for scenarios with strict compliance or custom resolution policy requirements—such as finance, government, and large internet enterprises. The SDK supports four deployment modes: public cloud DNS only, on-premises DNS only, active-standby hybrid (public cloud DNS + on-premises DNS as mutual fallback), and flexible adaptation to different business architectures.

Core capabilities

  • On-premises deployment support: Configure on-premises DNS endpoints using IPv4/IPv6 addresses or host domain names.

  • Bidirectional authentication mechanism: Uses customer-specific accessKeyId and accessKeySecret to sign requests, ensuring secure communication.

  • Circuit breaking and health check: When a self-managed DNS node fails consecutively three or more times, it is automatically circuit-broken. Thereafter, its availability is checked every minute using the specified healthCheckDomain. After recovery, it is automatically re-enabled.

  • Certificate validation control: Enable or disable TLS certificate validation (strongly recommended for production).

  • Smart fallback: When primary DNS (public cloud DNS or on-premises DNS) fails beyond a threshold, automatically switch to standby DNS to ensure high availability.

  • Seamless API compatibility: Whether using public cloud DNS or on-premises DNS, upper-layer resolution API calls remain identical—no business logic changes needed.

Configuration details

1. Use public cloud DNS only

For standard SaaS users who do not deploy on-premises DNS.

DNSResolver.Init(this, accountID,accessKeyId,accessKeySecret);

2. Use on-premises DNS only (on-premises deployment)

For customers fully dependent on on-premises DNS.

DNSResolver.InitFusionDNS(this,new String[]{"1.1.X.X","2.2.X.X"},null,null,"443", "check.example.com", "your_fusion_ak", "your_fusion_sk");
// Optional: Disable certificate validation (staging environment only)
// DNSResolver.setEnableCertificateValidation(false);

3. Public cloud DNS as primary, on-premises DNS as standby

Fail over to on-premises DNS when primary Alibaba Cloud public HTTPDNS fails.

// Primary: public cloud DNS
DNSResolver.Init(this, accountID,accessKeyId,accessKeySecret);
    
// Secondary: on-premises DNS
DNSResolver.InitFusionDNS(this,new String[]{"1.1.X.X","2.2.X.X"},null,null,"443", "check.example.com", "your_fusion_ak", "your_fusion_sk");
// Optional: disable certificate validation (staging environment only)
// DNSResolver.setEnableCertificateValidation(false);

4. On-premises DNS as primary, public cloud DNS as standby

Fail over to Alibaba Cloud public DNS when primary on-premises DNS fails.

// Primary: On-premises DNS
DNSResolver.InitFusionDNS(this,new String[]{"1.1.X.X","2.2.X.X"},null,null,"443", "check.example.com", "your_fusion_ak", "your_fusion_sk");
// Optional: Disable certificate validation (for staging environments only).
// DNSResolver.setEnableCertificateValidation(false);

// Backup: Public cloud DNS
DNSResolver.Init(this, accountID,accessKeyId,accessKeySecret);

New service APIs

To support on-premises DNS deployment and high-availability disaster recovery, the SDK adds three core APIs for configuring on-premises DNS, controlling security policies, and enabling automatic primary-standby failover.

1. Configure on-premises DNS endpoints and authentication

    /** Configures a self-managed DNS server for private deployment. If you use only public DNS, you do not need to call this method.
     *
     * Sets the address and authentication information for the self-managed DNS server.
     * Customers pass the private DNS server's address and authentication credentials through this interface.
     * The SDK uses this information to make requests.
     * @param ctx Context
     * @param serverIpv4Arr Array of IPv4 addresses (can be null)
     * @param serverIpv6Arr Array of IPv6 addresses (can be null)
     * @param serverHostArr Array of host domain names (can be null)
     * @param port Service port (for example, "443". If null, the default value "443" is used)
     * @param healthCheckDomain Domain name used for health checks after circuit breaking. When a DNS resolution service fails consecutively more than three times, circuit breaking is triggered, and the IP address of that service enters the healthCheck state (subsequent requests will not use this service). A timer runs every minute to call the DNS resolution API using this healthCheckDomain to probe whether the DNS resolution service is available. If the probe succeeds, the service returns to the alive state (subsequent requests can use this service)
     * @param accessKeyId Customer's private access key ID (used for authentication)
     * @param accessKeySecret Customer's private access key secret (used for authentication)
     */
    public static void InitFusionDNS(Context ctx,String[] serverIpv4Arr, String[] serverIpv6Arr, String[] serverHostArr, String port, String healthCheckDomain, String accessKeyId, String accessKeySecret)

2. Control TLS certificate validation for on-premises DNS

    /**For on-premises DNS used in private deployments. You do not need to configure this method if you use only public DNS.
     *
     * Specifies whether to enable certificate validation for on-premises DNS (default: true). If the server is not configured with a domain name certificate or an IP certificate, you can set this parameter to false for testing. However, when you deploy to a production environment, we recommend that you set it to true. Otherwise, security risks may arise.
     * @param enable Set to true to enable certificate validation (default: true). Set to false to disable it.
     */
    public static void setEnableCertificateValidation(boolean enable)

3. Set automatic failover threshold for primary-standby DNS

    /**When both public cloud DNS and on-premises DNS are configured, specify the number of times DNS resolution fails on the primary DNS before automatically downgrading to the secondary DNS as a fallback. If only one DNS type is configured, you do not need to configure this method.
     *
     * Specify the number of times DNS resolution fails on the primary DNS before automatically downgrading to the secondary DNS as a fallback. If only one DNS type is configured, you do not need to configure this method.
     * @param fallbackThreshold The number of failures (default is 4 when public cloud DNS is primary, or 2 when on-premises DNS is primary).
     * Valid values are from 0 to 4. Setting 0 means immediate downgrade. The maximum value is 4.
     */
     public static void setFallbackThreshold(int fallbackThreshold)