HttpURLConnection.getInputStream() 停滞不前并且永远无法完成

5
我正在尝试使用以下代码从JSON接口获取令牌:
```python ```
public class FetchToken extends AsyncTask<String, Void, Void> {
    String data = "";
    String token = "";

    public TokenDelegate delegate = null;

    @Override
    protected Void doInBackground(String... identity) {
        try {
            if (identity.length == 1) {
                URL url = new URL(identity[0]);

                HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                InputStream inputStream = httpURLConnection.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                String line = "";

                while (line != null) {
                    line = bufferedReader.readLine();
                    data = data + line;
                }

                JSONObject JO = new JSONObject(data);
                token = JO.get("token").toString();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        Log.d("token", token);
        //delegate.processFinish(token);
        super.onPostExecute(aVoid);
    }
}

我已经尝试在每行代码后将其打印到调试日志中,似乎代码的这一行 InputStream inputStream = httpURLConnection.getInputStream(); 从未完成,也没有执行其余代码。然而,这是在一个AsyncTask中进行的,在该AsyncTask的onPostExecute方法触发时,就好像任务已经完成了,但似乎并没有完成。
似乎没有任何catch块被执行,当我检查Android Profiler中的网络面板时,请求似乎没有返回任何内容。然而,通过浏览器访问JSON端点可以正确地返回所有内容。
希望有人知道问题可能是什么。我已经尝试过谷歌搜索,但没有结果。如果需要更多信息,请告诉我。谢谢。

那个AsyncTask的onPostExecute方法正在触发,然后如果(identity.length == 1),httpURLConnection.getInputStream()就会工作,因为这是一个阻塞调用,你确定你没有捕获异常并返回null吗?检查一下logcat。还要确保在finally块中关闭流。 - Mark
你曾经找到正确的解决方案吗? - Bahadır EKİCİ
在我的情况下,这是因为我的模拟器无法连接到互联网。 - Eugenio
4个回答

7

您最有可能想设置超时时间,以确保当外部资源未及时可用时连接失败。这些值以毫秒为单位,例如,连接和读取都设置5秒的超时时间:

 HttpURLConnection conn = ...
 conn.setConnectTimeout(5000);
 conn.setReadTimeout(5000);

默认情况下,超时时间被设置为0,根据setConnectTimeout()的说明:

0超时时间被解释为无限超时。


感谢您的建议。不幸的是,这并没有解决问题。当我在浏览器中访问资源时,它的响应比超时时间要快。 - Dehodson

5

这行代码InputStream inputStream = httpURLConnection.getInputStream();之所以不能完成,是因为它抛出了一个java.security.cert.CertPathValidatorException异常。由于在try/catch块中没有捕获这种类型的异常,因此错误未被记录。


3
请看以下代码并相应修改您的代码。
1)如果方法是GET,则数据或标头可以为空。
示例用法
 url = <some url>
 Map<String, String> headers = new HashMap<String, String>();       
 headers.put("Content-Type", "application/json");       
 headers.put("Accept", "application/json");

a) GET :

invokeHTTPRequest(url, "GET", headers, null);

b) POST

Student st = new Student();
Gson gson = new Gson();
String jsonReqData = gson.toJson(st);
String resp = invokeHTTPRequest3(url, "POST", headers,  jsonReqData);

公共静态字符串调用HTTPRequest(String urlString,String method,Map headers,String data){

    URL url = null;
    try {
        url = new URL(urlString);
        HttpURLConnection conn = null;
        conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod(method);
        conn.setConnectTimeout(10000);
        conn.setReadTimeout(10000);

        if (headers != null) {
            for (Map.Entry<String, String> header : headers.entrySet()) {
                conn.setRequestProperty(header.getKey(), header.getValue());
            }
        }



        if (data != null) {
            byte[] postDataBytes = data.toString().getBytes();
            conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
            conn.setDoOutput(true);
            conn.getOutputStream().write(postDataBytes);

        }

        BufferedReader rd = null;

        if(conn.getResponseCode() == 200){
            rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        }
        else{
            rd = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
        }

        StringBuilder result = new StringBuilder();

        String line;
        while ((line = rd.readLine()) != null) {
            result.append(line);
        }
        rd.close();


        return result.toString();

    } catch (Exception e) {
        //handle exception here
    }

}

2

你忘记在 HttpUrlConnection 上调用 connect 方法:

HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.connect();
InputStream inputStream = httpURLConnection.getInputStream();

添加带有.connect()的行似乎无法解决问题。 - Dehodson
3
实际上,connect() 不是必须的。只需调用 url.openConnection(); 即可。 - Barns
是的,我忘记了 getInputStream() 会强制执行 connect() :/ - Levi Moreira

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接