私のアプリはさまざまな時にサーバーに接続します。 3gとwifiの間で切り替えると、ソケットタイムアウトエラーが発生します。これを回避するには?私は人々が同様の問題を抱えていたstackoverflowのいくつかの記事を読んで、新しいソケットを使って修正しました。新しいソケットでhttpリクエストを作成するにはどうしたらいいですか?3Gと無線LANを切り替えるとAndroid Socketエラーが発生する
CODE:
class HttpRunnable implements Runnable
{
private HttpRequestNotification request = null;
public HttpRunnable(HttpRequestNotification req)
{
request = req;
}
public void run()
{
HttpURLConnection conn = null;
try {
System.out.println(request.url);
conn = (HttpURLConnection)(new URL(request.url)).openConnection();
conn.setInstanceFollowRedirects(false);
conn.setRequestMethod(request.verb);
conn.setReadTimeout(20000);
conn.setConnectTimeout(20000);
// If the request contains an explicit auth token, replace our cached copy
if (request.authToken != null && request.authToken.length() > 0)
authorizationToken = request.authToken;
// Add the authorization token, if we have it
if (authorizationToken != null && authorizationToken.length() > 0)
{
conn.setRequestProperty("Authorization", authorizationToken);
}
if (request.postData != null && request.postData.length > 0)
{ // Let the connection know we'll be posting data
conn.addRequestProperty("Content-Type", "application/xml");
conn.setDoOutput(true);
}
conn.connect();
if (request.postData != null && request.postData.length > 0)
{ // Write POST data, if necessary
OutputStream os = conn.getOutputStream();
os.write(request.postData);
os.close();
}
// Grab input stream. If it hasn't occurred already, this will send the Http request over the wire.
InputStream inputStream = conn.getInputStream();
// Save off statusCode, statusMessage, headers
request.statusCode = conn.getResponseCode();
request.statusMessage = conn.getResponseMessage();
Map hdrs = conn.getHeaderFields();
Iterator iter = hdrs.keySet().iterator();
while (iter.hasNext())
{
String key = (String) iter.next();
String val = conn.getHeaderField(key);
if (key != null && val != null)
{
if (key.equalsIgnoreCase("location"))
request.url = val;
request.headers.put(key, val);
}
}
// Extract the message body. We used to extract the content-length header & only
// read that amount of bytes, but we found that sometimes the header is missing.
// Specifically, we found that requests lacked a content-length header in these cases:
// 1) for HTTP 1.1 requests that provide a "transfer-encoding: chunked" header instead
// 2) When running on certain carriers, we found the content-length header to be unreliable
// (DroidX running over Verizon -- full response body was there, but the content-length
// field was waaaay too small.
// To handle all of these cases, we simply read until the end of the stream is reached, then
// convert the result to a byte array. See defect 14288 (over WiFi, some android devices
// return Content-Length; over 3G, they may use transfer-encoding).
ByteArrayOutputStream baos = new ByteArrayOutputStream(10*1024); // This size is an initial size, not max size
while (true)
{
int data = inputStream.read();
if (data < 0)
break;
baos.write(data);
}
request.responseData = baos.toByteArray();
// Extract the auth token, if it's present
if (authorizationToken == null && request.url.endsWith("authenticate") &&
request.statusCode >= 200 && request.statusCode < 300)
{
String authToken = conn.getHeaderField("X-Authorization-Token");
if (authToken != null && authToken.length() > 0)
request.authToken = authorizationToken = authToken;
}
if (request.statusCode >= 200 && request.statusCode < 400)
{
request.onSuccess();
}
else
{
// Note -- this check is included here as well as below for future-proofing. Note that currently
// the J2SE implementation of HttpConnection will throw an IOException if the resopnse code
// is not in the 200-299 range.
if (request.statusCode == HttpURLConnection.HTTP_UNAUTHORIZED &&
!UserAuthService.HttpRequestNotification_Login.class.isInstance(request))
{ // Got a 401 Unauthorized. Since this is not a login request, we want to transition
// the user back to the login screen.
LoginOrchestrator.getInstance().logout();
}
else
request.onError(request.statusCode, "");
}
}
catch (IOException e)
{
try
{
if (conn != null)
{
request.statusCode = conn.getResponseCode();
request.statusMessage = conn.getResponseMessage();
}
}
catch (IOException ex) {}
// Have to check for this HTTP_UNAUTHRORIZED case here as well -- the J2SE HttpConnection
// throws an IOException when the status code is not in the 200-299 range.
if (request.statusCode == HttpURLConnection.HTTP_UNAUTHORIZED &&
!UserAuthService.HttpRequestNotification_Login.class.isInstance(request))
{ // Got a 401 Unauthorized. Since this is not a login request, we want to transition
// the user back to the login screen.
LoginOrchestrator.getInstance().logout();
}
else
request.onError(request.statusCode, e.toString() + ": " + e.getMessage());
}
System.out.flush();
}
}
org.apache.http.client.HttpClientを使用していますか? –
java.net.HttpURLConnection; – spentak