接着处理稀奇古怪问题之DNS异常导致网络不通!!!!
部分用户访问不通,后台说DNS问题,这不需求就来了.要求Android 搜集DNS数据,方便后台查询.....
需求:获取DNS数据和后台相应数据
思路
- 获取网络配置中的DNS配置
- 获取网络请求时的DNS/HOST/响应的数据
1:获取网络配置的DNS数据
注意:
需要<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 权限
/**
* 获取当前 WiFi 路由器或系统 DNS 服务器列表
* @param context Context
* @return List<String> DNS IP 列表
*/
fun getDnsServers(context: Context): List<String> {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val activeNetwork = connectivityManager.activeNetwork ?: return emptyList()
val linkProperties = connectivityManager.getLinkProperties(activeNetwork) ?: return emptyList()
// 获取 InetAddress 列表并转换为字符串
return linkProperties.dnsServers.map { formatDnsType(it)}
}
fun formatDnsType(addr: InetAddress): String {
val type = when (addr) {
is Inet4Address -> "ipv4--> "
is Inet6Address -> "ipv6--> "
else -> "unknown--> "
}
return "$type:${addr.hostAddress}"
}
2:获取网络请求的响应以及DNS数据
interface DnsCheckCallback {
/** 域名解析结果 */
fun onDnsResolved(hostname: String, ipList: List<String>)
/** HTTP 请求响应 */
fun onHttpResponse(code: Int, body: String)
/** 请求或解析失败 */
fun onFailure(t: Throwable)
}
/**
* 使用系统 DNS 请求指定 URL 并通过回调返回 DNS 和 HTTP 信息
* @param url 请求的完整 URL,例如 https://xxx.xx.com 测试的域名
* @param callback 回调
*/
fun checkDns(
url: String,
callback: DnsCheckCallback
) {
val client = OkHttpClient.Builder()
.dns(object : Dns {
@Throws(UnknownHostException::class)
override fun lookup(hostname: String): List<InetAddress> {
val addresses = Dns.SYSTEM.lookup(hostname)
// 回调 DNS 解析结果
val ipList = addresses.map { hostname+" ---> "+formatDnsType(it) }
callback.onDnsResolved(hostname, ipList)
return addresses
}
})
.build()
val request = Request.Builder()
.url(url)
.get()
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
callback.onFailure(e)
}
override fun onResponse(call: Call, response: Response) {
try {
val body = response.body?.string() ?: ""
callback.onHttpResponse(response.code, body)
} catch (e: Exception) {
callback.onFailure(e)
}
}
})
}
3: 获取工具
import android.content.Context
import android.net.ConnectivityManager
import android.net.wifi.WifiManager
import android.os.Build
import android.util.Log
import okhttp3.*
import java.io.IOException
import java.net.Inet4Address
import java.net.Inet6Address
import java.net.InetAddress
import java.net.UnknownHostException
/**
* @Author: wkq
* @Time: 2026/2/6 12:15
* @Desc: 使用 OkHttp 请求指定 URL 并通过回调返回 DNS 和 HTTP 信息(简化版,只用系统 DNS)
*/
object DnsCheckUtil {
interface DnsCheckCallback {
/** 域名解析结果 */
fun onDnsResolved(hostname: String, ipList: List<String>)
/** HTTP 请求响应 */
fun onHttpResponse(code: Int, body: String)
/** 请求或解析失败 */
fun onFailure(t: Throwable)
}
/**
* 使用系统 DNS 请求指定 URL 并通过回调返回 DNS 和 HTTP 信息
* @param url 请求的完整 URL,例如
* @param callback 回调
*/
fun checkDns(
url: String,
callback: DnsCheckCallback
) {
val client = OkHttpClient.Builder()
.dns(object : Dns {
@Throws(UnknownHostException::class)
override fun lookup(hostname: String): List<InetAddress> {
val addresses = Dns.SYSTEM.lookup(hostname)
// 回调 DNS 解析结果
val ipList = addresses.map { hostname+" ---> "+formatDnsType(it) }
callback.onDnsResolved(hostname, ipList)
return addresses
}
})
.build()
val request = Request.Builder()
.url(url)
.get()
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
callback.onFailure(e)
}
override fun onResponse(call: Call, response: Response) {
try {
val body = response.body?.string() ?: ""
callback.onHttpResponse(response.code, body)
} catch (e: Exception) {
callback.onFailure(e)
}
}
})
}
/**
* 获取当前 WiFi 路由器或系统 DNS 服务器列表
* @param context Context
* @return List<String> DNS IP 列表
*/
fun getDnsServers(context: Context): List<String> {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val activeNetwork = connectivityManager.activeNetwork ?: return emptyList()
val linkProperties = connectivityManager.getLinkProperties(activeNetwork) ?: return emptyList()
// 获取 InetAddress 列表并转换为字符串
return linkProperties.dnsServers.map { formatDnsType(it)}
}
fun formatDnsType(addr: InetAddress): String {
val type = when (addr) {
is Inet4Address -> "ipv4--> "
is Inet6Address -> "ipv6--> "
else -> "unknown--> "
}
return "$type:${addr.hostAddress}"
}
}
总结
DNS污染/VPN/运营商拉黑都会导致域名指向不对,这种问题需要前后端配合处理,暂时只进展到了DNS数据查询,后续有处理的相关进展会伴随更新