2013-08-13 2 views
3

Android 앱에서 사용자가 인터넷에 연결되어 있는지 테스트하려고합니다. 당신이 관심이 있다면, 이전 질문 Detecting limited network connectivity in Android?DefaultHttpClient에 대해 getaddrinfo 시간 초과를 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를 사용하여 연결 및 소켓에 대한 시간 제한을 제어 할 수 있습니다. 내 장치가 무선 인터넷에 연결되어 있지만 와이파이가 인터넷에 액세스 할 수 없습니다 경우 그러나, 나는 예외지고있어 오류가 없다 :

libcore.io.GaiException : getaddrinfo를 실패 : 관련 EAI_NODATA (없음 주소 이 DNS 조회에 시간 초과처럼 보이는 호스트 이름

와 관련된 주소 : 호스트 "www.example.com"를 해결할

수 없습니다) 호스트 이름. DNS 조회의 제한 시간을 제어 할 수 있습니까? 위에서 언급 한 예외로 인해 httpClient.execute가 실패하는 데 약 45 초가 걸립니다. 빨리 포기하고 싶습니다.

답변

7

저는 약간의 숙제를했지만 DNS 조회 시간 제한을 조정할 수없는 것 같습니다. 그래서, 나는 더 나은 접근 방식을 명시 적 DNS 조회가 될 것이라고 생각했다. 그래서 나는 그것을 제어 할 수 있었고, 다음 번 시도를 빠르게하기 위해 캐시 된 결과를 가지기를 바란다. 그래서 나를 단순하게 만들었습니다.

그러나 이것은 45 초의 타임 아웃을 가졌습니다. 다른 사람들은 no control of the timeout for getByName()이 있다고 언급했습니다. 마지막으로, 나는 간단한 해결책을 찾았고, 별도의 스레드에서 조회를 시작하고 자신의 시간 제한을 관리합니다. This blog post이이를 잘 보여줍니다.

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; 
    } 
} 

이 도구를 사용하여 장치가 호스트 이름을 확인할 수 있는지 먼저 테스트 한 다음 전체 연결 테스트에 성공했는지 테스트 할 수 있습니다.

+0

감사합니다. 매우 중요한 사용 사례에 관한 유일한 게시물 인 것을보고 놀랐습니다. 예를 들어, 핫스팟을 통해 내 앱을 사용하는 사용자 (과부하가 걸리거나 느리거나 인터넷에 연결되지 않은 일반 사용자). –

+0

우리의 문제를 일으킨 상황을 "호텔 WiFi 문제에 대한 CEO"라고했습니다. 우리의 CEO는 호텔에 있고 그의 전화는 호텔의 WiFi에 연결됩니다. 하지만 그는 웹 브라우저를 실행하는 것을 잊어 버리고 실제로 네트워크에 액세스하기 위해 호텔의 Wi-Fi에 로그인합니다. 그는 호텔의 벽으로 둘러싸인 정원에만 한정 될 것이며, 우리가 앱을 돌릴 때 우리 서버에 접근 할 수 없었을 것입니다. 우리는 CEO (및 사용자)가 실제로 인터넷에 액세스 할 수 없을 때 상기시켜주기 위해이 테스트를 실시했습니다. –

+0

wifi에 연결되어 있지만 인터넷에 연결되어 있지 않은 경우 긴 dns 오류 지연을 해결하기 위해 exec (ping)와 함께 접근 방식을 사용하고 있습니다. 읽는 사람들은 dns가 캐싱된다는 것을 기억하십시오. 따라서 첫 번째 DNS 검사 후 인터넷 (ICMP) 연결을 확인하려면 핑이 필요합니다. 긴 하드 코드 된 (20 초) dns 시간 초과를 피할 수있는 다른 방법을 찾지 못했습니다. InetAddr.isReachable() 메서드는 루트 액세스가 필요한 저수준 ICMP 호출을 수행합니다. exec (ping)는 그렇지 않습니다. (8.8.8.8) –

관련 문제