我的Android应用程序中的一些代码遇到了一个问题,它从URL下载了一个文件,这里是一段代码片段:
int bytesRead = 0;
final byte[] buffer = new byte[32 * 1024];
InputStream stream = httpUrlConnection.getInputStream();
try {
while ((bytesRead = stream.read(buffer)) > 0) {
Log.i("TAG", "Read from steam, Bytes Read: " + bytesRead);
}
} catch (IOException ex) {
//Recover from lost WIFI connection.
} finally {
stream.close();
}
如果WiFi连接丢失,我的应用程序依赖InputStream.read()
抛出IOException
。如Java 8 documentation中所述,此方法应抛出IOException
"如果输入流已关闭,或者出现其他I / O错误" 。在Android M中,这会立即发生,我的代码可以处理并从异常中恢复。在Android N中,不抛出此异常导致我的应用程序只是挂在read()
方法中,它永远不会突破它。有没有其他人遇到这个问题,并以不会向后兼容的方式解决它?这是一个新的Android N bug吗?
答案 0 :(得分:2)
如果连接断开,从套接字读取可以永久阻止。您需要使用读取超时。
答案 1 :(得分:0)
正如@EJP所说"如果连接断开,套接字读取可以永久阻塞,只需将此行添加到代码中,并捕获java.net.SocketTimeoutException:
int bytesRead = 0;
final byte[] buffer = new byte[32 * 1024];
InputStream stream = httpUrlConnection.getInputStream();
httpUrlConnection.setConnectTimeout(5000);
try {
while ((bytesRead = stream.read(buffer)) > 0) {
Log.i("TAG", "Read from steam, Bytes Read: " + bytesRead);
}
} catch (java.net.SocketTimeoutException ex) {
//Recover from lost WIFI connection.
} finally {
stream.close();
}
答案 2 :(得分:0)
为了避免重新发明轮子并发现自己弄清楚这个以及其他一些常见场景,我会使用高级库,例如 Volley
Volley以非常直接的方式为您提供有趣的事情:
发送请求就像这样简单(来自文档)
final TextView mTextView = (TextView) findViewById(R.id.text);
...
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(this);
String url ="http://www.google.com";
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
// Display the first 500 characters of the response string.
mTextView.setText("Response is: "+ response.substring(0,500));
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
mTextView.setText("That didn't work!");
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
设置超时/重试策略非常简单:
stringRequest.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 1, 1.0f));
参数是:
关于错误处理
如您所见,您正在向请求传递错误侦听器new Response.ErrorListener()
。当出现错误时,Volley会在执行请求时发生错误时调用onErrorResponse回调public void onErrorResponse
方法传递VolleyError对象的实例。
以下是Volley中的例外列表,摘自本文here
所以你可以做像
这样的事情 if ((error instanceof NetworkError) || (error instanceof NoConnectionError)) {
//then it was a network error
}