美文网首页
iOS获取设备的网络状态(已适配iOS13)【转】

iOS获取设备的网络状态(已适配iOS13)【转】

作者: 小船2022 | 来源:发表于2022-10-26 09:52 被阅读0次

    前言

    小编最近在项目中遇到了一个问题,除刘海屏以外的iOS设备可以正常的搜索到硬件设备,但是刘海屏就不行。因此,小编花了一点时间研究了一下iOS设备获取当前设备的网络状态。

    实现

    因为iOS的系统是封闭的,所以是没有直接的APi去获取当前的网络状态。但是道高一尺,魔高一尺。开发者总会有办法获取自己想要的东西。

    1.网络状态获取

    获取当前的网络类型

    获取当前的网络类型是通过获取状态栏,然后遍历状态栏的视图完成的。

    先导入头文件,如下:

    #import"AppDelegate.h"

    实现方法如下:

    +(NSString*)getNetworkType{UIApplication*app=[UIApplication sharedApplication];id statusBar=nil;//    判断是否是iOS 13NSString*network=@"";if(@available(iOS13.0,*)){UIStatusBarManager*statusBarManager=[UIApplication sharedApplication].keyWindow.windowScene.statusBarManager;#pragmaclang diagnostic push#pragmaclang diagnostic ignored "-Wundeclared-selector"if([statusBarManager respondsToSelector:@selector(createLocalStatusBar)]){UIView*localStatusBar=[statusBarManager performSelector:@selector(createLocalStatusBar)];if([localStatusBar respondsToSelector:@selector(statusBar)]){statusBar=[localStatusBar performSelector:@selector(statusBar)];}}#pragmaclang diagnostic popif(statusBar){//            UIStatusBarDataCellularEntryid currentData=[[statusBar valueForKeyPath:@"_statusBar"]valueForKeyPath:@"currentData"];id _wifiEntry=[currentData valueForKeyPath:@"wifiEntry"];id _cellularEntry=[currentData valueForKeyPath:@"cellularEntry"];if(_wifiEntry&&[[_wifiEntry valueForKeyPath:@"isEnabled"]boolValue]){//                If wifiEntry is enabled, is WiFi.network=@"WIFI";}elseif(_cellularEntry&&[[_cellularEntry valueForKeyPath:@"isEnabled"]boolValue]){NSNumber*type=[_cellularEntry valueForKeyPath:@"type"];if(type){switch(type.integerValue){case0://                            无sim卡network=@"NONE";break;case1:network=@"1G";break;case4:network=@"3G";break;case5:network=@"4G";break;default://                            默认WWAN类型network=@"WWAN";break;}}}}}else{statusBar=[app valueForKeyPath:@"statusBar"];if([[[selfalloc]init]isLiuHaiScreen]){//            刘海屏id statusBarView=[statusBar valueForKeyPath:@"statusBar"];UIView*foregroundView=[statusBarView valueForKeyPath:@"foregroundView"];NSArray*subviews=[[foregroundView subviews][2]subviews];if(subviews.count==0){//                    iOS 12id currentData=[statusBarView valueForKeyPath:@"currentData"];id wifiEntry=[currentData valueForKey:@"wifiEntry"];if([[wifiEntry valueForKey:@"_enabled"]boolValue]){network=@"WIFI";}else{//                    卡1:id cellularEntry=[currentData valueForKey:@"cellularEntry"];//                    卡2:id secondaryCellularEntry=[currentData valueForKey:@"secondaryCellularEntry"];if(([[cellularEntry valueForKey:@"_enabled"]boolValue]|[[secondaryCellularEntry valueForKey:@"_enabled"]boolValue])==NO){//                            无卡情况network=@"NONE";}else{//                            判断卡1还是卡2BOOL isCardOne=[[cellularEntry valueForKey:@"_enabled"]boolValue];intnetworkType=isCardOne?[[cellularEntry valueForKey:@"type"]intValue]:[[secondaryCellularEntry valueForKey:@"type"]intValue];switch(networkType){case0://无服务                                    network=[NSString stringWithFormat:@"%@-%@",isCardOne?@"Card 1":@"Card 2",@"NONE"];break;case3:network=[NSString stringWithFormat:@"%@-%@",isCardOne?@"Card 1":@"Card 2",@"2G/E"];break;case4:network=[NSString stringWithFormat:@"%@-%@",isCardOne?@"Card 1":@"Card 2",@"3G"];break;case5:network=[NSString stringWithFormat:@"%@-%@",isCardOne?@"Card 1":@"Card 2",@"4G"];break;default:break;}}}}else{for(id subviewinsubviews){if([subview isKindOfClass:NSClassFromString(@"_UIStatusBarWifiSignalView")]){network=@"WIFI";}elseif([subview isKindOfClass:NSClassFromString(@"_UIStatusBarStringView")]){network=[subview valueForKeyPath:@"originalText"];}}}}else{//                非刘海屏UIView*foregroundView=[statusBar valueForKeyPath:@"foregroundView"];NSArray*subviews=[foregroundView subviews];for(id subviewinsubviews){if([subview isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")]){intnetworkType=[[subview valueForKeyPath:@"dataNetworkType"]intValue];switch(networkType){case0:network=@"NONE";break;case1:network=@"2G";break;case2:network=@"3G";break;case3:network=@"4G";break;case5:network=@"WIFI";break;default:break;}}}}}if([network isEqualToString:@""]){network=@"NO DISPLAY";}returnnetwork;}

    获取当前的Wifi信息

    获取当前的Wifi信息需要借助系统的SystemConfiguration这个库。

    先导入头文件,如下:

    #import

    实现方法如下:

    #pragmamark 获取Wifi信息+(id)fetchSSIDInfo{NSArray*ifs=(__bridge_transfer id)CNCopySupportedInterfaces();id info=nil;for(NSString*ifnaminifs){info=(__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);if(info&&[info count]){break;}}returninfo;}#pragmamark 获取WIFI名字+(NSString*)getWifiSSID{return(NSString*)[selffetchSSIDInfo][@"SSID"];}#pragmamark 获取WIFI的MAC地址+(NSString*)getWifiBSSID{return(NSString*)[selffetchSSIDInfo][@"BSSID"];}

    获取当前的Wifi信号强度

    获取信号强度与获取网络状态有点类似,通过遍历状态栏,从而获取WIFI图标的信号强度。在获取前需注意当前状态是否为WIFI。如下:

    +(int)getWifiSignalStrength{intsignalStrength=0;//    判断类型是否为WIFIif([[selfgetNetworkType]isEqualToString:@"WIFI"]){//        判断是否为iOS 13if(@available(iOS13.0,*)){UIStatusBarManager*statusBarManager=[UIApplication sharedApplication].keyWindow.windowScene.statusBarManager;id statusBar=nil;#pragmaclang diagnostic push#pragmaclang diagnostic ignored "-Wundeclared-selector"if([statusBarManager respondsToSelector:@selector(createLocalStatusBar)]){UIView*localStatusBar=[statusBarManager performSelector:@selector(createLocalStatusBar)];if([localStatusBar respondsToSelector:@selector(statusBar)]){statusBar=[localStatusBar performSelector:@selector(statusBar)];}}#pragmaclang diagnostic popif(statusBar){id currentData=[[statusBar valueForKeyPath:@"_statusBar"]valueForKeyPath:@"currentData"];id wifiEntry=[currentData valueForKeyPath:@"wifiEntry"];if([wifiEntry isKindOfClass:NSClassFromString(@"_UIStatusBarDataIntegerEntry")]){//                    层级:_UIStatusBarDataNetworkEntry、_UIStatusBarDataIntegerEntry、_UIStatusBarDataEntrysignalStrength=[[wifiEntry valueForKey:@"displayValue"]intValue];}}}else{UIApplication*app=[UIApplication sharedApplication];id statusBar=[app valueForKey:@"statusBar"];if([[[selfalloc]init]isLiuHaiScreen]){//                刘海屏id statusBarView=[statusBar valueForKeyPath:@"statusBar"];UIView*foregroundView=[statusBarView valueForKeyPath:@"foregroundView"];NSArray*subviews=[[foregroundView subviews][2]subviews];if(subviews.count==0){//                    iOS 12id currentData=[statusBarView valueForKeyPath:@"currentData"];id wifiEntry=[currentData valueForKey:@"wifiEntry"];signalStrength=[[wifiEntry valueForKey:@"displayValue"]intValue];//                    dBm//                    int rawValue = [[wifiEntry valueForKey:@"rawValue"] intValue];}else{for(id subviewinsubviews){if([subview isKindOfClass:NSClassFromString(@"_UIStatusBarWifiSignalView")]){signalStrength=[[subview valueForKey:@"_numberOfActiveBars"]intValue];}}}}else{//                非刘海屏UIView*foregroundView=[statusBar valueForKey:@"foregroundView"];NSArray*subviews=[foregroundView subviews];NSString*dataNetworkItemView=nil;for(id subviewinsubviews){if([subview isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView")class]]){dataNetworkItemView=subview;break;}}signalStrength=[[dataNetworkItemView valueForKey:@"_wifiStrengthBars"]intValue];returnsignalStrength;}}}returnsignalStrength;}

    2.Reachability的使用

    下载开源类Reachability,然后根据文档使用即可(该类把移动网络统称为WWAN):

    +(NSString*)getNetworkTypeByReachability{NSString*network=@"";switch([[Reachability reachabilityForInternetConnection]currentReachabilityStatus]){caseNotReachable:network=@"NONE";break;caseReachableViaWiFi:network=@"WIFI";break;caseReachableViaWWAN:network=@"WWAN";break;default:break;}if([network isEqualToString:@""]){network=@"NO DISPLAY";}returnnetwork;}

    上次发布了这篇文章之后,有人问我,怎么才能获取设备的IP地址呢?在这里,小编附上获取iP地址的方法。

    先导入头文件,如下:

    #import#import

    实现方法,如下:

    #pragma mark 获取设备IP地址+(NSString*)getIPAddress{NSString*address=@"error";structifaddrs*interfaces=NULL;structifaddrs*temp_addr=NULL;int success=0;// 检索当前接口,在成功时,返回0success=getifaddrs(&interfaces);if(success==0){// 循环链表的接口temp_addr=interfaces;while(temp_addr!=NULL){//                开热点时本机的IP地址if([[NSString stringWithUTF8String:temp_addr->ifa_name]isEqualToString:@"bridge100"]){address=[NSString stringWithUTF8String:inet_ntoa(((structsockaddr_in*)temp_addr->ifa_addr)->sin_addr)];}if(temp_addr->ifa_addr->sa_family==AF_INET){// 检查接口是否en0 wifi连接在iPhone上if([[NSString stringWithUTF8String:temp_addr->ifa_name]isEqualToString:@"en0"]){// 得到NSString从C字符串address=[NSString stringWithUTF8String:inet_ntoa(((structsockaddr_in*)temp_addr->ifa_addr)->sin_addr)];}}temp_addr=temp_addr->ifa_next;}}// 释放内存freeifaddrs(interfaces);returnaddress;}

    3.iOS 12下的补充

    在iOS 12下xcode需要打开权限才可以正常操作,如下:

    image

    4.iOS 13下的补充

    在iOS 13下xcode需要打开权限才可以正常操作,如下:

    image

    image

    并且,在iOS 13下,若要获取SSID和BSSID,需要添加定位权限

    image

    #import@interfaceViewController()@property(strong,nonatomic)CLLocationManager*locationManager;@end@implementationViewController-(void)viewDidLoad{[superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.if(@available(iOS13.0,*)){//        如果是iOS13 未开启地理位置权限 需要提示一下if([CLLocationManager authorizationStatus]==kCLAuthorizationStatusNotDetermined){self.locationManager=[[CLLocationManager alloc]init];[self.locationManager requestWhenInUseAuthorization];}}}

    到这里为止,这篇文章就结束了。在这里提醒一下各位看官,横屏时请注意不要把状态栏去掉。有说明不足的地方欢迎评论,这里附上Demo下载地址:Demo。最后,希望这篇文章对各位看官们有所帮助。对支持小编的看官们表示感谢。

    参考链接:https://wenku.baidu.com/view/0cc38fdeadaad1f34693daef5ef7ba0d4a736d10.html

    相关文章

      网友评论

          本文标题:iOS获取设备的网络状态(已适配iOS13)【转】

          本文链接:https://www.haomeiwen.com/subject/mmgtartx.html