Могу ли я установить тайм-аут getaddrinfo в Android для DefaultHttpClient?

В приложении для Android я пытаюсь проверить, работает ли у пользователя рабочее интернет-соединение. Если вам интересно, в предыдущем вопросе есть какой-то фон. Обнаружение ограниченного сетевого подключения в Android?

Код в основном похож:

try { HttpParams myParams = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(myParams, 10000); HttpConnectionParams.setSoTimeout(myParams, 10000); httpClient = new DefaultHttpClient(myParams); request = new HttpHead(url); response = httpClient.execute(request); statusCode = response.getStatusLine().getStatusCode(); if (statusCode != 200) { return false; } return true; } catch(Exception e) { return false; } 

Я могу контролировать таймауты для соединения и сокета с помощью HttpConnectionParams. Но, если мое устройство подключено к Wi-Fi, но Wi-Fi не имеет доступа в Интернет, ошибка, которую я получаю в исключении:

Libcore.io.GaiException: getaddrinfo не удалось: EAI_NODATA (Нет адреса, связанного с именем хоста)

Не удалось разрешить хост «www.example.com»: нет адреса, связанного с именем хоста

Похоже, что он был рассчитан на поиск DNS. Могу ли я контролировать тайм-аут DNS-поиска? HttpClient.execute занимает около 45 секунд, чтобы сбой с исключением, указанным выше. Я бы хотел, чтобы он сдался раньше.

Я сделал небольшую домашнюю работу, и кажется, что вы не можете настроить тайм-аут поиска DNS. Итак, я решил, что лучший подход будет заключаться в явном поиске DNS, чтобы я мог контролировать его (и, надеюсь, результат будет кэширован для ускорения следующей попытки). Так что это привело меня к простому:

 InetAddress addr = InetAddress.getByName(hostname); 

Но это также имело 45-секундный тайм-аут. Другие упоминали, что не было контроля над тайм-аутом для getByName () . Наконец, я наткнулся на простое решение, просто запустил поиск в отдельном потоке и управлял собственным таймаутом. Это сообщение в блоге показывает это довольно хорошо.

 private static boolean testDNS(String hostname) { try { DNSResolver dnsRes = new DNSResolver(hostname); Thread t = new Thread(dnsRes); t.start(); t.join(1000); InetAddress inetAddr = dnsRes.get(); return inetAddr != null; } catch(Exception e) { return false; } } private static class DNSResolver implements Runnable { private String domain; private InetAddress inetAddr; public DNSResolver(String domain) { this.domain = domain; } public void run() { try { InetAddress addr = InetAddress.getByName(domain); set(addr); } catch (UnknownHostException e) { } } public synchronized void set(InetAddress inetAddr) { this.inetAddr = inetAddr; } public synchronized InetAddress get() { return inetAddr; } } 

Используя это, я могу сначала проверить, может ли устройство разрешить имя хоста, а затем успешно ли оно выполнить тест на полную совместимость.