關鍵詞
CocoaAsyncSocket Socket iOS 10 網絡權限彈框
癥狀
昨天,為了可以讓硬件的同事測試 UDP Socket 收發包,所以去寫了一個集成了 CocoaAsyncSocket 可以完成基本持續發包的 Demo 。但是拿同事的手機,一直都沒有看到建立連接-發包成功等等的回調。
然后測試了其他多款不同型號,不同機型的手機,都沒有出現這個問題。
定位問題
- 代理失效?
因為從程序運行的結果直觀的來看,只是沒有回調返回。所以直接入回調方法入手,到GCDAsyncUdpSocket.m
的源碼中打斷點,結果一路單步過來,發現delegate始終都是有的,而且涉及到 Delegate 的方法一直都沒有被調用。 - 網絡錯誤?
在之前在對GCDAsyncUdpSocket.m
的源碼的探究中,了解到它的源碼是由下面幾部分構成
Configuration / Delegate Helpers / Errors / Utilities
Diagnostics / Binding / Connecting / Multicast
Reuse port / Broadcast / Sending / Receiving
Closing / CFStream / Advanced / Class Methods
所以直接從Error部分入手,在每個方法的開始打斷點,當進行發包的時候,發現程序停在了- errnoErrorWithReason:
這個方法里。這個方法中通過 NSString *errMsg = [NSString stringWithUTF8String:strerror(errno)]
這段代碼來獲取錯誤信息,errno
這是什么呢?
- errno
errno 是記錄系統的最后一次錯誤代碼。代碼是一個int型的值,在errno.h中定義。我們可以通過檢查errno這個值,來獲悉系統發生錯誤的原因。在這個庫中,errno值可以讓我們定位到 socket 通信中產生的錯誤。
errno.h這個文件中,宏定義了一部分系統中各種產生的錯誤,并對應著errno的值。
然后查找到errno的值是65,對應的錯誤是no route to host
就是無法進行網絡訪問。
問題原因
因為定位到了問題在于沒有網絡訪問,所以通過 iOS 10 無法訪問網絡
等關鍵詞查到了 大神倉的文章 iOS 10 的坑:新機首次安裝 app,請求網絡權限“是否允許使用數據” 以及其中提到的稀土的一篇講 關于 iOS 10 應用程序網絡請求許可彈窗解決方法的文章。
其中說到了由于大陸相關部門出臺的新規定指出,應用在未經用戶允許的前提下,系統不能授予其使用聯網、獲取定位的功能,所以只有在用戶點擊了彈窗允許訪問網絡的時候,應用程序才能訪問網絡。
然后發現,我拿的這個手機的蜂窩移動數據界面,果然是需要設置應用程序允許訪問網絡
的那款。
系統的BUG
引用掘金的一句話說明一下我遇到的情況...
如果你在 iOS 10 操作系統中安裝了一個新應用或者第一次打開某個應用時發現應用出現無法訪問網絡無法刷新數據的情況,并且在蜂窩數據網絡的設置項中無法找到相應應用的聯網權限設置選項
看了掘金的文章,他們定位的原因是:iOS 10 系統沒有正確地配置網絡權限,所以觸發一下系統的相關設置改動可能能夠重新激活應用的聯網權限請求彈窗
然后又咨詢了一下公司的大神,公司的大神表示看到了很多,基本上直接使用socket通訊是一般是不會觸發聯網權限的。然后查到了** EsptouchForIOS** 程序的issue,里面有這樣的解答。
經過研究發現,ios9直接升級到ios10.0.1的所有應用默認關閉所有網絡權限,ios9直接升級到ios10.0.2的所有應用默認打開所有網絡權限。但是,我們的Esptouch使用的都是底層的Socket函數,未使用Cocoa Touch框架。所以,未向用戶申請Network權限。
然后 Demo 使用的UDPAsyncSocket.h中,使用也是底層的Socket函數。。。
解決方案
于是在 Demo 進行 socket 發包前
- 進行了一次URLSession的請求來觸發網絡權限的彈窗
- 并重置了一下手機的網絡設置。
- Run
Bingo!!!之后就成功的看到了權限彈窗,點擊之后,可以成功發包了
參考鏈接
下面是一些產品碰到這個問題的解決方案,畢竟我這只是一個用于調試 UDP Socket 發包的 Demo。
EsptouchForIOS關于這個問題的解答
iOS 10 不提示「是否允許應用訪問數據」,導致應用無法使用的解決方案
iOS 10 的坑:新機首次安裝 app,請求網絡權限“是否允許使用數據”
ios10網絡權限問題