Android檢測(cè)是否連接互聯(lián)網(wǎng)
如今開(kāi)發(fā)的app沒(méi)有不用到網(wǎng)絡(luò)的,所以對(duì)當(dāng)前網(wǎng)絡(luò)狀態(tài)的準(zhǔn)確把控就尤為重要了。經(jīng)常有這樣的場(chǎng)景:獲取手機(jī)當(dāng)前網(wǎng)絡(luò)類(lèi)型、是否連接Wi-Fi、是否能夠訪問(wèn)外網(wǎng)(英特網(wǎng))。今天我們要說(shuō)的就是如何判斷手機(jī)是否能夠與服務(wù)器通信。
Note: 本文所有代碼均是基于kotlin語(yǔ)言實(shí)現(xiàn)
1.錯(cuò)誤方法
在寫(xiě)代碼前,先在網(wǎng)上搜索了主流的解決方案,發(fā)現(xiàn)大家都是前篇一律的思路:使用NetworkInfo中的一個(gè)狀態(tài)(State)是否是連接狀態(tài)來(lái)判斷,但是結(jié)果是殘酷的,該方法是用來(lái)判斷是否連接了Wi-Fi,并不能表示手機(jī)連接了互聯(lián)網(wǎng)。不過(guò)我也把代碼貼出來(lái),供大家參考:
2.正確方法
權(quán)限:
<uses-permissionandroid:name="android.permission.INTERNET"/><uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/>
方案一:ping服務(wù)器地址(簡(jiǎn)單)通過(guò)ping命令的返回結(jié)果來(lái)得知是否連接外網(wǎng),現(xiàn)在主流有效的方法均是這個(gè)原理,只是大部分都是ping的百度的地址,這里推薦使用8.8.8.8,示例代碼如下:
PS:8.8.8.8是一個(gè)dns服務(wù)器地址,是Google提供的免費(fèi)DNS服務(wù)器的IP地址。
這個(gè)方案的優(yōu)點(diǎn)是:
可以運(yùn)行在主線程,且是同步的
速度快
缺點(diǎn)也有:
在一些老的手機(jī)上并不起效,比如Galaxy S3,原因是跟手機(jī)的OEM有關(guān),具體原因可以參考:Why does ping works on some devices and not others?
方案二:連接服務(wù)器端口(推薦)使用socket連接服務(wù)器的一個(gè)端口,并通過(guò)連接的結(jié)果來(lái)判斷手機(jī)是否連接外網(wǎng),推薦使用該方法,因?yàn)樵摲椒ㄟm用于所有的手機(jī)Android版本,示例代碼如下:
funisOnline() =try{valTImeoutMs =1500Socket().use{//連接的端口不同,網(wǎng)絡(luò)協(xié)議不同。 DNS:53;HTTP:80valsocketAddr = InetSocketAddress("8.8.8.8",53) it.connect(socketAddr, TImeoutMs) }true} catch (e: Throwable) {false}
優(yōu)點(diǎn):
速度快,非???/p>
方法通吃,沒(méi)有煩人的版本適配
缺點(diǎn):
不能在主線程中運(yùn)行
方案三:根據(jù)域名獲取IP(推薦)使用InetAddress提供的方法getByName()獲取某個(gè)域名的IP地址,然后根據(jù)是否獲取的成功來(lái)判斷是否連接外網(wǎng)。推薦使用該方法。
優(yōu)點(diǎn):
速度快,超時(shí)可自定義
可運(yùn)行在主線程
各個(gè)版本通吃
缺點(diǎn):
暫無(wú)
3.總結(jié)其實(shí)以上有效的三個(gè)方案的思路都是一樣的:
進(jìn)行一次網(wǎng)絡(luò)訪問(wèn)(必須訪問(wèn)公網(wǎng)的一個(gè)地址,無(wú)論是域名或者IP地址)
根據(jù)網(wǎng)絡(luò)返回的結(jié)果進(jìn)行實(shí)際判斷