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

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

概述

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

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

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

实践方案

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

重要

实现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[] IPArray = mDNSResolver.getIpv4ByHostFromCache(hostname,true);
        if (IPArray == null || IPArray.length == 0){
            IPArray = mDNSResolver.getIPsV4ByHost(hostname);
        }
        if (IPArray != null && IPArray.length > 0) {
            List<InetAddress> inetAddresses = new ArrayList<>();
            InetAddress address;
            for (String ip : IPArray) {
                Log.d(TAG, "mDnsCache IP: " +hostname+ ip);
                address = InetAddress.getByName(ip);
                inetAddresses.add(address);
            }
            if (!inetAddresses.isEmpty()) {
                return inetAddresses;
            }
        }
        //如果返回null,走系统DNS服务解析域名
        return okhttp3.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示例工程源码。