2010-05-10 74 views
91

Tôi muốn trả về false nếu URL mất nhiều hơn 5 giây để kết nối - làm thế nào điều này có thể sử dụng Java? Đây là mã tôi đang sử dụng để kiểm tra xem URL có hợp lệ khôngHttpURLCài đặt thời gian chờ kết nối

HttpURLConnection.setFollowRedirects(false); 
HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(); 
con.setRequestMethod("HEAD"); 
return (con.getResponseCode() == HttpURLConnection.HTTP_OK); 

Trả lời

153

HttpURLConnection có phương thức setConnectTimeout.

Chỉ cần thiết lập thời gian chờ đến 5000 mili giây, và sau đó bắt java.net.SocketTimeoutException

Mã của bạn nên tìm một cái gì đó như thế này:

 

try { 
    HttpURLConnection.setFollowRedirects(false); 
    HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(); 
    con.setRequestMethod("HEAD"); 

    con.setConnectTimeout(5000); //set timeout to 5 seconds 

    return (con.getResponseCode() == HttpURLConnection.HTTP_OK); 
} catch (java.net.SocketTimeoutException e) { 
    return false; 
} catch (java.io.IOException e) { 
    return false; 
} 

 
+1

Tôi đặt giá trị thành 10 phút. Tuy nhiên nó ném cho tôi một 'java.net.ConnectException: Kết nối đã hết thời gian: kết nối' trước cả 2 phút. Bạn có biết điều gì gây ra vấn đề không? – Pacerier

+0

@ dbyrne điều này có vẻ hơi khó hiểu với tôi - vì chúng tôi đặt thời gian chờ sau khi đối tượng 'HttpURLConnection' được tạo, tôi tự hỏi đâu là vị trí chính xác trong mã sẽ tăng' SocketTimeoutException'? – Less

+3

SocketTimeoutException là một phân lớp của IOException. Nếu cả hai khối catch làm cùng một điều, bạn chỉ có thể bắt IOException. – spaaarky21

85

Bạn có thể thiết lập thời gian chờ như thế này,

con.setConnectTimeout(connectTimeout); 
con.setReadTimeout(socketTimeout); 
+1

Giá trị tối đa của thời gian chờ mà chúng tôi có thể chỉ định là gì? – Pacerier

+5

@Pacerier Các tài liệu không nêu rõ điều này. Nó ném một IllegalArgumentException nếu giá trị là âm (giá trị bằng 0 có nghĩa là chờ đợi vô thời hạn). Kể từ thời gian chờ là một int 32bit unsigned, tôi sẽ đoán thời gian chờ tối đa sẽ là khoảng 49 ngày (mặc dù tôi nghiêm túc nghi ngờ điều này một giá trị sẽ là hữu ích cho bất cứ ai). –

+1

+1 cho nhiều loại thời gian chờ ... – jsh

1

Nếu Kết nối HTTP không hết thời gian chờ, Bạn có thể thực hiện trình kiểm tra thời gian chờ trong chính chuỗi nền (AsyncTask, Service, v.v.), lớp sau đây là một bài kiểm tra ple cho Customize AsyncTask mà thời gian chờ sau thời gian nhất định

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àn toàn không cần thiết để tạo chuỗi chỉ mới để lên lịch cuộc gọi đến cancel(). Bạn có thể làm điều đó từ luồng chính trong 'onPreExecute()'.Ngoài ra, nếu bạn hủy tác vụ theo cách thủ công, bạn cũng nên hủy cuộc gọi đã lên lịch để tránh bị rò rỉ. – BladeCoder

+0

Điểm ở đây là hủy AsyncTask ở giữa doInBackground() khi phải mất quá nhiều thời gian khi thực hiện không tại onPreExecute(), tôi cũng chỉ muốn hủy bỏ trường hợp này của AsyncTask mất quá nhiều thời gian và giữ cho những người khác, đánh giá cao phản hồi của bạn. –

+1

Tôi nghĩ rằng thông điệp của tôi không đủ rõ ràng. Tôi đã không nói rằng bạn nên hủy bỏ trong onPreExecute(), tôi đã nói bạn nên tạo Handler trong onPreExecute() và gửi hủy bỏ trì hoãn từ chủ đề chính. Bằng cách này, bạn sẽ sử dụng chủ đề chính làm luồng looper và dĩ nhiên bạn có thể hủy AsyncTask sau này trong khi doInBackground() đang thực thi vì luồng chính cũng chạy đồng thời với luồng nền. – BladeCoder

0

tôi có thể có được giải pháp cho một vấn đề tương tự như vậy với việc bổ sung một dòng đơn giản

HttpURLConnection hConn = (HttpURLConnection) url.openConnection(); 
hConn.setRequestMethod("HEAD"); 

My yêu cầu là để biết mã phản ứng và cho rằng chỉ nhận được thông tin meta là đủ, thay vì nhận được cơ thể đáp ứng hoàn chỉnh.

Phương thức yêu cầu mặc định là GET và đã mất rất nhiều thời gian để trả lại, cuối cùng là ném cho tôi SocketTimeoutException. Câu trả lời khá nhanh khi tôi đặt Phương thức Yêu cầu thành HEAD.

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