2013-07-23 31 views
5

關於如何檢測Android中的網絡連接有許多問題。 https://stackoverflow.com/a/4239019/90236提供了一個非常詳細的答案,並且https://stackoverflow.com/a/8548926/90236顯示了識別人們連接的網絡類型的方法。在Android中檢測有限的網絡連接?

private boolean isNetworkAvailable() { 
    ConnectivityManager connectivityManager 
      = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo(); 
    return activeNetworkInfo != null && activeNetworkInfo.isConnected(); 
} 

這讓我們提醒用戶,如果它們是離線:

我們使用類似於像這些問題的答案代碼檢測網絡的連通性。但是,它不能幫助我們確定用戶是否具有有限的連接。有限的連接條件導致用戶投訴。這些包括:

  1. 用戶連接到家庭無線網絡,但有線調制解調器或互聯網服務不可用。

  2. 用戶在酒店或咖啡店併成功連接到wifi網絡,但網絡要求他們登錄或同意服務條款,才能獲得完整的網絡訪問權限。

在這兩種情況下,我們的isNetworkAvailable()測試都返回true。操作系統告訴我們我們已連接到網絡。但是,用戶沒有可用的Internet連接。

有沒有一種很好的方法來確定用戶具有完整的網絡連接?

我在考慮調用一個輕量級的Web服務來驗證它們的連接性,並警告用戶如果應用程序沒有從服務中獲得有效的返回。這是否過分矯枉過正?或讓其他人不得不求助於類似的技術?

回答

8

是否有一種很好的方法來確定用戶是否具有完整的網絡連接?

嘗試從某處下載東西。理想情況下,「某處」是您自己的服務器,用於測試設備和服務器之間的連接。

唉,在ConnectivityManager上沒有doesTehConnexionSuck()iCanHazBandwidth()方法。 :-)

這是否矯枉過正?

本着「金髮姑娘和三隻熊」的精神,我將其描述爲合理的技巧。

我們也必須做the same sorts of shenanigans in Web apps

+1

我喜歡「justrightkill」的想法,但它不具有相同的戒指給它 - http://www.youtube.com/watch?v=YjETcbEDmoQ –

+0

哈哈很搞笑..... –

3

爲了完整起見,讓我發佈一些我添加的代碼。我認爲這是相當普通的HttpClient代碼來發出Http請求,並在請求成功時返回true。我使用HttpHead,因爲我不關心響應中的實體,這應該使它更快。此方法位於名爲ConnectivityHelper的類中,而DefaultSettings是一個定義了一堆有用常量的類。

public static boolean isNetworkAvailable() { 
    ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 
    NetworkInfo netInfo; 

    try { 
     netInfo = manager.getActiveNetworkInfo(); 
    } catch (Exception e) { 
     netInfo = null; 
    } 

    return netInfo != null && netInfo.isConnected() && testConnection(DefaultSettings.TEST_CONNECTION_URL); 
} 


private static boolean testConnection(String url) { 
    HttpClient httpClient = null; 
    HttpHead request = null; 
    HttpResponse response = null; 
    int statusCode = 0; 

    try { 
     HttpParams myParams = new BasicHttpParams(); 
     HttpConnectionParams.setConnectionTimeout(myParams, DefaultSettings.CONNECTION_TIMEOUT); 
     HttpConnectionParams.setSoTimeout(myParams, DefaultSettings.SO_TIMEOUT); 

     httpClient = new DefaultHttpClient(myParams); 

     request = new HttpHead(url); 
     response = httpClient.execute(request); 
     statusCode = response.getStatusLine().getStatusCode(); 

     if (statusCode != 200) 
     { 
      Log.e(ConnectivityHelper.class.getName(), String.format("testConnection not successful. For %s - Status code = %d", url, statusCode)); 
      return false; 
     } 
     return true; 

    } catch(ClientProtocolException e) { 
     Log.e(ConnectivityHelper.class.getName(), String.format("testConnection failure. For %s - Exception: %s.", url, e.toString())); 

     if (request != null && !request.isAborted()) { 
      request.abort(); 
     } 

     return false; 
    } catch(IOException e) { 
     if (statusCode == 401) { 
      Log.e(ConnectivityHelper.class.getName(), String.format("testConnection access denied. For %s - Status code = %d", url, statusCode));    
     } else { 
      Log.e(ConnectivityHelper.class.getName(), String.format("testConnection failure. For %s - Exception: %s.", url, e.toString())); 
     } 

     if (request != null && !request.isAborted()) { 
      request.abort(); 
     } 

     return false; 
    } finally { 
     if (httpClient != null) { 
      httpClient.getConnectionManager().shutdown(); 
     } 
    }   
} 
+0

我認爲你應該將你的答案標記爲已接受。 – dentex

+0

嗯,這是@CommonsWare發佈的答案,讓我寫上面的代碼,所以他的答案是第一個,真的很有幫助。其餘的,正如他們所說,只是一個練習。 –

+0

夠公平的。 :) – dentex