Android端OkHttp框架场景下接入阿里云公共DNS Android SDK最佳实践方案

本文档介绍了阿里云公共DNS Android SDK在OkHttp框架场景下的接入方式。

概述

OkHttp是一个处理网络请求的开源项目,是Android端最火热的轻量级框架,由移动支付Square公司贡献用于替代HttpURLConnection和Apache HttpClient。随着OkHttp的不断成熟,越来越多的Android开发者使用OkHttp作为网络框架。相比于通用方案,OkHttp+阿里云公共DNS Android SDK有以下两个主要优势:

  • 实现简单,只需通过实现DNS接口即可接入阿里公共DNS域名解析服务。

  • 通用性强,该方案在HTTPS场景下无需做额外的配置。

实践方案

OkHttp默认使用系统DNS服务InetAddress进行域名解析,同时还提供了DNS接口。得益于OkHttp框架的良好设计,开发者在使用OkHttp进行网络访问时,通过实现该接口即可以优雅地使用阿里云公DNS Android SDK,在较复杂场景Https/Https+SNI下也不需要做额外的处理,侵入性极小,示例如下:

mOkHttpClient =new OkHttpClient.Builder()
        .dns(new Dns() {
        @NonNull
        @Override
        public List<InetAddress> lookup(String hostname) {
            Utils.checkNotNull(hostname, "hostname can not be null");
            String ips =dnsResolver.getIPsV4ByHost(url.getHost());
            String[] ipArr = ips.split(";");
            if (0 == ipArr.length) {
                return Collections.emptyList();
            }
           List<InetAddress> inetAddressList = new ArrayList<>(ipArr.length);
           for (String ip : ipArr) {
               if ("0".equals(ip)) {
                   continue;
                }
           }
           try {
                InetAddress inetAddress =InetAddress.getByName(ip);
                inetAddressList.add(inetAddress);
            } catch (UnknownHostException ignored) {
         }
      }
      return inetAddressList;
   }
})
.build();
注意

实现DNS接口意味着所有经由当前OkHttpClient实例处理的网络请求都会经过阿里云公共DNS。如果业务中只有少部分域名需要通过阿里云公共DNS进行解析的话,建议在调用阿里云公共DNS Android SDK域名解析接口之前先进行过滤。

接入阿里云公共DNS Android SDK

  • 自定义DNS接口

OkHttp暴露了一个DNS接口,通过实现该接口,我们可以自定义DNS。完整的OkHttp场景下接入阿里云公共DNS Android SDK最佳实践完整代码请参考Demo示例工程源码。

  1. 开发者可以在自己的项目目录里新建一个类实现DNS接口。

  2. 在自定义的DNS覆写lookup方法里按照Android SDK开发指南提供的API,做相关的域名解析操作。

  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 {
        //调用阿里云公共DNS Android SDK提供API进行域名解析
        String ip = mDNSResolver.getIPV4ByHost(hostname);
        Log.d(TAG, "mDnsCache IP: " + ip);

        if (ip != null) {
            //如果ip不为null,直接使用该ip进行网络请求
            return Arrays.asList(InetAddress.getAllByName(ip));
        }
        //如果返回null,走系统DNS服务解析域名
        return Dns.SYSTEM.lookup(hostname);
    }
}

  • 创建OkHttpClient

public void okhttpDnsRequest(String url, final Handler mHandler) {
        OkHttpClient client = new OkHttpClient.Builder()
                .dns(OkHttpDns.getInstance())
                .build();

        Request request = new Request.Builder()
                .url(url)
                .build();

        Response response = null;
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (!response.isSuccessful()) {
                    throw new IOException("Unexpected code " + response);
                }

                DataInputStream dis = new DataInputStream(response.body().byteStream());
                int len;
                byte[] buff = new byte[4096];
                StringBuilder result = new StringBuilder();
                while ((len = dis.read(buff)) != -1) {
                    result.append(new String(buff, 0, len));
                }

                String resultInfo = result.toString();
                Log.d("OkHttpDns", "Response: " + resultInfo);
             }
        });
    }
注意

  1. 当前OKHttp接入阿里云公共DNS Android SDK最佳实践文档只针对结合OKHttp场景下使用。

  2. 如何使用阿里云公共DNS Android SDK的域名解析服务和接入阿里云公共DNS Android SDK的自身问题,请先查看Android SDK开发指南。

  3. 开发者在OkHttp开发者在框架场景下接入阿里云公共DNS Android SDK最佳实践完整代码请参考Demo示例工程源码。