2015-08-27 40 views
0

我正在開發一個Android應用程序,它定期通過REST API調用回報數據服務器。每當應用程序嘗試發送其中一個報告時,但沒有網絡頻道(wifi或移動數據)可用時,應用程序將爲該任務創建一個包裝並將其放入與BroadcastReceiver相關的隊列中。接收者收聽android.net.wifi.STATE_CHANGEandroid.net.conn.CONNECTIVITY_CHANGE,然後嘗試在新連接上執行入隊任務。所有的認證邏輯也在這裏處理。實際的請求POST將通過Retrofit庫發送出去。(Android)有沒有可靠的信號來表明網絡通道是可路由的?

我的問題是,每當網絡訪問「回來」,並且接收器試圖啓動所有正在等待的任務時,我總是會回到java.net.UnknownHostException,指出數據服務器的主機名沒有關聯地址。看起來,雖然Android設備知道它已經連接到網絡,但它仍然不知道從哪裏獲取DNS,並且在此狀態下出現的任何請求都會失敗。

D/Retrofit﹕ java.net.UnknownHostException: Unable to resolve host "[REDACTED]": No address associated with hostname 
     at java.net.InetAddress.lookupHostByName(InetAddress.java:424) 
     at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236) 
     at java.net.InetAddress.getAllByName(InetAddress.java:214) 
     at com.squareup.okhttp.internal.Network$1.resolveInetAddresses(Network.java:29) 
     at com.squareup.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:266) 
     at com.squareup.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:240) 
     at com.squareup.okhttp.internal.http.RouteSelector.nextUnconnected(RouteSelector.java:156) 
     at com.squareup.okhttp.internal.http.RouteSelector.next(RouteSelector.java:130) 
     at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:312) 
     at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:235) 
     at com.squareup.okhttp.Call.getResponse(Call.java:262) 
     at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:219) 
     at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:192) 
     at com.squareup.okhttp.Call.execute(Call.java:79) 
     at retrofit.client.OkClient.execute(OkClient.java:53) 
     at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:326) 
     at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:240) 
     at [REDACTED](Native Method) 
     at [REDACTED] 
     [etc] 
    Caused by: libcore.io.GaiException: getaddrinfo failed: EAI_NODATA (No address associated with hostname) 
    Caused by: libcore.io.ErrnoException: getaddrinfo failed: ENETUNREACH (Network is unreachable) 

的根本原因異常(libcore.io.ErrnoException)聲稱,網絡不可達,但我甚至不嘗試,直到我已經後從Android OS接收的意圖這個執行特別是因爲的實際上,網絡現在是可達的。

我驗證無線網絡的可用性代碼:

protected static boolean isWifiAvailable(WifiManager wifi) 
{ 
    WifiInfo info = wifi.getConnectionInfo() ; 
    if(info == null) return false ; 
    if(info.getNetworkId() == -1) return false ; 
    if(info.getSupplicantState() != SupplicantState.COMPLETED) 
     return false ; 
    return true ; 
} 

我覈實移動數據可用性代碼:

protected static boolean isMobileDataAvailable(TelephonyManager tmgr) 
{ 
    return(tmgr.getDataState() == TelephonyManager.DATA_CONNECTED) ; 
} 

問:有沒有更可靠的信號 - 這是我沒有檢查在WifiInfoTelephonyManager - 那就表示網絡頻道真的是,真的準備好了嗎?或者這是一個沒有明確決議的競賽條件?

回答

0

經常發生的問題我在發佈問題後不久發現了一個解決方案。事實證明,移動數據檢查是足夠的......大部分時間。 WiFi的檢查是需要更多的工作之一:

protected static boolean isWifiAvailable(WifiManager wifi) 
{ 
    WifiInfo info = wifi.getConnectionInfo() ; 
    if(info == null) return false ; 
    if(info.getNetworkId() == -1) return false ; 
    if(info.getSupplicantState() != SupplicantState.COMPLETED) 
     return false ; 
    // Here are the crucial additions: 
    DhcpInfo dhcp = wifi.getDhcpInfo() ; 
    if(dhcp == null) return false ; 
    if(dhcp.ipAddress != info.getIpAddress()) return false ; 
    return true ; 
} 

通過檢查WifiInfoDhcpInfo我們終於有了一個結論性的測試當前的WiFi網絡是否路由。

+0

這是一個神測試,但它不是確鑿的。 – EJP

相關問題