现在百度上搜索到的获取网络信号强度的blog比较纷杂。要么是用私有api;要么太旧,不能在新的操作系统上跑;要么就是得越狱。
我经历过从越狱到非越狱,从iOS7到现在的iOS10,各种版本,都有尝试。现将我的代码贴出来,希望能帮到大家。包括WiFi和蜂窝网络的信号都可以获取。
真机测试环境:iOS10.3.3 iOS9.1(无需越狱)
//检查当前是否连网
- (BOOL)whetherConnectedNetwork
{
//创建零地址,0.0.0.0的地址表示查询本机的网络连接状态
struct sockaddr_storage zeroAddress;//IP地址
bzero(&zeroAddress, sizeof(zeroAddress));//将地址转换为0.0.0.0
zeroAddress.ss_len = sizeof(zeroAddress);//地址长度
zeroAddress.ss_family = AF_INET;//地址类型为UDP, TCP, etc.
// Recover reachability flags
SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
SCNetworkReachabilityFlags flags;
//获得连接的标志
BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
CFRelease(defaultRouteReachability);
//如果不能获取连接标志,则不能连接网络,直接返回
if (!didRetrieveFlags)
{
return NO;
}
//根据获得的连接标志进行判断
BOOL isReachable = flags & kSCNetworkFlagsReachable;
BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
return (isReachable&&!needsConnection) ? YES : NO;
}
//获取网络状态
- (NSString *)getNetworkType {
if (![self whetherConnectedNetwork]) return @"NONE";
UIApplication *app = [UIApplication sharedApplication];
NSArray *subviews = [[[app valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews];
NSString *type = @"NONE";
for (id subview in subviews) {
if ([subview isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")]) {
int networkType = [[subview valueForKeyPath:@"dataNetworkType"] intValue];
switch (networkType) {
case 0:
type = @"NONE";
break;
case 1:
type = @"2G";
break;
case 2:
type = @"3G";
break;
case 3:
type = @"4G";
break;
case 5:
type = @"WIFI";
break;
}
}
}
return type;
}
//获取网络信号强度(dBm)
- (NSString *)getSignalStrength {
if (![self whetherConnectedNetwork]) return @"";
UIApplication *app = [UIApplication sharedApplication];
NSArray *subviews = [[[app valueForKey:@"statusBar"] valueForKey:@"foregroundView"] subviews];
NSString *dataNetworkItemView = nil;
NSString *signalStrength = @"";
for (id subview in subviews) {
if([subview isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView") class]] && [[self getNetworkType] isEqualToString:@"WIFI"] && ![[self getNetworkType] isEqualToString:@"NONE"]) {
dataNetworkItemView = subview;
signalStrength = [NSString stringWithFormat:@"%@dBm",[dataNetworkItemView valueForKey:@"_wifiStrengthRaw"]];
break;
}
if ([subview isKindOfClass:[NSClassFromString(@"UIStatusBarSignalStrengthItemView") class]] && ![[self getNetworkType] isEqualToString:@"WIFI"] && ![[self getNetworkType] isEqualToString:@"NONE"]) {
dataNetworkItemView = subview;
signalStrength = [NSString stringWithFormat:@"%@dBm",[dataNetworkItemView valueForKey:@"_signalStrengthRaw"]];
break;
}
}
return signalStrength;
}
//获取网络信号强度等级
WiFi是指
蜂窝网络信号是指
可以放在网络信号强度旁,用图片显示,比较直观
- (NSString *)getSignalStrengthBar {
if (![self whetherConnectedNetwork]) return @"";
UIApplication *app = [UIApplication sharedApplication];
NSArray *subviews = [[[app valueForKey:@"statusBar"] valueForKey:@"foregroundView"] subviews];
NSString *dataNetworkItemView = nil;
NSString *signalStrengthBars = @"";
for (id subview in subviews) {
if([subview isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView") class]] && [[self getNetworkType] isEqualToString:@"WIFI"] && ![[self getNetworkType] isEqualToString:@"NONE"]) {
dataNetworkItemView = subview;
signalStrengthBars = [NSString stringWithFormat:@"0%@",[dataNetworkItemView valueForKey:@"_wifiStrengthBars"]];
break;
}
if ([subview isKindOfClass:[NSClassFromString(@"UIStatusBarSignalStrengthItemView") class]] && ![[self getNetworkType] isEqualToString:@"WIFI"] && ![[self getNetworkType] isEqualToString:@"NONE"]) {
dataNetworkItemView = subview;
signalStrengthBars = [NSString stringWithFormat:@"1%@",[dataNetworkItemView valueForKey:@"_signalStrengthBars"]];
break;
}
}
return signalStrengthBars;
}
这里没有申请NetworkExtension框架的使用,也没办法对WiFi进行更进一步的操作,只是对信号强度的获取。毕竟你申请NetworkExtension框架的使用,是要问你为什么搞这个滴,没有合适的理由,也不好过。
使用的时候记得导入<SystemConfiguration/SystemConfiguration.h>,实时监测网络信号强度,放到NSTimer就好,时间间隔,建议1秒。
在这里扯个淡,记得当初在网络上查到可以通过遍历UIStatusBar获取WiFi信号强度,顿时觉得,蜂窝是不是也可以通过这个方式查到,一是因为翻墙Google了很多次相关资料,二是觉得老外干活儿比较规范,就用相关单词,一个单词一个单词的替换_wifiStrengthRaw变量中的wifi,结果还真弄出来了。
还有就是,前公司做的产品比较偏,后期都没有在AppStore上线,都是通过企业账号发布,或者在Cydia上发布越狱,所以不清楚这个可不可以上线AppStore。所以用这个可以上线的话,请留言告诉我,或者告诉大家。
应该是墙内全网首次发布,墙外不清楚,希望转发注明出处,毕竟第一次写blog,谢谢!
网友评论
我这个取到的是nil,真机测试
UIApplication *app = [UIApplication sharedApplication];
//iPhone X兼容导航条获取
NSArray *subviews = @[];
if([[app valueForKeyPath:@"_statusBar"] isKindOfClass:NSClassFromString(@"UIStatusBar_Modern")]) {
subviews = [[[[app valueForKeyPath:@"_statusBar"] valueForKeyPath:@"_statusBar"] valueForKeyPath:@"foregroundView"] subviews];
} else {
subviews = [[[app valueForKeyPath:@"_statusBar"] valueForKeyPath:@"foregroundView"] subviews];
}
这个网络状态是可以获取到的,但是信号强度没有试过,新公司并没有iPhone X的测试机,什么情况可以说一声。理论上应该没有问题。