Android稀奇古怪DNS异常之DNS数据获取

0 阅读2分钟

image.png

接着处理稀奇古怪问题之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数据查询,后续有处理的相关进展会伴随更新