iOS获取网络类型的方法汇总
Reachability类只能区分WIFI和WWAN类型,却无法区分2G网和3G网。
网上也有些方法,却都存在Bug。
经过网上查找资料和测试,基本上总结了以下几种方法:
1、使用导航栏的方式:(私有API)
代码:
typedefenum{ NetWorkType_None=0, NetWorkType_WIFI, NetWorkType_2G, NetWorkType_3G, }NetWorkType;
UIApplication*application=[UIApplicationsharedApplication]; NSArray*subviews=[[[applicationvalueForKey:@"statusBar"]valueForKey:@"foregroundView"]subviews]; NSNumber*dataNetWorkItemView=nil; for(idsubViewinsubviews){ if([subViewisKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView")class]]){ dataNetWorkItemView=subView; break; } } NetWorkTypenetworkType=NetWorkType_None; switch([[dataNetWorkItemViewvalueForKey:@"dataNetworkType"]integerValue]){ case0: NSLog(@"Nowifiorcellular"); networkType=NetWorkType_None; break; case1: NSLog(@"2G"); networkType=NetWorkType_2G; break; case2: NSLog(@"3G"); networkType=NetWorkType_3G; break; default: NSLog(@"Wifi"); networkType=NetWorkType_WIFI; break; } returnnetworkType;
使用这种方法要确保导航栏没有被隐藏,如果导航栏被隐藏则取不到值。另外,该方法存在Bug,通过Reachability类,在网络类型发生改变时,再执行该代码,获取的网络类型数据没有更新。如果程序进入后台再转到前台,重新执行该代码时,便可以重新获取最新的网络类型数据。这样用户体验不好,当用户在移动中,网络类型发生改变,无法获取最新的网络类型,则页面数据无法更新。(PS:如果哪位大神知道,有什么方法可以刷新数据值,望不吝赐教,感谢!)
2、通过SCNetworkReachability类
代码:
structsockaddr_inzeroAddress; bzero(&zeroAddress,sizeof(zeroAddress)); zeroAddress.sin_len=sizeof(zeroAddress); zeroAddress.sin_family=AF_INET; SCNetworkReachabilityRefdefaultRouteReachability=SCNetworkReachabilityCreateWithAddress(NULL,(structsockaddr*)&zeroAddress);//创建测试连接的引用: SCNetworkReachabilityFlagsflags; SCNetworkReachabilityGetFlags(defaultRouteReachability,&flags); if((flags&kSCNetworkReachabilityFlagsReachable)==0) { returnNetWorkType_None; } NetWorkTyperetVal=NetWorkType_None; if((flags&kSCNetworkReachabilityFlagsConnectionRequired)==0) { retVal=NetWorkType_WIFI; } if((((flags&kSCNetworkReachabilityFlagsConnectionOnDemand)!=0)|| (flags&kSCNetworkReachabilityFlagsConnectionOnTraffic)!=0)) { if((flags&kSCNetworkReachabilityFlagsInterventionRequired)==0) { retVal=NetWorkType_WIFI; } } if((flags&kSCNetworkReachabilityFlagsIsWWAN)==kSCNetworkReachabilityFlagsIsWWAN) { if((flags&kSCNetworkReachabilityFlagsReachable)==kSCNetworkReachabilityFlagsReachable){ if((flags&kSCNetworkReachabilityFlagsTransientConnection)==kSCNetworkReachabilityFlagsTransientConnection){ retVal=NetWorkType_3G; if((flags&kSCNetworkReachabilityFlagsConnectionRequired)==kSCNetworkReachabilityFlagsConnectionRequired){ retVal=NetWorkType_2G; } } } } returnretVal;
这种方法跟Reachability的方法相同,也无法区分2G网和3g网,但是网上有人测试可以区分,如果有人知道原因,希望指正,谢谢!
3、使用SoftwareUpdateService.framework(私有API)
准备工作:
导出生成私有API的头文件声明
使用私有或未公开的API,首先需要导出其对应的头文件,在头文件里有相关函数的声明。
工具:
class-dump
class-dump可以从编译后的Objective-C的二进制文件中提取对应的数据结构及函数等声明。
使用方法:
为了能在任意目录下使用class-dump命令,首先建议把class-dump文件拷贝到/user/local/bin/目录下,然后就可以在任意目录下执行以下命令:
class-dump/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.0.sdk/System/Library/Frameworks/SoftwareUpdateServices.framework/>SUKit.h
但是bulidsetting设置framework的searchpath时要设置真实的私有库路径,因为我们要用它的可执行文件,只有头文件是不行的。
代码:
NSBundle*b=[NSBundlebundleWithPath:@"/System/Library/PrivateFrameworks/SoftwareUpdateServices.framework"]; if([bload]){ //loadClassfromSTRING SUNetworkMonitor*networkMonitor=[SUNetworkMonitorsharedInstance]; intnetType=[networkMonitorcurrentNetworkType]; NetWorkTypenetworkType=NetWorkType_None; switch(netType){ case0: NSLog(@"Nowifiorcellular"); networkType=NetWorkType_None; break; case1: NSLog(@"WIFI"); networkType=NetWorkType_WIFI; break; case2: NSLog(@"2G"); networkType=NetWorkType_2G; break; case3: NSLog(@"3G"); networkType=NetWorkType_3G; break; default: break; }<br> returnnetworkType; } returnNetWorkType_None;
这种方法可以获取网络类型,并且在网络类型改变时,获取最新的网络类型。目前还没有发现Bug,只是准备阶段的工作比较麻烦。
4、最后一种方法,就是利用IOS7系统自带的API获取。只是,IOS7以下的系统版本需要上述的方法获取网络类型。
以上所述就是本文的全部内容了,希望大家能够喜欢。