我在三星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;
}
感谢阅读。在此先感谢您的帮助。