Android HttpRequest结果在三星Galaxy设备上缓存了10分钟

时间:2014-07-22 13:37:22

标签: android caching httprequest samsung-mobile

我在三星Galaxy S3 / S4 / Note2上使用我的Android应用程序的用户存在很大问题。

我的应用程序发送GET请求以检索“http://www.msftncsi.com/ncsi.txt”的内容,以检查在WebView中打开Web表单之前Internet连接是否正常工作。它在大多数设备上运行得非常好,无论如何它在三星设备上有一种奇怪的行为,因为它看起来像是将请求响应存储了10分钟。

因此,如果我在互联网访问失败时发送此请求,那么即使互联网访问得到修复,我也会在10分钟内得到相同的结果(漏报)。 反之亦然:如果我在互联网访问正常时发送请求,那么即使我断开路由器与互联网的连接,我也会在10分钟内收到相同的响应(误报)。

我尝试了这个线程的解决方案(没有工作):How to prevent Android from returning a cached response to my HTTP Request?

重要提示:我无法修改服务器的响应标头。

以下是三星设备上的代码失败:

Logger.d(LOG_TAG, "Starting the thread checking internet access.");
boolean isInternetAccessAvailable = false;
boolean tryAgain = false;

do
{
    try
    {
        HttpClient httpClient = new DefaultHttpClient();

        HttpParams httpParams = httpClient.getParams();
        HttpConnectionParams.setConnectionTimeout(httpParams, mRequestTimeout);
        HttpConnectionParams.setSoTimeout(httpParams, mRequestTimeout);

        HttpClientParams.setRedirecting(httpParams, false);

        HttpGet httpGet = new HttpGet(CHECK_INTERNET_URL);

        HttpResponse httpResponse = httpClient.execute(httpGet);

        if (!mCheckInternetTask.isCancelled())
        {
            Logger.d(LOG_TAG, "Received server response. Start response content parsing.");

            StatusLine statusLine = httpResponse.getStatusLine();
            int statuscode = statusLine.getStatusCode();

            if (statuscode == HttpStatus.SC_OK)
            {
                HttpEntity entity = httpResponse.getEntity();

                if (entity != null)
                {
                    String resultString = null;
                    try
                    {
                        InputStream inputStream = null;
                        inputStream = entity.getContent();
                        resultString = convertStreamToString(inputStream);
                    }
                    catch (IllegalStateException e)
                    {
                        Logger.w(LOG_TAG, "IllegalStateException during HTTP entity conversion into String", e);
                    }
                    catch (IOException e)
                    {
                        Logger.w(LOG_TAG, "IOException during HTTP entity conversion into String", e);
                    }

                    if (resultString != null && resultString.equals("Microsoft NCSI"))
                    {
                        Logger.i(LOG_TAG, "Microsoft NCSI web content reachable: Internet OK.");
                        isInternetAccessAvailable = true;
                    }
                    else
                    {
                        Logger.i(LOG_TAG, "Microsoft NCSI web content not reachable: Internet KO.");
                    }
                }
                else
                {
                    Logger.e(LOG_TAG, "getInternetStatusFromOS() HttpEntity is null !!");
                }

                // Do no try again
                tryAgain = false;
            }
            else if (statuscode == HttpStatus.SC_MOVED_TEMPORARILY)
            {
                Logger.i(LOG_TAG, "Captive portal detected, Internet KO");
            }
            else if (!tryAgain)
            {
                Logger.w(LOG_TAG, "HTTP response code is " + statuscode + ", not 200, try to clear the DNS cache and try again");
                clearDnsCache();
                tryAgain = true;
            }
            else
            {
                Logger.i(LOG_TAG, "HTTP response code is " + statuscode + ", not 200: Internet KO.");

                // Do no try again
                tryAgain = false;
            }
        }
    }
    catch (ConnectTimeoutException e)
    {
        Logger.d(LOG_TAG, "ConnectTimeoutException caught: Internet KO.", e);
    }
    catch (SocketTimeoutException e)
    {
        tryAgain = true;
        Logger.d(LOG_TAG, "SocketTimeoutException caught: Internet KO.", e);
    }
    catch (ClientProtocolException e)
    {
        Logger.d(LOG_TAG, "ClientProtocolException caught: Internet KO.", e);
    }
    catch (IOException e)
    {
        Logger.d(LOG_TAG, "IOException caught: Internet KO.", e);
    }
}
while (tryAgain && !mCheckInternetTask.isCancelled());

if (mCheckInternetTask.isCancelled())
{
    Logger.d(LOG_TAG, "Thread interrupted (timed out).");
}
else
{
    Logger.d(LOG_TAG, "Check Internet access runnable finished, with result: " + isInternetAccessAvailable);
    setCheckInternetAccessResult(isInternetAccessAvailable);
}

我已经在三星Galaxy S2上使用隐藏功能清除dns缓存但它不再起作用在Galaxy S3 / S4 / Note2(可能还有其他Galaxy设备)上排序了这个问题:

/**
 * Try to clear the DNS cache, if necessary.<br/>
 * When starting the application, if the {@value #CHECK_INTERNET_URL} is not reachable, the DNS cache will
 * remember this status for at least 10 minutes. Any request to this URL will return with a 404 error
 * during this period.<br>
 * Two solutions can be found:
 * <ul>
 * <li>Using the <a
 * href="http://docs.oracle.com/javase/6/docs/technotes/guides/net/properties.html#nct">networkaddress
 * .cache.ttl</a> and the <a
 * href="http://docs.oracle.com/javase/6/docs/technotes/guides/net/properties.html#ncnt"
 * >networkaddress.cache.negative.ttl</a> constants.</li>
 * <li>Using the clearDnsCache from the <a href=
 * "https://android.googlesource.com/platform/libcore/+/master/luni/src/main/java/java/net/InetAddress.java"
 * >INetAddress</a> class source code</li>
 * </ul>
 * The first solution doesn't work on the Galaxy SII (the device on which the Internet access detection
 * problem appeared first). The second solutions needs to use a method that is not visible from the code:
 * we will have to use Reflection.
 * 
 * @return true if the clearDnsCache method could be found, and was called.
 */
private boolean clearDnsCache()
{
    boolean success = false;

    try
    {
        Method method = null;
        method = InetAddress.class.getMethod("clearDnsCache");

        if (method != null)
        {
            method.invoke(null);
            success = true;
        }
    }
    catch (SecurityException e)
    {
        Logger.d(LOG_TAG, "SecurityException when trying to call INetAddress#clearDnsCache()", e);
    }
    catch (NoSuchMethodException e)
    {
        Logger.d(LOG_TAG, "NoSuchMethodException when trying to call INetAddress#clearDnsCache()", e);
    }
    catch (IllegalArgumentException e)
    {
        Logger.d(LOG_TAG, "IllegalArgumentException when trying to call INetAddress#clearDnsCache()", e);
    }
    catch (IllegalAccessException e)
    {
        Logger.d(LOG_TAG, "IllegalAccessException when trying to call INetAddress#clearDnsCache()", e);
    }
    catch (InvocationTargetException e)
    {
        Logger.d(LOG_TAG, "InvocationTargetException when trying to call INetAddress#clearDnsCache()", e);
    }

    return success;
}

感谢阅读。在此先感谢您的帮助。

0 个答案:

没有答案