本文档介绍了阿里云公共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下也不需要做额外的处理,侵入性极小。
实现DNS接口意味着所有经由当前OkHttpClient实例处理的网络请求都会经过阿里云公共DNS。如果业务中只有少部分域名需要通过阿里云公共DNS进行解析,建议在调用阿里云公共DNS Android SDK域名解析接口之前先进行过滤。
接入阿里云公共DNS Android SDK
自定义DNS接口
OkHttp暴露了一个DNS接口,通过实现该接口,我们可以自定义DNS。完整的OkHttp场景下接入阿里云公共DNS Android SDK最佳实践完整代码请参考Demo示例工程源码。
开发者可以在自己的项目目录里新建一个类实现DNS接口。
在自定义的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);
}
});
}
当前OKHttp接入阿里云公共DNS Android SDK最佳实践文档只针对结合OKHttp场景下使用。
如何使用阿里云公共DNS Android SDK的域名解析服务和接入阿里云公共DNS Android SDK的自身问题,请先查看Android SDK开发指南。
开发者在OkHttp开发者在框架场景下接入阿里云公共DNS Android SDK最佳实践完整代码请参考Demo示例工程源码。