All Products
Search
Document Center

SDK for Android developer guide

Last Updated: Jun 28, 2021

This topic describes how to develop Alibaba Cloud Public DNS SDK for Android and use it to access Alibaba Cloud Public DNS.

1.Overview

Alibaba Cloud Public DNS SDK is developed by Alibaba Cloud to provide a DNS resolution service for mobile developers.

The SDK allows mobile developers to easily access Alibaba Cloud Public DNS in their Android apps. This prevents DNS resolution errors and implements precise scheduling of DNS queries at a low cost. The demo project source code provides you with an example of how to integrate the SDK with an Android app and how to use Alibaba Cloud Public DNS in the Android app.

The current version of SDK encapsulates the JSON API for DNS over HTTPS (DoH) of Alibaba Cloud Public DNS. The SDK provides Java function interfaces for Android apps to perform DNS resolution and can effectively cache domain name resolution results based on time-to-live (TTL) and least recently used (LRU) policies. The SDK has the following benefits based on the features of Alibaba Cloud Public DNS:

  • Ease of use:

    To use Alibaba Cloud Public DNS, you need only to integrate the SDK with your app. This allows you to use the resolution service in an easier and more convenient manner.

  • DNS resolution without delay:

    LRUThe SDK implements the caching algorithm so that the IP addresses obtained from DNS resolution are cached on your local server. The SDK also automatically updates the cached data and deletes expired data based on TTL. This way, the cached data is always valid and DNS resolution can be implemented without delay.

2.Use the SDK

2.1 Integration of the SDK JAR package

  1. Log on to the Alibaba Cloud DNS console. In the left-side navigation pane, click Public DNS. On the Public DNS page, activate Alibaba Cloud Public DNS. The Overview tab displays the unique account ID that is automatically generated for your Alibaba Cloud account. You can use Alibaba Cloud Public DNS in your app based on the account ID.

  2. Click the link in the console to obtain the SDK JAR package of Alibaba Cloud Public DNS.

  3. Decompress the alidns_android_sdk.jar file of the SDK to the libs directory of your project to install the SDK. Then, you can use the SDK.

2.2 Integration of a Gradle package by using Maven

Add the following code to the build.gradle file:

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

Add the file information that you want to reference:

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

2.3 App initialization

public class DnsCacheApplication extends Application{

    private String accountID="10001"; // You can replace 10001 with your account ID.
    private static final String TAOBAO_URL="www.taobao.com";
    private static final String M_TAOBAO_URL="m.taobao.com";
    private static final String ALIYUN_URL="aliyun.com";
    private static final int CACHE_MAX_NUMBER=100; // Specify the maximum number of domain names that can be cached. The default value of CACHE_MAX_NUMBER is 100.
    private static final int MAX_NEGATIVE_CACHE = 30; // Specify the maximum TTL for negative caching. The default value of MAX_NEGATIVE_CACHE is 30. Unit: seconds. 
    private static final int MAX_TTL_CACHE = 1 * 60 * 60; // Specify the maximum TTL for caching. The default value of MAX_TTL_CACHE is 3600. Unit: seconds.

    @Override
    public void onCreate() {
       super.onCreate();
       DNSResolver.Init(this, accountID);    // Set the account ID that is used to access the SDK in the Alibaba Cloud DNS console.
       DNSResolver.setEnableShort(false); // Specify whether to enable the short mode. The default value is false, which indicates that the short mode is not enabled.
       DNSResolver.setEnableIPv6(false); // Specify whether to enable IPv6 access. The default value is false, which indicates that this feature is not enabled.
       DNSResolver.setEnableCache(true); // Specify whether to enable caching. The default value is true, which indicates that this feature is enabled.
       DNSResolver.setEnableSpeedTest(false); // Specify whether to enable connection speed testing of IP addresses. The default value is false, which indicates that this feature is disabled.
       DNSResolver.setMaxTtlCache(MAX_TTL_CACHE); // Specify the maximum TTL for caching. The default value is 3600. Unit: seconds.
       DNSResolver.setSpeedPort(DNSResolver.PORT_80); // Specify the port number for IP socket detection. The default port number is 80.
       DNSResolver.setMaxNegativeCache(MAX_NEGATIVE_CACHE); // Specify the maximum TTL for negative caching. The default value is 30. Unit: seconds.
       DNSResolver.setSchemaType(DNSResolver.HTTP); // Specify whether the access protocol is HTTP or HTTPS.
       DNSResolver.getInstance().setMaxCacheSize(CACHE_MAX_NUMBER); // Specify the maximum number of domain name resolution results that can be cached. The default value is 100.
       DNSResolver.getInstance().preLoadDomains(DNSResolver.QTYPE_IPV4,new String[]{TAOBAO_URL, M_TAOBAO_URL, ALIYUN_URL,BAIDU_URL});
    }
}

When you access Alibaba Cloud Public DNS SDK, we recommend that you integrate the SDK into the Application class of your Android app.

Note

DNSResolver is the core class of Alibaba Cloud Public DNS SDK. DNSResolver encapsulates the JSON API for DoH provided by Alibaba Cloud Public DNS to resolve the destination domain name to the related IP address.

When you use the SDK for an Android project, make sure that you have configured the following access permissions:

<!--Permissions that you need to configure-->
   <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"/>
   <uses-permission android:name="android.permission.WAKE_LOCK"/>
   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Usage notes

1. If a mobile phone of Android 9.0 sends an HTTP request, the error message "cleartext HTTP traffic no permitted" is reported.

  • Cause: By default, plaintext network access is disabled on Android mobile phones from Android 9.0 (API level 28 for Android SDK Platform).

  • Solution

Add the following information to <application> in the AndroidManifest.xml file of your app:

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

2. For Android 9.0, the error message "Didn't find class BasicHttpParams" is reported.

  • Cause: The Apache HTTP client is phased out.

Google no longer supports Apache HTTP clients from Android 6.0. From Android 9.0, org.apache.http.legacy is removed from bootclasspath.

This modification has no impact on most apps whose taskVersion is earlier than Android 9.0. However, if the Apache HTTP interface is used or the referenced lib package uses this interface when you use an app whose taskVersion is later than Android 9.0, the error message "Didn't find class BasicHttpParams" is reported.

  • Solution

Add the following information to <application> in the AndroidManifest.xml file of your app:

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

3. You can use SDK 2.0 or later to enable authentication to prevent user identities from being stolen by unauthorized third parties.

You can enable authentication only after you configure the following parameters. To enable authentication, create an AccessKey ID and AccessKey secret in the DNS console by following the instructions provided in Service authentication and add the following configurations to the AndroidManifest.xml file of your app:

   <meta-data
            android:name="com.alibaba.pdns.ACCESS_KEY_ID"
            android:value="Replace the value with the AccessKey ID that is generated when you register your app in the Alibaba Cloud Management Console"./>

   <meta-data
            android:name="com.alibaba.pdns.ACCESS_KEY_SECRET"
            android:value="Replace the value with the AccessKey secret that is generated when you register your app in the Alibaba Cloud Management Console"./>

4. To more effectively use this SDK, we recommend that you set the JDK version to 1.8 when you compile the app.

2.4.1 Service initialization

Alibaba Cloud Public DNS SDK uses the DNSResolver class to encapsulate service requests and local caches of Alibaba Cloud Public DNS. You can use DNSResolver.Init(this,accountID) to initialize services to access Alibaba Cloud Public DNS.accountID is the unique ID that the server automatically generates when you register your Alibaba Cloud account in the Alibaba Cloud Public DNS console.

2.4.2 Configure pre-resolved domain names

When you initialize your Android app, you can register domain names that you may use with Alibaba Cloud Public DNS SDK so that the SDK can resolve the domain names in advance. This reduces the delay of requests during subsequent resolution. The following code shows how to configure pre-resolved domain names:

DNSResolver.getInstance().preLoadDomains(DNSResolver.QTYPE_IPV4,new String[]{TAOBAO_URL, M_TAOBAO_URL, ALIYUN_URL,BAIDU_URL})

DNSResolver.QTYPE_IPV4  Obtain the IPv4 record type that corresponds to the pre-resolved domain names.
DNSResolver.QTYPE_IPV6  Obtain the IPv6 record type that corresponds to the pre-resolved domain names.
Notice

When you configure a pre-resolved interface, an asynchronous network request is triggered in real time. You must make sure that the code logic has the necessary initialization settings when the pre-resolved interface is called.

2.4.3 Specify whether to use the IPv6 addresses of servers

Alibaba Cloud Public DNS supports IPv4 and IPv6 dual-stack access. You can set DNSResolver.setEnableIPv6(boolean enable) to determine whether to use IPv4 or IPv6 addresses. If you set DNSResolver.setEnableIPv6(boolean enable) to true, IPv6 addresses are used to access the interface on the server. If you set DNSResolver.setEnableIPv6(boolean enable) to false, IPv4 addresses are used to access the interface on the server. If you do not set DNSResolver.setEnableIPv6(boolean enable), IPv4 addresses are used. If IPv6 addresses are used for access, the system automatically switches to IPv4 addresses when Alibaba Cloud Public DNS is inaccessible. In this case, a maximum of three access retries are allowed.

2.4.4 Specify whether to enable the short mode

Data returned by the JSON API for DoH of Alibaba Cloud Public DNS can be in the JSON format or a simple array of IP addresses. You can set DNSResolver.setEnableShort (boolean enable) to enable or disable the short mode. If you do not set DNSResolver.setEnableShort (boolean enable), the short mode is disabled by default.

The following code shows the setting of the short mode:

DNSResolver.setEnableShort (true); // The default value is false. If you do not set this parameter, the default value is used.
Notice

In short mode, the SDK calls Alibaba Cloud Public DNS to return a simple array of IP addresses. This reduces the amount of data returned and is suitable for scenarios in which heavy network traffic is not allowed.

2.4.5 Specify the maximum cache size

DNSResolver.getInstance().setMaxCacheSize(CACHE_MAX_NUMBER); // Specify the maximum number of domain name resolution results that can be cached. The default value is 100.

You can set the maximum cache size as required.

2.4.6 Specify the maximum TTL for caching

DNSResolver.setMaxTtlCache(MAX_TTL_CACHE);// Specify the maximum TTL for caching. The default value is 3600. Unit: seconds.

2.4.7 Specify the server access protocol

DNSResolver.setSchemaType(DNSResolver.HTTP); // Specify the server access protocol. The default access protocol is HTTP.

DNSResolver.HTTP indicates that HTTP is used to access the interface on the server.

DNSResolver.HTTPS indicates that HTTPS is used to access the interface on the server.

2.4.8 Specify whether to enable caching

DNSResolver.setEnableCache(true); // Specify whether to enable the caching feature. This feature is enabled by default.

If setEnableCache is set to true, caching is enabled. If setEnableCache is set to false, caching is disabled.

2.4.9 Specify whether connection speed testing of IP addresses is enabled

DNSResolver.setEnableSpeedTest(false); // Specify whether to enable connection speed testing of IP addresses. This feature is disabled by default.

If setEnableSpeedTest is set to true, this feature is enabled. If setEnableSpeedTest is set to false, this feature is disabled.

2.4.10 Specify the port number in the socket for connection speed testing of IP addresses

DNSResolver.setSpeedPort(DNSResolver.PORT_80)

You can specify the port number in the socket for connection speed testing of IP addresses. The default port number is 80.

2.4.11 Enable domain name caching based on ISP networks

DNSResolver.setIspEnable(true);// Specify whether to enable domain name caching based on Internet service provider (ISP) networks.

If setIspEnable is set to true, the cached domain name resolution results are stored separately based on the network environments. If setIspEnable is set to false, the same cached domain name resolution results are used under different networks.

2.4.12 Specify the maximum TTL for negative caching

DNSResolver.setMaxNegativeCache(MAX_NEGATIVE_CACHE);// Specify the maximum TTL for negative caching. The default value is 30. Unit: seconds.

You can set the maximum TTL for negative caching based on your business requirements.

3.Service API operations

/**
  * Obtain the DomainInfo object array in the IPv4 records that correspond to a specific URL.
  *
  * @param url Example: http://www.taobao.com
  * @return The DomainInfo object array in the IPv4 records that correspond to the URL is returned.
  */
  public DomainInfo[] getIPsV4DInfoByUrl(String url) 

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

/**
   * Obtain the DomainInfo object array in the IPv6 records that correspond to a specific URL.
   * 
   * @param url Example: http://m.taobao.com
   * @return The DomainInfo object array in the IPv6 records that correspond to the URL is returned.
   */
    public DomainInfo[] getIPsV6DInfoByUrl(String url) 
   

 /**
    * Obtain a DomainInfo object in the IPv4 records that correspond to a specific URL.
    *
    * @param url Example: http://m.taobao.com
    * @return A DomainInfo object in the IPv4 records that correspond to the URL is returned.
    */
    public DomainInfo getIPV4DInfoByUrl(String url) 


 /**
    * Obtain a DomainInfo object in the IPv6 records that correspond to a specific URL.
    *
    * @param url Example: http://www.taobao.com
    * @return A DomainInfo object in the IPv6 records that correspond to the URL is returned.
    */
  public DomainInfo getIPV6DInfoByUrl(String url) 

Note: The returned DomainInfo object encapsulates the following attributes:

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

   /**
    * The available URL in which the hostname field is replaced by an IP address.
    */
public String url = null;

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

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

   /**
    * The start time of the request.
    */
   public String startTime = null;

   /**
    * The end time of the request. If the request times out, the value is null.
    */
   public String stopTime = null; 

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

  /**
    * Obtain the array of IPv4 records that correspond to a specific hostname.
    * @param hostName Example: www.taobao.com
    * @return The array of IPv4 addresses that correspond to the hostname is returned.
    */
  public  String[] getIPsV4ByHost(String hostName) 

/**
    * Obtain the array of IPv6 records that correspond to a specific hostname.
    * @param hostName Example: www.taobao.com
    * @return The array of IPv6 addresses that correspond to the hostname is returned.
    */
  public String[] getIPsV6ByHost(String hostName) 

/**
    * Obtain an IPv4 record that corresponds to a specific hostname.
    * @param hostName Example: 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) 

/**
    * Obtain an IPv6 record that corresponds to a specific hostname.
    * @param hostName Example: www.taobao.com
    * @return A random IPv6 address in the set of IPv6 addresses that correspond to the hostname is returned. If connection speed testing of IP addresses is enabled, the optimal IPv6 address is returned.
    */
 public String getIPV6ByHost(String hostName) 

   /**
     * Obtain the IP address array of the IPv4 record type from the cache after the domain name is resolved.
     * If no IP address array exists in the cache, null is returned. Then, an asynchronous query is triggered and the query results are stored in the cache.
     *
     * @param host The hostname that you query, such as www.taobao.com.
     * @return The IP address array of the IPv4 record type from the cache after the hostname is resolved.
     */
    private String[] getIpv4ByHostFromCache(String host)

    /**
     * Obtain the IP address array of the IPv6 record type from the cache after the domain name is resolved.
     * If no IP address array exists in the cache, null is returned. Then, an asynchronous query is triggered and the query results are stored in the cache.
     *
     * @param host The hostname that you query, such as (www.taobao.com).
     * @return The IP address array of the IPv6 record type from the cache after the hostname is resolved.
     */
    private String[] getIpv6ByHostFromCache(String host)      

   /**
     * Preloading logic.
     *
     * @param qType The type of IP addresses (IPv4 or IPv6) to be uploaded.
     * @param domains The resolved domain name to be preloaded.
     */
    public void preLoadDomains(String qType, final String[] domains)

   /**
     * Obtain the statistics on successful and failed queries of Alibaba Cloud Public DNS.
     *
     * @return The JSON array string of the resolution statistics on all domain names.
     */
    public String getRequestReportInfo()
    

4.Example of SDK API operations

URl: the received access address, such as http://www.taobao.com.

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

4.1 Obtain IPv4 addresses

String IPV4 = DNSResolver.getInstance().getIPV4ByHost(hostname); // Obtain the resolution results of IPv4 addresses.

4.2 Obtain IPv6 addresses

String IPV6 =  DNSResolver.getInstance().getIPV6ByHost(hostname) // Obtain the resolution results of IPv6 addresses.

4.3 Obtain the DomainInfo object that corresponds to a specific URL

DomainInfo dinfo = DNSResolver.getInstance().getIPV4DInfoByUrl(url); // Obtain the URL in which the domain name is replaced by an IP address.

4.4 Obtain the statistics on successful and failed queries of Alibaba Cloud Public DNS

String reportInfo = DNSResolver.getInstance().getRequestReportInfo();// Obtain the statistics on successful and failed queries.

The following figure shows the meanings of the fields in the JSON array string of the resolution statistics on all domain names.

Snapshot
Notice

The resolution statistics of Alibaba Cloud Public DNS are collected based on network environments, domain names, and query types.

5.Example:

public class MainActivity extends AppCompatActivity {
   private Button button;
   private TextView tvInfo;
   private TextView tvResult;
   private String hostUrl = "http://www.taobao.com";
   private String hostName = "www.taobao.com";
   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 in Alibaba Cloud Public DNS SDK to obtain the IP address resolved from the specified domain name.
               String ipv4 = DNSResolver.getInstance().getIPV4ByHost(hostName);
               tvInfo.setText("IP address resolved from the domain name: "+ ipv4);
          // Call the getIPV4DInfoByUr operation in Alibaba Cloud Public SDK to obtain the URL in the domainInfo object after the specified domain name is resolved. The URL is the one in which the hostname field is replaced by an 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 a network request.
               String requestUrl = dinfo.url;
               HttpURLConnection conn = null;
               try {
                   URL url = new URL(requestUrl);
                   conn = (HttpURLConnection) url.openConnection();
                   // When an IP address is used for access, you must set the hostname field in the HTTP request header to the resolved domain name.
                   conn.setRequestProperty("Host", url.getHost());// Set the hostname 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 accountID = "10001"; // You can replace 10001 with your account ID.
   private static final String TAOBAO_URL = "www.taobao.com";
   private static final String M_TAOBAO_URL = "m.taobao.com";
   private static final String ALIYUN_URL = "aliyun.com";
   private static final String BAIDU_URL = "www.baidu.com";
   private static final int CACHE_MAX_NUMBER = 100; // Specify the maximum number of domain name resolution results that can be cached. The default value is 100.
   private static final int MAX_NEGATIVE_CACHE = 30; // Specify the maximum TTL for negative caching. The default value of MAX_NEGATIVE_CACHE is 30. Unit: seconds.
   private static final int MAX_TTL_CACHE = 1 * 60 * 60; // Specify the maximum TTL for caching. The default value of MAX_TTL_CACHE is 3600. Unit: seconds.

   @Override
   public void onCreate() {
       super.onCreate();
       DNSResolver.Init(this, accountID);    // Set the account ID that is used to access the SDK in the Alibaba Cloud DNS console.
        DNSResolver.setEnableShort(false); // Specify whether to enable the short mode.
        DNSResolver.setEnableIPv6(false); // Specify whether to enable IPv6 access.
        DNSResolver.setEnableCache(true); // Specify whether to enable the caching feature.
        DNSResolver.setEnableSpeedTest(false); // Specify whether to enable connection speed testing of IP addresses.
        DNSResolver.setIspEnable(true);// Specify whether to enable domain name caching based on ISP networks.    
        DNSResolver.setMaxTtlCache(MAX_TTL_CACHE); // Specify the maximum TTL for caching. The default value is 3600. Unit: seconds.
        DNSResolver.setMaxNegativeCache(MAX_NEGATIVE_CACHE);// Specify the maximum TTL for negative caching. The default value is 30. Unit: seconds.
        DNSResolver.setSchemaType(DNSResolver.HTTP); // Specify whether the server access protocol is HTTP or HTTPS.
        DNSResolver.setSpeedPort(DNSResolver.PORT_80); // Specify the port number for IP socket detection. The default port number is 80.
        DNSResolver.getInstance().setMaxCacheSize(CACHE_MAX_NUMBER); // Specify the maximum number of resolution results of domain names that can be cached. The default value is 100.
        DNSResolver.getInstance().preLoadDomains(DNSResolver.QTYPE_IPV4, new String[]{TAOBAO_URL, M_TAOBAO_URL, ALIYUN_URL});
   }
}

Usage notes

  1. After you use Alibaba Cloud Public DNS to resolve a domain name to an IP address, you can use the IP address to send business requests. You must specify the hostname field in the HTTP request header as the domain name that has been resolved.

  2. The demo program makes it easy to learn how to use the Alibaba Cloud public DNS SDK.

    You can download the demo program for reference.

For more information, download the demo project.