Introduction
This section describes the steps for integrating the HTTPDNS Android SDK.
Android Studio projects that manage dependencies with Gradle are recommended.
The SDK supports Android 4.0 and later versions.
The SDK is compatible with targetSdkVersion up to Android 14 (34).
The SDK supports arm64-v8a, armeabi-v7a, x86, and x86_64 architectures.
The SDK is open source, allowing you to modify the source code to meet your specific needs. For more information, see httpdns-android-sdk.
Step 1: Add the SDK to your application
Two integration methods are available: Maven dependency and local dependency. Choose the method that best suits your needs.
The Maven dependency method is recommended for its simplicity, reduced error potential, and ease of updates.
1 Maven dependency method
1.1 Configure the Maven repository
For Gradle 7.0 and later, use the dependencyResolutionManagement
configuration method. For earlier versions, use the allprojects
method.
1.1.1 dependencyResolutionManagement method
In your root-level (project-level) Gradle file (<project>/settings.gradle
), include the Maven repository address within the dependencyResolutionManagement
section under repositories
.
dependencyResolutionManagement {
repositories {
maven {
url 'https://maven.aliyun.com/nexus/content/repositories/releases/'
}
}
}
1.1.2 allprojects method
In your root-level (project-level) Gradle file (<project>/build.gradle
), include the Maven repository address within the allprojects
section's repositories
block.
allprojects {
repositories {
maven {
url 'https://maven.aliyun.com/nexus/content/repositories/releases/'
}
}
}
1.2 Add SDK dependencies
In your module-level (application-level) Gradle file (typically located at <project>/<app-module>/build.gradle), include the SDK dependency within the dependencies
section.
dependencies {
implementation 'com.aliyun.ams:alicloud-android-httpdns:${httpdnsVersion}'
}
You can retrieve the httpdnsVersion
from the Android SDK Release Notes or the .
2 Local dependency method
2.1 Download the SDK
You can download HTTPDNS from the EMAS SDK list and copy all the files from the SDK package into your module-level (application-level) <project>/<app-module>/libs
directory.
2.2 Add SDK dependencies
2.2.1 Configure the local SDK directory
In your module-level (application-level) Gradle file (typically located at <project>/<app-module>/build.gradle), include the address of the local SDK file directory.
repositories {
flatDir {
dirs 'libs'
}
}
2.2.2 Add SDK dependencies
In your module-level (application-level) Gradle file (typically <project>/<app-module>/build.gradle), include the SDK dependencies within the dependencies
section.
dependencies {
implementation (name: 'alicloud-android-httpdns-${httpdnsVersion}', ext: 'aar')
implementation (name: 'alicloud-android-logger-${loggerVersion}', ext: 'aar')
implementation (name: 'alicloud-android-crashdefend-${crashDefendVersion}', ext: 'jar')
implementation (name: 'alicloud-android-ipdetector-${ipdetectorVersion}', ext: 'aar')
implementation (name: 'alicloud-android-utdid-${utdidVersion}', ext: 'jar')
}
Ensure the SDK version numbers in the dependencies match those in the downloaded files.
If a class is missing during compilation, include
implementation fileTree(dir: 'libs', include the following: ['*.jar'])
under dependencies.
Step 2: Configure and use the SDK
1 Configure HTTPDNS
// Initialize the configuration. You can call it without handling the return value.
InitConfig config = InitConfig.Builder()
// Specify the initial region.
.setRegion(currentRegion)
// Specify whether to enable HTTPS. By default, HTTP is enabled.
.setEnableHttps(enableHttps)
// Specify the timeout period for service requests in milliseconds. The default is 2 seconds, and the maximum is 5 seconds.
.setTimeout(2 * 1000)
// Specify whether to enable local caching. By default, local caching is disabled.
.setEnableCacheIp(true)
// Specify whether expired IP addresses can be returned. By default, expired IP addresses can be returned.
.setEnableExpiredIp(true)
// Specify a list of IPv4 addresses that you want to probe to return the optimal IPv4 address.
.setIPRankingList(ipRankingItemJson.toIPRankingList())
// Specify a custom time-to-live (TTL) for the cache.
.configCacheTtlChanger(ttlChanger)
// Configure the domain name list of fixed IP addresses, which can optimize the internal logic of the SDK and reduce the resolution frequency.
.configHostWithFixedIp(hostListWithFixedIp)
// Specify the policy for domain names that do not use HTTPDNS resolution.
.setNotUseHttpDnsFilter(notUseHttpDnsFilter)
// Specify the account ID.
.build()
HttpDns.init(accountID, config);
// Initialize the configuration. You can call it without handling the return value.
new InitConfig.Builder()
// Specify the initial region.
.setRegion(currentRegion)
// Specify whether to enable HTTPS. By default, HTTP is enabled.
.setEnableHttps(enableHttps)
// Specify the timeout period for service requests in milliseconds. The default is 2 seconds, and the maximum is 5 seconds.
.setTimeout(2 * 1000)
// Specify whether to enable local caching. By default, local caching is disabled.
.setEnableCacheIp(true)
// Specify whether expired IP addresses can be returned. By default, expired IP addresses can be returned.
.setEnableExpiredIp(true)
// Specify a list of IPv4 addresses that you want to probe to return the optimal IPv4 address.
.setIPRankingList(list)
// Specify a custom time-to-live (TTL) for the cache.
.configCacheTtlChanger(ttlChanger)
// Configure the domain name list of fixed IP addresses, which can optimize the internal logic of the SDK and reduce the resolution frequency.
.configHostWithFixedIp(hostListWithFixedIp)
// Specify the policy for domain names that do not use HTTPDNS resolution.
.setNotUseHttpDnsFilter(notUseHttpDnsFilter)
// Specify the account ID.
.buildFor(accountID);
-
If
setEnableHttps
is not configured totrue
during initialization, you must include the settingandroid:usesCleartextTraffic="true"
within theapplication
element of theAndroidManifest.xml
file at the application level. Failing to do so will result in unsuccessful domain name resolution requests on systems running version targetSdkVersion 27 or higher.
For details on specific configuration interfaces, see basic configuration interfaces and advanced configuration interfaces.
2 Obtain a service instance
The HTTPDNS SDK for Android offers domain name resolution through global service instances. To acquire a service instance, you can use any of the methods listed below.
2.1 Standard method
val httpdns = HttpDns.getService(applicationContext, accountID)
HttpDnsService httpdns = HttpDns.getService(applicationContext, accountID);
2.2 Authentication methods
val httpdns = HttpDns.getService(applicationContext, accountID, secretKey)
HttpDnsService httpdns = HttpDns.getService(applicationContext, accountID, secretKey);
-
Starting with HTTPDNS SDK V1.1.3, authentication is supported. It is necessary to deactivate non-authenticated interfaces in the HTTPDNS console with caution. For more information, see or implement authenticated access.
-
The authentication's default validity period is 10 minutes.
-
To prevent the potential leakage of accountID/secretKey parameters or data during app operations in logs, we recommend disabling HTTPDNS log printing in the production version. Refer to disable HTTPDNS log printing for guidance.
-
As users utilize the same SDK, ensure that the accountID or secretKey parameter is specified in the code during access, as these parameters are crucial for metering and billing. To safeguard against information leakage through malicious decompiling, we recommend enabling obfuscation and hardening the application before deployment.
1 Configure HTTPDNS
HTTPDNS offers a variety of domain name resolution techniques, such as pre-resolution, synchronous resolution, asynchronous resolution, and synchronous non-blocking resolution. An example of the synchronous resolution interface is provided below.
val httpDnsResult = dnsService?.getHttpDnsResultForHostSync("www.aliyun.com", RequestIpType.auto)
HTTPDNSResult httpDnsResult = httpdns.getHttpDnsResultForHostSync("www.aliyun.com", RequestIpType.auto);
The API (getHttpDnsResultForHostSync) initially checks the cache. If it finds an active resolution result, it immediately returns the result from the SDK's local cache. If no active result is found, the calling thread is blocked while domain name resolution is carried out on a worker thread. The resolution result is returned upon completion, or an empty value is returned if the operation times out.
To avoid stuttering that may occur when this API is improperly used on the main thread, it includes a safeguard. If the API is called from the main thread, it automatically switches to the logic of the getHttpDnsResultForHostSyncNonBlocking API.
Choose the domain name resolution API that best fits your specific usage scenario. For more information, see domain name resolution APIs and custom resolution APIs.
4 Use domain name resolution results
Once the previous step has been successfully completed, you can retrieve the domain name resolution result. For more information about the data structure, see HTTPDNSResult or .
The example below illustrates the resolution process using the okhttp network library. Here is the sample code:
object : Dns {
@Throws(UnknownHostException::class)
override fun lookup(host: String): List<InetAddress> {
val httpdnsResult: HTTPDNSResult = HttpDns.getService(context)
.getHttpDnsResultForHostSync(host, RequestIpType.auto)
val inetAddresses: MutableList<InetAddress> = ArrayList()
var address: InetAddress
try {
if (httpdnsResult.ips != null) {
//Process IPv4 addresses
for (ipv4 in httpdnsResult.ips) {
address = InetAddress.getByName(ipv4)
inetAddresses.add(address)
}
}
if (httpdnsResult.ipv6s != null) {
//Process IPv6 addresses
for (ipv6 in httpdnsResult.ipv6s) {
address = InetAddress.getByName(ipv6)
inetAddresses.add(address)
}
}
} catch (e: UnknownHostException) {
}
return if (!inetAddresses.isEmpty()) {
inetAddresses
} else Dns.SYSTEM.lookup(host)
}
}
new Dns() {
@Override
public List<InetAddress> lookup(String host) throws UnknownHostException {
HTTPDNSResult httpdnsResult = HttpDns.getService(context, accountID).getHttpDnsResultForHostSync(host, RequestIpType.auto);
List<InetAddress> inetAddresses = new ArrayList<>();
InetAddress address;
try {
if (httpdnsResult.getIps() != null) {
//Process IPv4 addresses
for (String ipv4 : httpdnsResult.getIps()) {
address = InetAddress.getByName(ipv4);
inetAddresses.add(address);
}
}
if (httpdnsResult.getIpv6s() != null) {
//Process IPv6 addresses
for (String ipv6 : httpdnsResult.getIpv6s()) {
address = InetAddress.getByName(ipv6);
inetAddresses.add(address);
}
}
} catch (UnknownHostException e) {
}
if (!inetAddresses.isEmpty()) {
return inetAddresses;
}
return Dns.SYSTEM.lookup(host);
}
};
5 Obfuscation configuration
If your project employs code obfuscation, maintain the following configuration for obfuscation.
-keep class com.alibaba.sdk.android.**{*;}
Step 3: Access authentication
1 Enable SDK logs
Enable HTTPDNS SDK logs by following the instructions in whether to allow HTTPDNS to print logs.
2 Analyze logs
# Initiate sync request
D sync request host www.aliyun.com with type both extras : null cacheKey null
# Cache query result
D host www.aliyun.com result in cache is null
# Trigger cloud resolution
I sync start request for www.aliyun.com both
D ip detector type is 3
D ipdetector type is both
D start resolve ip request for www.aliyun.com both
# Resolution timeout duration
D the httpDnsConfig timeout is: 2000
D final timeout is: 2000
D wait for request finish
# Initiate resolution request
D request url http://xx.xx.xx.xx:80/xxxx/sign_d?host=www.aliyun.com&sdk=android_2.4.0&query=4,6&sid=CaZk1vTyI3hy&s=b4a34694b7215b4cd6a10376b3425a8e&t=1715772172
# Resolution successful
D request success {"ipsv6":[],"host":"www.aliyun.com","ips":[],"ttl":60,"origin_ttl":60}
# Update cache
D save host www.aliyun.com for type v4 ttl is 60
D save host www.aliyun.com for type v6 ttl is 60
D sync resolve time is: 224
# Return resolution result
I request host www.aliyun.com for both and return host:www.aliyun.com, ips:[], ipv6s:[], extras:{}, expired:false, fromDB:false after request
Refer to the logs to determine if domain name resolution is successful.
Notes
-
Compilation Failure After SDK Upgrade
If you encounter a compilation failure after upgrading the SDK version, this may be due to changes in the SDK API. For the new interfaces to use as replacements, please refer to the Android SDK API.
-
Ensure to Write Downgrade Code
Downgrade code is necessary for using Local DNS when HTTPDNS does not yield the expected result.
-
Record the IP and SessionId from HTTPDNS
We offer a solution for diagnosing resolution problems. It's important to log the IP and sessionId retrieved from HTTPDNS. For more information, see how to use the session tracing solution to troubleshoot resolution issues.
-
Set the HOST Field in the HTTP Request Header
In the HTTP protocol, the server uses the HOST field in the HTTP request header to determine the domain name of the request.
After implementing HTTPDNS, you may need to replace the HOST field in the HTTP request URL with the IP address from HTTPDNS resolution. If the standard network library assigns your IP address to the HOST field, the server may not process the request correctly.
To address this, specify the HOST field value in the HTTP request. Example:
val originalUrl = "http://www.aliyun.com/" var url = URL(originalUrl) val originalHost = url.host // Obtain IP in a synchronous non-blocking manner val httpdns = HttpDns.getService(applicationContext, accountID) val result: HTTPDNSResult = httpdns.getHttpDnsResultForHostSyncNonBlocking(originalHost, RequestIpType.auto) val conn: HttpURLConnection if (result.ips != null && result.ips.isNotEmpty()) { // Successfully obtain IPv4 through HTTPDNS, perform URL replacement and set HOST header url = URL(originalUrl.replaceFirst(originalHost.toRegex(), result.ips[0])) conn = url.openConnection() as HttpURLConnection // Set the HOST field in the request conn.setRequestProperty("Host", originalHost) } else if (result.ipv6s != null && result.ipv6s.isNotEmpty()) { // Successfully obtain IPv4 through HTTPDNS, perform URL replacement and set HOST header url = URL(originalUrl.replaceFirst(originalHost.toRegex(), result.ipv6s[0])) conn = url.openConnection() as HttpURLConnection // Set the HOST field in the request conn.setRequestProperty("Host", originalHost) } else { conn = url.openConnection() as HttpURLConnection }
String originalUrl = "http://www.aliyun.com/"; URL url = new URL(originalUrl); String originalHost = url.getHost(); // Obtain IP in a synchronous non-blocking manner HttpDnsService httpdns = HttpDns.getService(applicationContext, accountID); HTTPDNSResult result = httpdns.getHttpDnsResultForHostSyncNonBlocking(originalHost, RequestIpType.auto); HttpURLConnection conn; if (result.getIps() != null && result.getIps().length > 0) { // Successfully obtain IPv4 through HTTPDNS, perform URL replacement and set HOST header url = new URL(originalUrl.replaceFirst(originalHost, result.getIps()[0])); conn = (HttpURLConnection) url.openConnection(); // Set the HOST field in the request conn.setRequestProperty("Host", originalHost); } else if (result.getIpv6s() != null && result.getIpv6s().length > 0) { // Successfully obtain IPv4 through HTTPDNS, perform URL replacement and set HOST header url = new URL(originalUrl.replaceFirst(originalHost, result.getIpv6s()[0])); conn = (HttpURLConnection) url.openConnection(); // Set the HOST field in the request conn.setRequestProperty("Host", originalHost); } else { conn = (HttpURLConnection) url.openConnection(); }
-
Cookie Field
Some network libraries automatically manage cookies based on the domain name information in the URL. When using HTTPDNS with IP URL requests, disable the automatic cookie management feature to avoid issues. By default, this feature is disabled.
-
HTTPS/WebView/SNI Scenarios
-
For HTTPS scenarios, see the IP direct connection solution for Android HTTPS (including SNI) business scenarios.
-
For WebView scenarios, see Best Practices for HTTPDNS+WebView on Android.
-
-
Usage in Proxy Scenarios
When using an HTTP proxy, the client initiates requests with an absolute path URL. With HTTPDNS and IP URL access, the proxy may pass the IP information as the real HOST information to the target server, which cannot process such requests.
To solve this, use the proprietary protocol field
X-Online-Host
. For example:Target URL: http://www.example.com/product/oss/ IP address that www.example.com is resolved to by using HTTPDNS: 192.168.XX.XX Proxy: 10.0.XX.XX:XX Your HTTP request header: GET http://192.168.XX.XX/product/oss/ HTTP/1.1 # The HTTP request header initiated by the proxy. The request line contains an absolute path Host: www.example.com # This header is ignored by the proxy gateway. The proxy gateway uses the Host information in the absolute path of the request line as the host of the origin. The IP address of the host is 192.168.XX.XX X-Online-Host: www.example.com # This header is a proprietary header added by the mobile gateway to pass the real Host. The origin needs to be configured to recognize this proprietary header to obtain the real Host information
You can also set the
X-Online-Host
request header field using thesetRequestProperty
method and configure the server to parse this proprietary header field.NoteIn most scenarios, it is recommended to disable HTTPDNS when using a proxy.