Android 检测是否连接互联网(英特网)
文章转载自:http://www.xwdoor.net/android-test-is-connected-to-the-internet-internet/
如今开发的app
没有不用到网络的,所以对当前网络状态的准确把控就尤为重要了。经常有这样的场景:获取手机当前网络类型、是否连接Wi-Fi、是否能够访问外网(英特网)。今天我们要说的就是如何判断手机是否能够与服务器通信。
Note: 本文所有代码均是基于kotlin
语言实现
1.错误方法
在写代码前,先在网上搜索了主流的解决方案,发现大家都是前篇一律的思路:使用NetworkInfo
中的一个状态(State
)是否是连接状态来判断,但是结果是残酷的,该方法是用来判断是否连接了Wi-Fi,并不能表示手机连接了互联网。不过我也把代码贴出来,供大家参考:
http://www.xwdoor.net/android-test-is-connected-to-the-internet-internet/
2.正确方法
权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
方案一:ping
服务器地址(简单)
通过ping
命令的返回结果来得知是否连接外网,现在主流有效的方法均是这个原理,只是大部分都是ping
的百度的地址,这里推荐使用8.8.8.8
,示例代码如下:
http://www.xwdoor.net/android-test-is-connected-to-the-internet-internet/
PS:8.8.8.8
是一个dns
服务器地址,是Google
提供的免费DNS
服务器的IP
地址。
这个方案的优点是:
- 可以运行在主线程,且是同步的
- 速度快
缺点也有:
- 在一些老的手机上并不起效,比如
Galaxy S3
,原因是跟手机的OEM
有关,具体原因可以参考:Why does ping works on some devices and not others?
方案二:连接服务器端口(推荐)
使用socket
连接服务器的一个端口,并通过连接的结果来判断手机是否连接外网,推荐使用该方法,因为该方法适用于所有的手机Android
版本,示例代码如下:
fun isOnline() = try {
val timeoutMs = 1500
Socket().use {
//连接的端口不同,网络协议不同。 DNS:53;HTTP:80
val socketAddr = InetSocketAddress("8.8.8.8", 53)
it.connect(socketAddr, timeoutMs)
}
true
} catch (e: Throwable) {
false
}
优点:
- 速度快,非常快
- 方法通吃,没有烦人的版本适配
缺点:
- 不能在主线程中运行
方案三:根据域名获取IP
(推荐)
使用InetAddress
提供的方法getByName()
获取某个域名的IP
地址,然后根据是否获取的成功来判断是否连接外网。推荐使用该方法。
http://www.xwdoor.net/android-test-is-connected-to-the-internet-internet/
优点:
- 速度快,超时可自定义
- 可运行在主线程
- 各个版本通吃
缺点:
- 暂无
3.总结
其实以上有效的三个方案的思路都是一样的:
- 进行一次网络访问(必须访问公网的一个地址,无论是域名或者
IP
地址) - 根据网络返回的结果进行实际判断
参考: