Intereting Posts

Как вы получаете текущие DNS-серверы для Android?

Я пытаюсь получить адреса на используемых в настоящее время DNS-серверах в своем приложении, либо я подключен через Wifi или мобильный. Объект DhcpInfo должен предоставить это, но как я могу получить доступ к действительному объекту DhcpInfo?

Solutions Collecting From Web of "Как вы получаете текущие DNS-серверы для Android?"

Вызов для функции getRuntime().exec может повесить ваше приложение.

android.net.NetworkUtils.runDhcp() вызывают ненужные сетевые запросы.

Поэтому я предпочитаю делать это:

 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 предоставит вам массив NetworkInfo, используя getAllNetworkInfo() . Затем используйте android.net.NetworkUtils.runDhcp() чтобы получить DhcpInfo для любого заданного сетевого интерфейса. Структура DhcpInfo имеет IP-адрес для dns1 и dns2 для этого интерфейса (которые представляют собой целочисленные значения, представляющие 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(); 

Собственная альтернатива:

 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, поэтому вам придется создать два разных для поддержки всех телефонов.

Я рекомендую dnsjava для комплексного использования DNS на Android. Посмотрим, как 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 } } 

Сначала добавьте внешний JARs layoutlib.jar в ваш путь сборки, файл layoutlib.jar в $ SDK_PATH / platform / android-xxx / data /, затем

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

Вы также можете увидеть все свойства в оболочке adb с помощью команды $ getprop.

Следующие работы для API 21 и выше. Он возвращает правильные серверы DNS для WiFi и сотовых интерфейсов. Я проверил значения, возвращаемые с помощью командной оболочки '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(); } } 

Вы можете использовать java-отражение. пример:

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