2012-07-04 48 views
14

我有以下代碼塊:爲什麼超時值不被android HttpURLConnection所尊重?

try { 
    URL url = new URL("http://site-to-test.com/nonexistingpage.html"); 

    HttpURLConnection urlc = (HttpURLConnection) url.openConnection(); 
    urlc.setRequestProperty("User-Agent", CoreProtocolPNames.USER_AGENT); 
    urlc.setRequestProperty("Connection", "close"); 
    urlc.setConnectTimeout(500); // timeout is in milliseconds 
    urlc.connect(); 

    if (urlc.getResponseCode() == 404) { 
     // Server was reachable 
     Log.i(TAG, "Server is reachable"); 
    } 

} catch (MalformedURLException mue) { 
    Log.e(TAG, "MalformedURLException: " + mue.getMessage()); 
} catch (IOException e) { 
    Log.e(TAG, "IOException: " + e.getMessage()); 
} 

site-to-test域不是通過當前的網絡可到達的,在接收到前IOException約30-40秒這個代碼塊。我特別將超時值設置爲500ms。我在這裏錯過了什麼?不管網絡狀態和網站的可用性如何,上述塊不應該在半秒內終止?

+1

可以使用的TimerTask和樣本使用這個類定時器一起設置限制.... –

+0

順便說一句,你正在做一個單獨的'Thread'(或'AsyncTask'),對吧? –

+0

是的,亞歷克斯,我不會夢想阻止UI線程。 –

回答

13

似乎Java URLConnection provides no fail-safe timeout on reads

的解決方案是,作爲文章解釋,使用一個單獨的線程來定時,並手動斷開HttpURLConnection類一旦定時器線程完成。

+0

如果我使用AsyncTask而不是線程,可以使用這種解決方法嗎? – NoBugs

+0

我想我在Android中爲我的AsyncTask問題找到了一個很好的解決方案。我設置了一個定時器在一定的延遲後停止,並在下載另一個片段時重置定時器。這樣,它不會超時慢速連接,但超時如果網絡斷開連接:http://stackoverflow.com/questions/6829801/httpurlconnection-setconnecttimeout-has-no-effect/11790633#11790633 – NoBugs

+0

我有一個' HttpURLConnection'對象,獲取數據並嘗試使用'OutputStream'對象將其寫入文件。 'output = connection.getOutputStream();'。在關閉Wi-Fi後,拋出了'ConnectException'。這是否意味着我可以聽我的網絡連接? –

1

經過深入調查和大量的步驟後,我發現實現AsyncTask(或服務,您用來執行後臺工作的對象)的計時器遠離HTTP連接類的最佳方式,有時您斷開連接HTTP連接,這不會中斷網絡通話,我實現了當你需要超時檢查你的HTTP連接

public abstract class AsyncTaskWithTimer<Params, Progress, Result> extends 
    AsyncTask<Params, Progress, Result> { 

    private static final int HTTP_REQUEST_TIMEOUT = 30000; 

    @Override 
    protected Result doInBackground(Params... params) { 
     createTimeoutListener(); 
     return doInBackgroundImpl(params); 
    } 

    private void createTimeoutListener() { 
     Thread timeout = new Thread() { 
      public void run() { 
       Looper.prepare(); 

       final Handler handler = new Handler(); 
       handler.postDelayed(new Runnable() { 
        @Override 
        public void run() { 

         if (AsyncTaskWithTimer.this != null 
           && AsyncTaskWithTimer.this.getStatus() != Status.FINISHED) 
          AsyncTaskWithTimer.this.cancel(true); 
         handler.removeCallbacks(this); 
         Looper.myLooper().quit(); 
        } 
       }, HTTP_REQUEST_TIMEOUT); 

       Looper.loop(); 
      } 
     }; 
     timeout.start(); 
    } 

    abstract protected Result doInBackgroundImpl(Params... params); 
} 

public class AsyncTaskWithTimerSample extends AsyncTaskWithTimer<Void, Void, Void> { 

    @Override 
    protected void onCancelled(Void void) { 
     Log.d(TAG, "Async Task onCancelled With Result"); 
     super.onCancelled(result); 
    } 

    @Override 
    protected void onCancelled() { 
     Log.d(TAG, "Async Task onCancelled"); 
     super.onCancelled(); 
    } 

    @Override 
    protected Void doInBackgroundImpl(Void... params) { 
     // Do background work 
     return null; 
    }; 
} 
+0

工程很棒。謝謝。不能爲我的生活得到HttpURLConnection以紀念setXXXTimeout方法。 –