All Products
Search
Document Center

Alibaba Cloud DNS:Use HTTPDNS Android SDK with Android WebView

Last Updated:Dec 04, 2025

This topic provides best practices for integrating the HTTPDNS SDK for Android in a WebView scenario.

Overview

WebView is a UI control provided by Android that parses and displays web pages written in HTML and JavaScript. Android provides APIs that allow you to intercept network requests in WebView and inject custom logic. You can use these APIs to intercept network requests, retrieve the host from the request URL, and then call the HTTPDNS SDK for Android to resolve the host. The resolved IP address can then be used to create a new URL for network requests. These practices apply to HTTP, HTTPS, and Server Name Indication (SNI) scenarios. The following prerequisites must be met:

  • The device runs on Android API level 21 or later.

  • HTTP redirect requests without the Cookie header

  • GET requests

For complete sample code illustrating the best practices for integrating the HTTPDNS SDK for Android in a WebView scenario, see sample project source code.

Best practices

public void setWebViewClient(WebViewClient client);

WebView provides the setWebViewClient API that lets you set the WebViewClient to receive notifications and requests. You can intercept network requests by calling the shouldInterceptRequest method.

public class WebViewClient{
       // API < 21
       public WebResourceResponse shouldInterceptRequest(WebView view,String url){
             .....
       } 
       // API >= 21
      public WebResourceResponse shouldInterceptRequest(WebView view,WebResourceRequest request) {
            .....
       }
     ......
 }
Important

The shouldInterceptRequest method provided by the Android SDK has different versions for different API levels.

  • The following shouldInterceptRequest method is called when the API level is less than 21:

public WebResourceResponse shouldInterceptRequest(WebView view,String url)

Only the request URL is returned. You cannot obtain the request method, headers, or request body. If you call this method to intercept requests, WebView may fail to load all requested resources. Therefore, we recommend that you do not intercept requests on devices with API levels less than 21:

public WebResourceResponse shouldInterceptRequest(WebView view,String url) {
      return super.shouldInterceptRequest(view, url);
}
  • The following shouldInterceptRequest method is called when the API level is 21 or greater:

public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
     String scheme = request.getUrl().getScheme().trim();
     String method = request.getMethod();
     Map<String, String> headerFields = request.getRequestHeaders();
     // Only requests without a body can be processed correctly.
     if ((scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https"))&& method.equalsIgnoreCase("get")) {
            ......
     } else {
           return super.shouldInterceptRequest(view, reqeust);
     }
}
Important

WebResourceRequest does not provide a method to obtain the request body, so the shouldInterceptRequest method can only intercept GET requests. It cannot be used to intercept POST requests.

Implementation

  • Provide WebResourceResponse callback

WebResourceResponse must be returned when you call the shouldInterceptRequest method:

public WebResourceResponse(String mimeType, String encoding, InputStream data) ;

To create a WebResourceResponse object, you need to provide: MIME type of the request, encoding of the request, and input stream of the request.

The input stream of the request can be obtained by calling URLConnection.getInputStream(), while the MIME type and encoding can be obtained from the ContentType of the request by calling URLConnection.getContentType().

Important

Not all requests return complete contentType information. In this case, use the following strategy.

String contentType = conn.getContentType();
String mime = getMime(contentType);
String charset = getCharset(contentType);

// Requests without the MIME type are not intercepted.
if (TextUtils.isEmpty(mime)) {
        return super.shouldInterceptRequest(view, request);
 } else {
       if (!TextUtils.isEmpty(charset)) {
             // If you can obtain both the MIME type and Accept-Charset header of a request, you can intercept this request.
             return new WebResourceResponse(mime, charset, connection.getInputStream());
       } else {
             // If you cannot obtain the character encoding of a request, you can determine whether to intercept this request based on the requested resource.
             // When a binary resource is requested, character encoding is not required. You can intercept this request.
             if (isBinaryRes(mime)) {
                   Log.e(TAG, "binary resource for " + mime);
                   return new WebResourceResponse(mime, charset, connection.getInputStream());
            }else {
                   // When a non-binary resource is requested, character encoding is required. Unencoded requests are not intercepted.
                  Log.e(TAG, "non binary resource for " + mime);
                 return super.shouldInterceptRequest(view, request);
           }
       }
  }

  • Set the Host header

public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
     ...... 
     URL url = new URL(request.getUrl().toString());
     conn = (HttpURLConnection) url.openConnection();
     // Obtain an IP address by calling an API in the HTTPDNS SDK for Android.
     String ip = null;
     String[] ipv4Array = mDNSResolver.getIpv4ByHostFromCache(url.getHost(),true);
     if (ipv4Array != null && ipv4Array.length > 0) {
        ip = ipv4Array[0];
     }
     if (ip != null) {
           //Log.d(TAG, "get IP: " + ip + " for host: " + url.getHost() + "from pdns resolver success!");
          String newUrl = path.replaceFirst(url.getHost(), ip);
          conn = (HttpURLConnection) new URL(newUrl).openConnection(); 
          for (Map.Entry<String, String> field : headers.entrySet()) {
                // Set the header information of the HTTP request.
               conn.setRequestProperty(field.getKey(), field.getValue( ));
          }
      }
      // conn.setRequestProperty("Host", url.getHost());
    } 
}

Use cases

Redirection

When you intercept a GET request from the server that results in a redirect, check whether the original request contains a Cookie. If the original request header contains a Cookie, do not intercept the request because the Cookie might change after the redirection. If the original request header does not contain a Cookie, a second request must be sent.

int code = conn.getResponseCode();
if (code >= 300 && code < 400) {
      if (the GET request contains the Cookie header) {
             // This request is not intercepted.
            return super.shouldInterceptRequest(view, request);
      }

      // Note that the Location key is case-sensitive. Different capitalization styles indicate different redirection modes. For example, the key may indicate that all subsequent requests are redirected to the specified IP address, or that only the current request is redirected to the specified IP address. The capitalization styles and corresponding redirection modes are determined by the server.
      String location = conn.getHeaderField("Location");
      if (location == null) {
            location = conn.getHeaderField("location");
      }

      if (!(location.startsWith("http://") || location.startsWith("https://"))) {
             // Complete the new URL.
             URL originalUrl = new URL(path);
             location = originalUrl.getProtocol() + "://"+ originalUrl.getHost() + location;
      }
      Log.e(TAG, "code:" + code + "; location:" + location + ";path" + path);
     Initiate the GET request again.
  } else {
        // redirect finish.
        Log.e(TAG, "redirect finish");
        ......
 }

HTTPS certificate verification

If the intercepted request is an HTTPS request, you must verify the certificate:

if (conn instanceof HttpsURLConnection) {
     final HttpsURLConnection httpsURLConnection = (HttpsURLConnection)conn;
     // Verify the certificate for an HTTPS request.
     httpsURLConnection.setHostnameVerifier(new HostnameVerifier() {
         @Override
         public boolean verify(String hostname, SSLSession session) {
             String host = httpsURLConnection.getRequestProperty("Host");
             if (null == host) {
                   host = httpsURLConnection.getURL().getHost();
             }
             return HttpsURLConnection.getDefaultHostnameVerifier().verify(host, session);
       }
   });
}

HTTPS+SNI

If the HTTPS request involves an SNI scenario, you need to customize the SSLSocket. For more information, see IP direct connection solution for HTTPS (including SNI) scenarios on Android.

Important
  1. The best practices in this topic apply only to scenarios where you use WebView to integrate the HTTPDNS SDK for Android.

  2. For information about how to use the HTTPDNS SDK for Android for domain name resolution and how to resolve potential integration issues, see Android SDK developer guide.

  3. For a complete sample project that demonstrates the best practices for integrating the HTTPDNS SDK for Android in a WebView scenario, see the demo project source code.