你如何获得Android的当前DNS服务器?

我试图获取我的应用程序中当前使用的DNS服务器的地址,或者通过Wifi或移动连接。 DhcpInfo对象应该提供这个,但我怎样才能得到一个有效的DhcpInfo对象?

Solutions Collecting From Web of "你如何获得Android的当前DNS服务器?"

调用getRuntime().exec可以挂起你的应用程序。

android.net.NetworkUtils.runDhcp()会导致不必要的networking请求。

所以我更喜欢这样做:

 Class<?> SystemProperties = Class.forName("android.os.SystemProperties"); Method method = SystemProperties.getMethod("get", new Class[] { String.class }); ArrayList<String> servers = new ArrayList<String>(); for (String name : new String[] { "net.dns1", "net.dns2", "net.dns3", "net.dns4", }) { String value = (String) method.invoke(null, name); if (value != null && !"".equals(value) && !servers.contains(value)) servers.add(value); } 

android.net.ConnectivityManager将使用getAllNetworkInfo()为您提供一个NetworkInfo数组。 然后使用android.net.NetworkUtils.runDhcp()为任何给定的networking接口获取DhcpInfo – DhcpInfo结构具有该接口的dns1dns2的IP地址(表示IP地址的整数值)。

如果你想知道如何将整数转换为IP地址,你可以这样做:

 /** * Convert int IP adress to String * cf. http://teneo.wordpress.com/2008/12/23/java-ip-address-to-integer-and-back/ */ private String intToIp(int i) { return ( i & 0xFF) + "." + (( i >> 8 ) & 0xFF) + "." + (( i >> 16 ) & 0xFF) + "." + (( i >> 24 ) & 0xFF); } 

编辑

你也可以通过做这样的事情得到一个DchcpInfo对象:

 WiFiManager wifi = (WifiManager) getSystemService(WIFI_SERVICE); DhcpInfo info = wifi.getDhcpInfo(); 

我build议dnsjava在Android上使用复杂的DNS。 我们来看看dnsjava如何确定连接的当前活动DNS服务器。 来自dnsjava ResolverConfig.java:428 :

 /** * Parses the output of getprop, which is the only way to get DNS * info on Android. getprop might disappear in future releases, so * this code comes with a use-by date. */ private void findAndroid() { // This originally looked for all lines containing .dns; but // http://code.google.com/p/android/issues/detail?id=2207#c73 // indicates that net.dns* should always be the active nameservers, so // we use those. String re1 = "^\\d+(\\.\\d+){3}$"; String re2 = "^[0-9a-f]+(:[0-9a-f]*)+:[0-9a-f]+$"; try { ArrayList lserver = new ArrayList(); ArrayList lsearch = new ArrayList(); String line; Process p = Runtime.getRuntime().exec("getprop"); InputStream in = p.getInputStream(); InputStreamReader isr = new InputStreamReader(in); BufferedReader br = new BufferedReader(isr); while ((line = br.readLine()) != null ) { StringTokenizer t = new StringTokenizer(line, ":"); String name = t.nextToken(); if (name.indexOf( "net.dns" ) > -1) { String v = t.nextToken(); v = v.replaceAll("[ \\[\\]]", ""); if ((v.matches(re1) || v.matches(re2)) && !lserver.contains(v)) lserver.add(v); } } configureFromLists(lserver, lsearch); } catch ( Exception e ) { // ignore resolutely } } 

一个本地的select是:

 char dns1[PROP_VALUE_MAX]; __system_property_get("net.dns1", dns1); 

或者更好的一个全面的清单:

 for (i = 1; i <= MAX_DNS_PROPERTIES; i++) { char prop_name[PROP_NAME_MAX]; snprintf(prop_name, sizeof(prop_name), "net.dns%d", i); __system_property_get(prop_name, dns); } 

这样做有几个好处:

  1. runDHCP 真的很慢。 它可能需要长达5-10秒。 如果使用不当,可能会造成严重的挂起。
  2. runDCHP似乎不适用于3G / 4G。
  3. 由于runDCHP是一个隐藏的API,它可能会改变。 事实上,它在ICS中确实发生了变化。 在ICS中需要一个新的DhcpInfoInternal,所以你必须创build两个不同的支持所有的手机。

首先将外部JAR layoutlib.jar添加到您的构buildpath,$ SDK_PATH / platforms / android-xxx / data /中的layoutlib.jar文件,然后

 String dnsStr1 = android.os.SystemProperties.get("net.dns1"); String dnsStr2 = android.os.SystemProperties.get("net.dns2"); 

你也可以用$ getprop命令查看adb shell中的所有属性。

以下适用于API 21及以上版本。 它会为WiFi和Cellular接口返回正确的DNS服务器。 我已经validation了shell实用程序“getprop”返回的值

 ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE); for (Network network : connectivityManager.getAllNetworks()) { NetworkInfo networkInfo = connectivityManager.getNetworkInfo(network); if (networkInfo.isConnected()) { LinkProperties linkProperties = connectivityManager.getLinkProperties(network); Log.d("DnsInfo", "iface = " + linkProperties.getInterfaceName()); Log.d("DnsInfo", "dns = " + linkProperties.getDnsServers()); return linkProperties.getDnsServers(); } } 

你可以使用javareflection。 例:

  ConnectivityManager mgr = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); Method getLinkPropeties; try{ getLinkPropeties = mgr.getClass().getMethod("getLinkProperties", int.class); }catch (InvocationTargetException e) { e.printStackTrace(); }