我需要可靠地检测设备是否具有完整的互联网访问权限,即用户不限于强制门户(也称为围墙花园),即有限的子网,它强制用户在表单上提交他们的凭据以获得完全访问权限。
我的应用程序正在自动执行身份验证过程,因此在开始登录 Activity 之前了解无法完全访问互联网非常重要。
问题不是关于如何检查网络接口(interface)是否已启动并处于连接状态。这是为了确保设备具有不受限制的互联网访问权限,而不是沙盒内网段。
到目前为止我尝试过的所有方法都失败了,因为连接到任何知名主机都不会引发异常,而是返回有效的 HTTP 200
响应代码,因为所有请求都被路由到登录页面。
这是我尝试过的所有方法,但由于上述原因,它们都返回 true
而不是 false
:
1:
InetAddress.getByName(host).isReachable(TIMEOUT_IN_MILLISECONDS);
isConnected = true; <exception not thrown>
2:
Socket socket = new Socket();
SocketAddress sockaddr = new InetSocketAddress(InetAddress.getByName(host), 80);
socket.connect(sockaddr, pingTimeout);
isConnected = socket.isConnected();
3:
URL url = new URL(hostUrl));
URLConnection urlConn = url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection) urlConn;
httpConn.setAllowUserInteraction(false);
httpConn.setRequestMethod("GET");
httpConn.connect();
responseCode = httpConn.getResponseCode();
isConnected = responseCode == HttpURLConnection.HTTP_OK;
那么,如何确保我连接到实际主机而不是登录重定向页面?显然,我可以从我使用的“ping”主机检查实际响应正文,但它看起来不是一个合适的解决方案。
最佳答案
作为引用,这里是来自 Android 4.0.1 AOSP 代码库的“官方”方法: WifiWatchdogStateMachine.isWalledGardenConnection() .我将下面的代码包括在内,以防万一将来链接断开。
private static final String mWalledGardenUrl = "http://clients3.google.com/generate_204";
private static final int WALLED_GARDEN_SOCKET_TIMEOUT_MS = 10000;
private boolean isWalledGardenConnection() {
HttpURLConnection urlConnection = null;
try {
URL url = new URL(mWalledGardenUrl); // "http://clients3.google.com/generate_204"
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setInstanceFollowRedirects(false);
urlConnection.setConnectTimeout(WALLED_GARDEN_SOCKET_TIMEOUT_MS);
urlConnection.setReadTimeout(WALLED_GARDEN_SOCKET_TIMEOUT_MS);
urlConnection.setUseCaches(false);
urlConnection.getInputStream();
// We got a valid response, but not from the real google
return urlConnection.getResponseCode() != 204;
} catch (IOException e) {
if (DBG) {
log("Walled garden check - probably not a portal: exception "
+ e);
}
return false;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
}
这种方法依赖于一个特定的 URL,mWalledGardenUrl = "http://clients3.google.com/generate_204"
总是返回一个 204
响应代码。即使 DNS 受到干扰,这也会起作用,因为在这种情况下,将返回 200
代码而不是预期的 204
。我看到一些强制门户网站欺骗了对这个特定 URL 的请求,以防止在 Android 设备上显示 Internet 无法访问 消息。
Google 有这个主题的变体:获取 http://www.google.com/blank.html
将返回一个具有零长度响应的 200
代码 body 。所以如果你得到一个非空的 body ,这将是另一种判断你在围墙花园后面的方法。
Apple 有自己的 URL 来检测强制门户:当网络启动时,IOS 和 MacOS 设备将连接到像 http://www.apple.com/library/test/success.html 这样的 URL , http://attwifi.apple.com/library/test/success.html , 或 http://captive.apple.com/hotspot-detect.html它必须返回 200
的 HTTP 状态代码和包含 Success
的正文。
NOTE: This approach will not work in areas with regionally restricted Internet access such as China where the whole country is a walled garden, and where some Google/Apple services might be blocked. Some of these might not be blocked:
http://www.google.cn/generate_204
,http://g.cn/generate_204
,http://gstatic.com/generate_204
orhttp://connectivitycheck.gstatic.com/generate_204
— yet these all belong to google so not guaranteed to work.
关于android - 如何检查不受限制的 Internet 访问? (强制门户检测),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13958614/