2011-10-24 5 views
3

私は、アプリケーションがアクティブな間開いているソケット接続を使用してサーバーに接続するアンドロイドアプリを持っています。電話機が非アクティブ(ロック画面)またはユーザーがホームボタンを押すと、アプリケーションはソケット接続を閉じて、アプリケーションが再び表示されるようにすると再び開きます。ネットワーク(Mobile - > Wifi)の変更中にSocketConnectionを維持するベストプラクティス

このパターンは、私たちが持っているほとんどのAndroid携帯(約15台)でうまく動作しますが、Motorola Milestone、Defy、SE Xperia Arc、LG Optimus Oneは、それに続いて利用でき、接続します。

public static boolean waitNetworkConnection(Context context, int retries) { 
    ConnectivityManager cm = (ConnectivityManager) 
         context.getSystemService(Context.CONNECTIVITY_SERVICE); 

    NetworkInfo ni = getNetworkToTest(cm); 

    if (ni == null || !ni.isConnected()) { 
     // sleep a short while to allow system to switch connecting networks. 
     Tools.sleep(1000); 
     int counter = 0; 
     while (counter < retries && (ni == null || (ni.isAvailable() && 
       !ni.isConnected()))) { 
      Tools.sleep(500); 
      ni = getNetworkToTest(cm); 
      counter++; 
     } 
    } 

    return (cm.getActiveNetworkInfo() != null && 
      cm.getActiveNetworkInfo().isConnected()); 
} 

、このメソッドを好む(上記1での使用)をテストするための接続を取得するために、:だから私は(サーバーへのソケットを開く前に)次のコードを使用して最適なネットワーク接続を待機します(必要に応じていない接続)が利用可能な場合のWiFi接続:

private static NetworkInfo getNetworkToTest(ConnectivityManager cm) { 
    NetworkInfo[] nis = cm.getAllNetworkInfo(); 
    NetworkInfo ni = cm.getActiveNetworkInfo(); 

    for (int i = 0; i < nis.length; i++) { 
     if (nis[i].getType() == 1 /* Wifi */ && nis[i].isAvailable()) { 
      ni = nis[i]; 
      return(ni); 
     } 
    } 
    return(ni); 
} 

これは、デバイスのほとんどのために正常に動作しますが、前述のもののために、これは非常に頻繁に失敗し、この方法は、モバイルネットワーク接続を使用するように私に語ったと、ソケット接続を開いている間にデバイスが接続タイプを切り替えると、非常に一般的なエラーメッセージでSocketExceptionが発生し、detできなくなりますソケット接続がこの問題によって引き起こされているかどうか、または他のネットワークエラーが原因で発生しているかどうかを確認します。

再試行を行うだけでは、この問題は解決されません。これは、ソケットタイムアウトを検出するために(2回チェックされるため)非常に時間がかかるためです。

他の誰かがこの問題に遭遇しました(非常に低速でWifiに接続しています)、これに対する解決策がありますか?

答えて

0

のWi-Fi/3Gの問題ラウンド取得HTTPラッパーを、持っているdroidfuと呼ばれるプロジェクトがあります。ここで

BetterHttpRequestBaseクラスのコードからの抜粋です:

public BetterHttpResponse send() throws ConnectException { 

    BetterHttpRequestRetryHandler retryHandler = new BetterHttpRequestRetryHandler(maxRetries); 

    // tell HttpClient to user our own retry handler 
    httpClient.setHttpRequestRetryHandler(retryHandler); 

    HttpContext context = new BasicHttpContext(); 

    // Grab a coffee now and lean back, I'm not good at explaining stuff. This code realizes 
    // a second retry layer on top of HttpClient. Rationale: HttpClient.execute sometimes craps 
    // out even *before* the HttpRequestRetryHandler set above is called, e.g. on a 
    // "Network unreachable" SocketException, which can happen when failing over from Wi-Fi to 
    // 3G or vice versa. Hence, we catch these exceptions, feed it through the same retry 
    // decision method *again*, and align the execution count along the way. 
    boolean retry = true; 
    IOException cause = null; 
    while (retry) { 
     try { 
      return httpClient.execute(request, this, context); 
     } catch (IOException e) { 
      cause = e; 
      retry = retryRequest(retryHandler, cause, context); 
     } catch (NullPointerException e) { 
      // there's a bug in HttpClient 4.0.x that on some occasions causes 
      // DefaultRequestExecutor to throw an NPE, see 
      // http://code.google.com/p/android/issues/detail?id=5255 
      cause = new IOException("NPE in HttpClient" + e.getMessage()); 
      retry = retryRequest(retryHandler, cause, context); 
     } finally { 
      // if timeout was changed with this request using withTimeout(), reset it 
      if (oldTimeout != BetterHttp.getSocketTimeout()) { 
       BetterHttp.setSocketTimeout(oldTimeout); 
      } 
     } 
    } 

    // no retries left, crap out with exception 
    ConnectException ex = new ConnectException(); 
    ex.initCause(cause); 
    throw ex; 
} 
+0

ステートレスhttpを使用している場合は正常に動作しますが、ステートフルなソケット接続が必要です。 – HefferWolf

関連する問題