iOS中如何判断当前网络环境是2G/3G/4G/5G/WiFi
前言
5g 什么的,还得等苹果api更新啊,不过将来还是这个处理过程就是了。
关于判断当前的网络环境是2g/3g/4g,这个问题以前经常看到,最近在一工程里看到了如果判断的api。而在撸webrtc音视频通话的时候,看到了demo中将scnetworkreachability与其结合,当网络环境改变时,判断当前连接的是什么网络环境,写法欠佳(因为将其与webrtc的其他逻辑柔和在了一个类)。其实只需要将官方的reachability做一下改进即可。
如何判断当前的网络环境
我们可以利用#import <coretelephony/cttelephonynetworkinfo.h>框架下的一些api来判断当前的网络。
先来看一下该框架下的一些常量定义:
coretelephony_extern nsstring * const ctradioaccesstechnologygprs __osx_available_starting(__mac_na,__iphone_7_0); coretelephony_extern nsstring * const ctradioaccesstechnologyedge __osx_available_starting(__mac_na,__iphone_7_0); coretelephony_extern nsstring * const ctradioaccesstechnologywcdma __osx_available_starting(__mac_na,__iphone_7_0); coretelephony_extern nsstring * const ctradioaccesstechnologyhsdpa __osx_available_starting(__mac_na,__iphone_7_0); coretelephony_extern nsstring * const ctradioaccesstechnologyhsupa __osx_available_starting(__mac_na,__iphone_7_0); coretelephony_extern nsstring * const ctradioaccesstechnologycdma1x __osx_available_starting(__mac_na,__iphone_7_0); coretelephony_extern nsstring * const ctradioaccesstechnologycdmaevdorev0 __osx_available_starting(__mac_na,__iphone_7_0); coretelephony_extern nsstring * const ctradioaccesstechnologycdmaevdoreva __osx_available_starting(__mac_na,__iphone_7_0); coretelephony_extern nsstring * const ctradioaccesstechnologycdmaevdorevb __osx_available_starting(__mac_na,__iphone_7_0); coretelephony_extern nsstring * const ctradioaccesstechnologyehrpd __osx_available_starting(__mac_na,__iphone_7_0); coretelephony_extern nsstring * const ctradioaccesstechnologylte __osx_available_starting(__mac_na,__iphone_7_0);
这不就是2g/3g/4g等网络环境么?我想等5g普及之后,苹果肯定也会加入代表5g的常量定义的。
先看随手写的一个网络环境判断:
- (void)networkstatus { nsarray *typestrings2g = @[ctradioaccesstechnologyedge, ctradioaccesstechnologygprs, ctradioaccesstechnologycdma1x]; nsarray *typestrings3g = @[ctradioaccesstechnologyhsdpa, ctradioaccesstechnologywcdma, ctradioaccesstechnologyhsupa, ctradioaccesstechnologycdmaevdorev0, ctradioaccesstechnologycdmaevdoreva, ctradioaccesstechnologycdmaevdorevb, ctradioaccesstechnologyehrpd]; nsarray *typestrings4g = @[ctradioaccesstechnologylte]; if ([[[uidevice currentdevice] systemversion] floatvalue] >= 7.0) { cttelephonynetworkinfo *teleinfo= [[cttelephonynetworkinfo alloc] init]; nsstring *accessstring = teleinfo.currentradioaccesstechnology; if ([typestrings4g containsobject:accessstring]) { nslog(@"4g网络"); } else if ([typestrings3g containsobject:accessstring]) { nslog(@"3g网络"); } else if ([typestrings2g containsobject:accessstring]) { nslog(@"2g网络"); } else { nslog(@"未知网络"); } } else { nslog(@"未知网络"); } }
代码中的currentradioaccesstechnology是ios 7之后新加的api。
改进reachability
在ios应用中的使用场景肯定不是主动获取,应该是网络产生变化的时候,自动给出通知等,然后做一些相应的处理。下面我们就自己撸一个reachability,然后给出当前的网络环境。
我们都知道,使用reachability时,如果网络变化,会给出一个通知,但是我们获取的网络状态只有wifi/wwan/notreach几种。我们可以在reachability返回的通知里,wwan这种类型下,再做上面的网络判断即可。但是更优的做法就将判断放在reachability中,在使用的时候直接返回不同的网络状态。
由于最新的reachability已经支持了ipv6,我也是在最新的reachability上做了一些改进。
大部分方法跟reachability一样,我扩展了枚举类型,修改了网络状态判断。
主要修改如下:
typedef ns_enum(nsuinteger, hlnetworkstatus) { hlnetworkstatusnotreachable = 0, hlnetworkstatusunknown = 1, hlnetworkstatuswwan2g = 2, hlnetworkstatuswwan3g = 3, hlnetworkstatuswwan4g = 4, hlnetworkstatuswifi = 9, };
这里是网络类型判断的修改:
- (hlnetworkstatus)networkstatusforflags:(scnetworkreachabilityflags)flags { if ((flags & kscnetworkreachabilityflagsreachable) == 0) { // the target host is not reachable. return hlnetworkstatusnotreachable; } hlnetworkstatus returnvalue = hlnetworkstatusnotreachable; if ((flags & kscnetworkreachabilityflagsconnectionrequired) == 0) { /* if the target host is reachable and no connection is required then we'll assume (for now) that you're on wi-fi... */ returnvalue = hlnetworkstatuswifi; } if ((((flags & kscnetworkreachabilityflagsconnectionondemand ) != 0) || (flags & kscnetworkreachabilityflagsconnectionontraffic) != 0)) { /* ... and the connection is on-demand (or on-traffic) if the calling application is using the cfsocketstream or higher apis... */ if ((flags & kscnetworkreachabilityflagsinterventionrequired) == 0) { /* ... and no [user] intervention is needed... */ returnvalue = hlnetworkstatuswifi; } } if ((flags & kscnetworkreachabilityflagsiswwan) == kscnetworkreachabilityflagsiswwan) { /* ... but wwan connections are ok if the calling application is using the cfnetwork apis. */ nsarray *typestrings2g = @[ctradioaccesstechnologyedge, ctradioaccesstechnologygprs, ctradioaccesstechnologycdma1x]; nsarray *typestrings3g = @[ctradioaccesstechnologyhsdpa, ctradioaccesstechnologywcdma, ctradioaccesstechnologyhsupa, ctradioaccesstechnologycdmaevdorev0, ctradioaccesstechnologycdmaevdoreva, ctradioaccesstechnologycdmaevdorevb, ctradioaccesstechnologyehrpd]; nsarray *typestrings4g = @[ctradioaccesstechnologylte]; if ([[[uidevice currentdevice] systemversion] floatvalue] >= 7.0) { cttelephonynetworkinfo *teleinfo= [[cttelephonynetworkinfo alloc] init]; nsstring *accessstring = teleinfo.currentradioaccesstechnology; if ([typestrings4g containsobject:accessstring]) { return hlnetworkstatuswwan4g; } else if ([typestrings3g containsobject:accessstring]) { return hlnetworkstatuswwan3g; } else if ([typestrings2g containsobject:accessstring]) { return hlnetworkstatuswwan2g; } else { return hlnetworkstatusunknown; } } else { return hlnetworkstatusunknown; } } return returnvalue; }
改进后的reachability用法
为了便于使用,尽量按照reachability的做法来处理,所以用法与之前没什么太大区别,就换了个通知而已。
[[nsnotificationcenter defaultcenter] addobserver:self selector:@selector(reachabilitychanged:) name:knetworkreachabilitychangednotification object:nil]; hlnetworkreachability *reachability = [hlnetworkreachability reachabilitywithhostname:@"www.baidu.com"]; self.hostreachability = reachability; [reachability startnotifier]; // 通知处理 - (void)reachabilitychanged:(nsnotification *)notification { hlnetworkreachability *curreach = [notification object]; hlnetworkstatus netstatus = [curreach currentreachabilitystatus]; switch (netstatus) { case hlnetworkstatusnotreachable: nslog(@"网络不可用"); break; case hlnetworkstatusunknown: nslog(@"未知网络"); break; case hlnetworkstatuswwan2g: nslog(@"2g网络"); break; case hlnetworkstatuswwan3g: nslog(@"3g网络"); break; case hlnetworkstatuswwan4g: nslog(@"4g网络"); break; case hlnetworkstatuswifi: nslog(@"wifi"); break; default: break; } }
完整demo地址:hlnetworkreachability (本地下载)。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。