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以下的系统版本需要上述的方法获取网络类型。
以上所述就是本文的全部内容了,希望大家能够喜欢。