Android:在应用程序中间切换 3G 到 WIFI = 失去网络连接

Posted

技术标签:

【中文标题】Android:在应用程序中间切换 3G 到 WIFI = 失去网络连接【英文标题】:Android: 3G to WIFI switch while in the middle on the app = loss of network connectivity 【发布时间】:2011-05-19 20:24:54 【问题描述】:

我在使用 HTC Legend (android 2.2) 时遇到了一个恼人的问题。在 Xperia、Galaxy、Nexus 等设备上未发现此问题。

当我在 3G 连接上启动我的应用程序,获取一些数据,然后进入手机设置并启用 WIFI 时,手机会自动获得优于 3G 的 WIFI 连接。问题是,一旦我切换回应用程序,它似乎已经失去了所有网络连接并且无法连接到任何东西。但是,其他应用程序,例如 Web 浏览器,使用新的 Wifi 连接没有问题。从手机外壳 Ping 可以正常工作。

如果我等待的时间足够长(例如 15 分钟),网络堆栈似乎会自动修复,并且我的应用能够再次建立网络连接。当然,这种延迟是不可接受的。

有没有办法以编程方式重新初始化网络堆栈?我每次都新建一个java.net.HttpURLConnection,但是一旦获得了WIFI,它仍然会超时。

谢谢

代码:

byte[] response = null;
    HttpURLConnection connection = null;
    int responseCode = -1;

    // check the cache first
    String readyResponse = ResponseCache.getInstance().get(getUrl());
    if (readyResponse != null) 
        Log.d(LOG_TAG, "Returning CACHED server response for " + getUrl());
        return readyResponse.getBytes();
    

    try 

        URL url = new URL(getUrl());
        Log.i(LOG_TAG, "Sending Request: " + url.toExternalForm());

        connection = (HttpURLConnection) url.openConnection();
        connection.setUseCaches(false);
        connection.setDoOutput(true); 
        connection.setDoInput(true);
        connection.setConnectTimeout(ApplicationConfiguration.HTTP_CONNECT_TIMEOUT);
        connection.setReadTimeout(ApplicationConfiguration.HTTP_READ_TIMEOUT);

        if (BuildType.getHTTPMethod() == BuildType.METHOD_GET)
        
            connection.setRequestMethod("GET");
        
        else
        
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

            String body = getParameters();
            connection.setRequestProperty("Content-Length", Integer.toString(body.length()));

            OutputStreamWriter wr = new OutputStreamWriter(connection.getOutputStream());
            wr.write(getParameters());
            wr.flush(); 
        



        connection.connect();

        responseCode = connection.getResponseCode();

还有堆栈跟踪

E/xxx.yyy.zzz(  927): java.net.SocketTimeoutException: Read timed out
E/xxx.yyy.zzz(  927):  at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.nativeread(Native Method)
E/xxx.yyy.zzz(  927):  at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.access$200(OpenSSLSocketImpl.java:55)
E/xxx.yyy.zzz(  927):  at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream.read(OpenSSLSocketImpl.java:532)
E/xxx.yyy.zzz(  927):  at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.readln(HttpURLConnectionImpl.java:1279)
E/xxx.yyy.zzz(  927):  at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.readServerResponse(HttpURLConnectionImpl.java:1351)
E/xxx.yyy.zzz(  927):  at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.sendRequest(HttpURLConnectionImpl.java:1339)
E/xxx.yyy.zzz(  927):  at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.doRequestInternal(HttpURLConnectionImpl.java:1656)
E/xxx.yyy.zzz(  927):  at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.doRequest(HttpURLConnectionImpl.java:1649)
E/xxx.yyy.zzz(  927):  at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:1374)
E/xxx.yyy.zzz(  927):  at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:117)
E/xxx.yyy.zzz(  927):  at xxx.yyy.zzz.executeRequest(zzz.java:95)

【问题讨论】:

【参考方案1】:

我看到你有一个 SocketTimeoutException,也许你可以捕获这个异常并使用新的套接字连接?

【讨论】:

是的,我的解决方案与您的建议类似,此外,我将 setConnectTimeout() 和 setReadTimeout() 设置为非常低的值,并一直敲击 URL,直到获得有效的套接字。【参考方案2】:

有一个bug that causes the system to reuse old http connections。 将系统属性 http.keepAlive 设置为 false 应该可以解决问题:

System.setProperty("http.keepAlive", "false");

【讨论】:

仅适用于 pre-froyo

以上是关于Android:在应用程序中间切换 3G 到 WIFI = 失去网络连接的主要内容,如果未能解决你的问题,请参考以下文章

如何在单击按钮时在android中从3G切换到2G

AsyncTask 的 Android 下载文件不适用于 3G 仅适用于 Wi-Fi

Android 应用程序在 WIFI 和 3G(无代理)上工作,但在 3G 上不工作(如果分配了代理和端口)

如何在 Android SDK 中启用/禁用 3G/2G

从 WiFi 切换到 3G 时出现网络错误

PC 到 Android 架构选择:蓝牙 X Wi-fi