2012-07-04 36 views
14

Tôi có khối mã sau:Tại sao giá trị thời gian chờ không được HttpURLConnection của android tôn trọng?

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

Khi miền site-to-test là không thể truy cập thông qua mạng lưới hiện nay, mã này khối trong khoảng 30-40 giây trước khi nhận IOException. Và tôi đặc biệt đặt giá trị thời gian chờ là 500 mili giây. Tôi đang thiếu gì ở đây? Không nên các khối trên chấm dứt trong nửa giây, bất kể trạng thái mạng và tính khả dụng của trang web?

+1

bạn có thể sử dụng TimerTask và Hẹn giờ với nhau để đặt giới hạn .... –

+0

BTW, bạn đang làm điều này trên một 'Thread' riêng biệt (hoặc 'AsyncTask'), phải không? –

+0

Có, Alex, tôi sẽ không mơ ước chặn chuỗi giao diện người dùng. –

Trả lời

13

Dường như Java URLConnection provides no fail-safe timeout on reads

Giải pháp là, như bài báo giải thích, sử dụng một chủ đề riêng biệt cho thời gian, và ngắt kết nối HttpURLConnection bằng tay một lần thread hẹn giờ được thực hiện.

+0

Giải pháp này có thể thực hiện được nếu tôi sử dụng AsyncTask thay vì Chủ đề không? – NoBugs

+0

Tôi nghĩ rằng tôi đã tìm thấy một giải pháp tốt cho vấn đề AsyncTask của tôi trong Android. Tôi đặt Bộ hẹn giờ để dừng sau một khoảng thời gian nhất định và đặt lại bộ hẹn giờ khi nó tải xuống một phần khác. Bằng cách này nó không thời gian ra trên kết nối chậm, nhưng lần ra nếu mạng bị ngắt kết nối: http://stackoverflow.com/questions/6829801/httpurlconnection-setconnecttimeout-has-no-effect/11790633#11790633 – NoBugs

+0

Tôi có một ' Đối tượng HttpURLConnection', lấy dữ liệu và cố gắng ghi nó vào một tệp bằng cách sử dụng đối tượng 'OutputStream'. 'output = connection.getOutputStream();'. Sau khi tôi đã tắt Wi-Fi, 'ConnectException' đã bị ném. Điều đó có nghĩa là tôi có thể nghe kết nối mạng của mình không? –

1

Sau khi điều tra sâu và rất nhiều đường nhỏ, tôi thấy rằng cách tốt nhất để thực hiện bộ hẹn giờ cho AsyncTask (hoặc Dịch vụ, đối tượng bạn đã sử dụng để thực hiện công việc nền) khỏi lớp kết nối HTTP, đôi khi bạn ngắt kết nối kết nối HTTP, điều này không làm gián đoạn cuộc gọi web, tôi thực hiện lớp này sẽ được sử dụng khi bạn cần kiểm tra thời gian chờ cho kết nối HTTP của bạn

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

Một mẫu cho điều này

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

Hoạt động tuyệt vời. Cảm ơn. Không thể cho cuộc sống của tôi nhận được HttpURLConnection để tôn vinh các phương pháp setXXXTimeout. –

Các vấn đề liên quan