前戏
苹果iOS 14针对本地局域做了一些权限限制,详情见链接:https://developer.apple.com/videos/play/wwdc2020/10110/
wwdc翻译过来凑字数的
什么是本地网络?
这里的本地网络其实就是我们常说的局域网,是将设备接入路由器以后形成的网络,设备可以通过这张网络互相通信,如我们的设备发现、设备绑定、局域网优先等功能都是使用的本地网络。
从 iOS 13 开始,应用想要获得当前连接到的 Wi-Fi 名称,那就必须要获得定位权限。因为通过识别 Wi-Fi 名称, 应用就能轻松地在你和周围的人之间建立大数据网络。但是不给定位权限不代表应用就没有办法跟踪你了,因为应用可以通过本地网络里的设备进行跟踪。
为什么需要向用户申请权限?
和iOS 13获取WiFi名称需要通过定位权限类似,苹果加强了对用户隐私安全权限,这里也是类似的问题。在过去的 iOS 版本中,应用可以随意扫描本地网络中的设备,因此应用就可以很轻松地得到本地网络里所有设备的名称和 MAC 地址。MAC 地址是一种确认网络设备位置的地址,每个网卡都有一个唯一的 MAC 地址,加上 MAC 地址也具有唯一性,设备厂商会按照一定的规律分配 MAC,所以不同的局域网都是独一无二可以识别的。比方说,你从线下渠道买了个新相机,拍完照片利用相机自带的 Wi-Fi 将照片导入到手机上。这时候带有某个推广模块的应用对局域网发起了一次扫描,识别到了一个新的设备,推广模块会将相机的 MAC 地址上传了云端,进行简单的识别对比以后,很容易知道这个 MAC 地址属于相机。这样带有推广模块的应用都会在画像里给你加上「相机用户」这样的标签,当你下次打开带有同一个推广模块的购物应用时,你就会看到推荐了一堆和相机有关的东西。
那些应用需要使用本地网络?
- 利用本地网络进行设备发现
- 利用本地网络进行数据传输
- 网络调试工具
影响范围
主要影响无法使用Socket或者Bonjour做一些局域网的发现,数据传输。
对局域网应用如:智能家居类,局域网游戏,网络测试工具等等。本人测试了下其实也没有那么大,因为发现这个开关,App下次启动后可能不会生效,暂时未定位原因。
怎么解决?
相信很多人都很奇怪为什么不整个权限申请或状态查询的接口,在翻了一些资料后发现,居然真的没有。 链接:https://developer.apple.com/forums/tags/wwdc20-10110
很无奈!
大部分应用使用局域一般使用Socket或者Bonjour做一些局域的发现,数据传输。说在调用的时候会出现code:65 desc:no route to host。这是其实就是所谓的无本地网络权限。但是我在测试时发现有时候即使是关掉本地网络权限的开关,也能正常的使用UDP、TCP。简直不敢信!难道iOS 14也会想iOS 13一开始出来一样各种坑满天飞?
这里的思路是
- 通过接口获取本机的IP地址
- 使用(SimplePing)来ping手机的IP
整个流程的大概耗时在0.13-0.2秒之间,大部分在0.17秒左右。可能耗时还能接受。但是不知道某些路由器是否可以设置禁止ping。如果有那就炸裂了。 下面上简单的代码
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. NSDictionary *router = [LDSRouterInfo getRouterInfo]; pinger = [[SimplePing alloc] initWithHostName:router[@"ip"]]; pinger.delegate = self; [self->pinger start]; } - (void)simplePing:(SimplePing *)pinger didStartWithAddress:(NSData *)address { if (timer) { return; } timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_mAIn_queue()); dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC, 0 * NSEC_PER_SEC); dispatch_source_set_event_handler(timer, ^{ [pinger sendPingWithData:nil]; }); dispatch_resume(timer); } - (void)simplePing:(SimplePing *)pinger didSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber { NSLog(@"可以使用局域网"); } - (void)simplePing:(SimplePing *)pinger didFailToSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber error:(NSError *)error { if (error.code == 65) {//no route to host NSLog(@"不可以使用局域网"); } }
友情提示
- 调上面接口可以触发首次启动本地网络权限的系统弹窗
- 不知道某些路由器是否可以设置禁止ping
- 整理流程在iPhone 6sp耗时130-200毫秒之间。平均值在160毫秒左右
- 上面代码未正式上线,本人也在测试中,请酌情使用。