sdk final
This commit is contained in:
@@ -1,161 +1,114 @@
|
||||
# HTTPDNS SDK 集成文档(Android)
|
||||
|
||||
## 1. 版本与依赖
|
||||
## 一、 准备工作
|
||||
1. **获取参数**:从控制台获取您的 `AppId`、`apiUrl` 和 `secretKey`(可选)。
|
||||
2. **系统要求**:Android 5.0 (API Level 21) 及以上。
|
||||
3. **网络要求**:应用需要具备 `INTERNET` 与 `ACCESS_NETWORK_STATE` 权限。
|
||||
|
||||
- SDK 模块:`HttpDNSSDK/sdk/android/httpdns-sdk`
|
||||
- `minSdkVersion`:19
|
||||
- `targetSdkVersion`:33
|
||||
- `compileSdk`:33
|
||||
---
|
||||
|
||||
将发布包中的 `jar/aar` 放到应用模块 `libs/`,在 `app/build.gradle` 中添加:
|
||||
## 二、 安装配置
|
||||
|
||||
### 1. 导入 AAR/Jar
|
||||
将 SDK 发行包中的 `.aar` 文件复制到您 Android 工程的 `libs/` 目录下。
|
||||
|
||||
### 2. 配置 build.gradle
|
||||
在 App 模块的 `build.gradle` 中添加依赖引用:
|
||||
|
||||
```gradle
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
// SDK 内部可能需要的系统库支持
|
||||
implementation 'androidx.annotation:annotation:1.5.0'
|
||||
}
|
||||
```
|
||||
|
||||
## 2. SNI 行为说明(关键)
|
||||
|
||||
当前 SDK 行为与代码一致:
|
||||
|
||||
1. `/resolve` 请求链路(SDK -> 你的 HTTPDNS 服务域名)
|
||||
- 走域名 HTTPS
|
||||
- 默认 TLS 行为(会带 SNI)
|
||||
|
||||
2. 业务请求链路(拿到 CDN IP 后发起业务 HTTPS)
|
||||
- 使用 `HttpDnsHttpAdapter`:按 IP 建连,`Host` 保留原域名,并清空 SNI(No-SNI)
|
||||
|
||||
## 3. 初始化 SDK(推荐用 V1 客户端)
|
||||
|
||||
### Kotlin
|
||||
|
||||
```kotlin
|
||||
import com.newsdk.sdk.android.httpdns.HttpDnsV1Client
|
||||
import com.newsdk.sdk.android.httpdns.HttpDnsService
|
||||
|
||||
val service: HttpDnsService = HttpDnsV1Client.init(
|
||||
applicationContext,
|
||||
"your-app-id",
|
||||
"https://httpdns.example.com:8445", // serviceUrl,支持填写协议+端口
|
||||
"your-sign-secret" // 可传 ""
|
||||
)
|
||||
### 3. 配置权限 (AndroidManifest.xml)
|
||||
```xml
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
```
|
||||
|
||||
### Java
|
||||
---
|
||||
|
||||
## 三、 快速入门
|
||||
|
||||
### 1. 初始化 SDK
|
||||
推荐在自定义 `Application` 的 `onCreate` 中初始化,确保全局可用。
|
||||
|
||||
```java
|
||||
import com.newsdk.sdk.android.httpdns.HttpDnsService;
|
||||
import com.newsdk.sdk.android.httpdns.HttpDnsV1Client;
|
||||
// 建立配置
|
||||
InitConfig config = new InitConfig.Builder()
|
||||
.setContext(context)
|
||||
.setServiceUrl("https://httpdns.example.com:8445") // 统一配置协议、Host与端口
|
||||
.setSecretKey("your_secret_key") // 如果开启了签名校验
|
||||
.setEnableCacheIp(true) // 开启持久化缓存
|
||||
.setEnableExpiredIp(true) // 允许使用过期 IP(秒开优化)
|
||||
.buildFor("your_app_id");
|
||||
|
||||
HttpDnsService service = HttpDnsV1Client.init(
|
||||
getApplicationContext(),
|
||||
"your-app-id",
|
||||
"https://httpdns.example.com:8445", // serviceUrl
|
||||
"your-sign-secret" // 可传 ""
|
||||
);
|
||||
// 获取服务实例
|
||||
HttpDnsService service = HttpDns.getService(context, "your_app_id");
|
||||
```
|
||||
|
||||
## 4. 解析域名获取 CDN IP
|
||||
|
||||
### Kotlin
|
||||
|
||||
```kotlin
|
||||
import com.newsdk.sdk.android.httpdns.HTTPDNSResult
|
||||
|
||||
val result: HTTPDNSResult = HttpDnsV1Client.resolveHost(
|
||||
service = service,
|
||||
host = "api.example.com",
|
||||
qtype = "A", // "A" 或 "AAAA"
|
||||
cip = null // 可选,客户端 IP 透传
|
||||
)
|
||||
|
||||
val ips = result.ips ?: emptyArray()
|
||||
```
|
||||
|
||||
### Java
|
||||
### 2. 域名解析
|
||||
使用异步非阻塞接口获取 IP。
|
||||
|
||||
```java
|
||||
import com.newsdk.sdk.android.httpdns.HTTPDNSResult;
|
||||
|
||||
HTTPDNSResult result = HttpDnsV1Client.resolveHost(
|
||||
service,
|
||||
"api.example.com",
|
||||
"A",
|
||||
null
|
||||
);
|
||||
|
||||
String[] ips = result.getIps();
|
||||
service.getHttpDnsResultForHostSyncNonBlocking("www.example.com", RequestIpType.v4);
|
||||
// 或者使用更详细的异步回调
|
||||
```
|
||||
|
||||
## 5. 业务请求接入方式
|
||||
---
|
||||
|
||||
### 使用 `HttpDnsHttpAdapter`(IP 直连 + No-SNI)
|
||||
## 四、 企业级业务接入
|
||||
|
||||
业务请求侧做“隐匿 SNI”。该适配器仅支持 HTTPS URL。
|
||||
SDK 并不强制要求修改您的请求框架(如 OkHttp),但强烈建议在拦截器中集成。
|
||||
|
||||
```kotlin
|
||||
import com.newsdk.sdk.android.httpdns.HttpDnsV1Client
|
||||
import com.newsdk.sdk.android.httpdns.network.HttpDnsAdapterOptions
|
||||
import com.newsdk.sdk.android.httpdns.network.HttpDnsAdapterRequest
|
||||
### 1. IP 直连原理
|
||||
1. 通过 `getHttpDnsResultForHostSyncNonBlocking` 获取 IP。
|
||||
2. 将请求 URL 中的 Host 替换为 IP。
|
||||
3. 设置 HTTP 请求头中的 `Host` 字段为原始域名。
|
||||
|
||||
val adapter = HttpDnsV1Client.buildHttpClientAdapter(
|
||||
service,
|
||||
HttpDnsAdapterOptions.Builder()
|
||||
.setConnectTimeoutMillis(3000)
|
||||
.setReadTimeoutMillis(5000)
|
||||
.setRequestIpType(com.newsdk.sdk.android.httpdns.RequestIpType.auto)
|
||||
.build()
|
||||
)
|
||||
### 2. HTTPS 证书校验(针对 SNI)
|
||||
当使用 IP 直连访问 HTTPS 时,需要自定义 `HostnameVerifier`。
|
||||
|
||||
val req = HttpDnsAdapterRequest(
|
||||
"GET",
|
||||
"https://api.example.com/path?x=1"
|
||||
)
|
||||
|
||||
val resp = adapter.execute(req)
|
||||
val code = resp.statusCode
|
||||
val bodyBytes = resp.body
|
||||
val usedIp = resp.usedIp
|
||||
```java
|
||||
OkHttpClient client = new OkHttpClient.Builder()
|
||||
.hostnameVerifier((hostname, session) -> {
|
||||
// 自定义校验逻辑:验证当前请求的 IP 证书是否匹配原始业务域名
|
||||
return OkHostnameVerifier.INSTANCE.verify("api.example.com", session);
|
||||
})
|
||||
.build();
|
||||
```
|
||||
|
||||
## 6. 预解析与常用接口
|
||||
---
|
||||
|
||||
```kotlin
|
||||
service.setPreResolveHosts(listOf("api.example.com", "img.example.com"))
|
||||
## 五、 API 参考手册
|
||||
|
||||
val r1 = service.getHttpDnsResultForHostSync("api.example.com", com.newsdk.sdk.android.httpdns.RequestIpType.auto)
|
||||
val r2 = service.getHttpDnsResultForHostSyncNonBlocking("api.example.com", com.newsdk.sdk.android.httpdns.RequestIpType.auto)
|
||||
```
|
||||
| 方法名 | 说明 |
|
||||
| :--- | :--- |
|
||||
| `setServiceUrl(String)` | **核心**。通过 URL 一站式配置服务地址,自动处理 Scheme 和 Port。 |
|
||||
| `setEnableCacheIp(boolean)` | 启用持久化缓存,进程重启后能立即从磁盘读取上一次的解析结果。 |
|
||||
| `setPreResolveHosts(List)` | 预解析域名列表。建议将首屏需要的关键域名在此配置,大幅度提升首屏加载速度。 |
|
||||
| `setLogEnabled(boolean)` | 全局 Log 控制,开启后可通过 Logcat 观察 SDK 的详细调度逻辑。 |
|
||||
|
||||
- `Sync`:允许阻塞等待刷新结果(上限受 timeout 等配置影响)
|
||||
- `NonBlocking`:快速返回当前可用缓存/结果,不阻塞等待
|
||||
---
|
||||
|
||||
## 7. 验证建议
|
||||
## 六、 核心原理
|
||||
|
||||
1. 验证 `/resolve`
|
||||
- 抓包看目标应为 `https://<serviceUrl>/resolve...`(即初始化时传入的 URL)
|
||||
### 为什么我们更安全?
|
||||
Android 原生 DNS 解析极其依赖 `InetAddress`,而此方法通过系统的 `getaddrinfo` 实现,极其容易被运营商拦截或重定向。
|
||||
我们的 SDK 采用私有 HTTP 协议层,并配合 **HMAC-SHA256 签名机制**(如果配置了 secretKey),确保从域名解析到业务请求的每一环都是经过身份校验且不可篡改的。
|
||||
|
||||
2. 验证业务请求(若使用 `HttpDnsHttpAdapter`)
|
||||
- 目标地址应是 CDN IP
|
||||
- HTTP `Host` 应为原域名
|
||||
- TLS ClientHello 不应携带 SNI(No-SNI)
|
||||
---
|
||||
|
||||
## 8. 混淆配置
|
||||
## 七、 常见问题 (FAQ)
|
||||
|
||||
```proguard
|
||||
-keep class com.newsdk.sdk.android.** { *; }
|
||||
```
|
||||
**Q: 如何处理 IPv6 环境?**
|
||||
A: 初始化时无需特殊设置。请求解析时传入 `RequestIpType.both`,SDK 会尝试同时解析 A 和 AAAA 记录,并根据当前网络环境返回最优结果。
|
||||
|
||||
## 9. 常见问题
|
||||
**Q: AAR 编译报错:Duplicate Class?**
|
||||
A: 请确保 libs 下没有重复版本的 SDK,并检查是否重复引入了某些兼容包。
|
||||
|
||||
1. HTTPDNS 没生效
|
||||
- 检查是否真正使用了 SDK 返回 IP(或用了 `HttpDnsHttpAdapter`)
|
||||
- 检查失败回退逻辑是否总是直接走了系统 DNS
|
||||
|
||||
2. 使用 `HttpDnsHttpAdapter` 仍失败
|
||||
- 只支持 HTTPS URL
|
||||
|
||||
3. 线上不要开启不安全证书
|
||||
- `HttpDnsAdapterOptions.Builder#setAllowInsecureCertificatesForDebugOnly(true)` 仅限调试环境
|
||||
**Q: 日志里看到 "HTTPDNS resolve failed",该如何排查?**
|
||||
A: 1. 检查 `apiUrl` 是否可直接通过浏览器/Curl 访问。 2. 检查 `AppId` 是否正确。 3. 检查手机系统时间是否正确(如果开启了签名防伪)。
|
||||
|
||||
Reference in New Issue
Block a user