关于在iOS设备上探测WIFI,3G,GPRS使用情况的细节
2012-05-28 12:41
811 查看
转自:http://blog.csdn.net/devfun/article/details/7365774
由于设计的游戏需要有一些联网请求,但有时候在设备未连接网络的情况下,如果对网络情况不加以判断,则可能造成游戏为了等游戏超时,浪费不必要的时间。
所以在游戏启动时检测一下网络状况是很必要的,而且当玩家的设备连接上网络以后,有一个回调函数也是非常必要的一件事儿,这样可能更方便我们在后台下载数据库等信息。
apple为我们提供了一套范例代码,下面我就来分析一下这段代码。
范例代码地址在:https://developer.apple.com/library/ios/#samplecode/Reachability/Listings/Classes_ReachabilityAppDelegate_m.html#//apple_ref/doc/uid/DTS40007324-Classes_ReachabilityAppDelegate_m-DontLinkElementID_4
范例中包含两部分,一部分是appdelegate,一部分是reachability
以上的部分为具体实现的部分,下面我们再来看在appdelegate里面调用的部分
由于设计的游戏需要有一些联网请求,但有时候在设备未连接网络的情况下,如果对网络情况不加以判断,则可能造成游戏为了等游戏超时,浪费不必要的时间。
所以在游戏启动时检测一下网络状况是很必要的,而且当玩家的设备连接上网络以后,有一个回调函数也是非常必要的一件事儿,这样可能更方便我们在后台下载数据库等信息。
apple为我们提供了一套范例代码,下面我就来分析一下这段代码。
范例代码地址在:https://developer.apple.com/library/ios/#samplecode/Reachability/Listings/Classes_ReachabilityAppDelegate_m.html#//apple_ref/doc/uid/DTS40007324-Classes_ReachabilityAppDelegate_m-DontLinkElementID_4
范例中包含两部分,一部分是appdelegate,一部分是reachability
#import <sys/socket.h> #import <netinet/in.h> #import <netinet6/in6.h> #import <arpa/inet.h> #import <ifaddrs.h> #import <netdb.h> #import <CoreFoundation/CoreFoundation.h> #import "Reachability.h" #define kShouldPrintReachabilityFlags 1 static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment) { #if kShouldPrintReachabilityFlags NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n", (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-',//当前网络为蜂窝网络,即3G或者GPRS (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-',//网络请求地址可达 (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-', (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-', (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-', (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-', (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-', (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-',//该值为一个本地地址 (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-', comment ); #endif } @implementation Reachability static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) { #pragma unused (target, flags) NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback"); NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback"); //We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively // in case someon uses the Reachablity object in a different thread. NSAutoreleasePool* myPool = [[NSAutoreleasePool alloc] init]; Reachability* noteObject = (Reachability*) info; // Post a notification to notify the client that the network reachability changed. [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject]; [myPool release]; } //启动探测网络 - (BOOL) startNotifier { BOOL retVal = NO; SCNetworkReachabilityContext context = {0, self, NULL, NULL, NULL}; //SCNetworkReachabilitySetCallback函数为指定一个target(此处为reachabilityRef,即www.apple.com,在reachabilityWithHostName里设置的) //当设备对于这个target链接状态发生改变时(比如断开链接,或者重新连上),则回调reachabilityCallback函数, if(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context)) { //指定一个runloop给指定的target if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) { retVal = YES; } } return retVal; } //停止网络探测 - (void) stopNotifier { if(reachabilityRef!= NULL) { SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); } } - (void) dealloc { [self stopNotifier]; if(reachabilityRef!= NULL) { CFRelease(reachabilityRef); } [super dealloc]; } //通过域名设定一个目标地址比如www.apple.com + (Reachability*) reachabilityWithHostName: (NSString*) hostName; { Reachability* retVal = NULL; SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]); if(reachability!= NULL) { retVal= [[[self alloc] init] autorelease]; if(retVal!= NULL) { retVal->reachabilityRef = reachability; retVal->localWiFiRef = NO; } } return retVal; } //通过ip地址设定一个目标的地址,可以加端口号,貌似我实验的不太成功 + (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress; { SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress); Reachability* retVal = NULL; if(reachability!= NULL) { retVal= [[[self alloc] init] autorelease]; if(retVal!= NULL) { retVal->reachabilityRef = reachability; retVal->localWiFiRef = NO; } } return retVal; } //检测当前网络能否连上internet + (Reachability*) reachabilityForInternetConnection; { struct sockaddr_in zeroAddress; bzero(&zeroAddress, sizeof(zeroAddress)); zeroAddress.sin_len = sizeof(zeroAddress); zeroAddress.sin_family = AF_INET; return [self reachabilityWithAddress: &zeroAddress]; } //检测当前网络是否能够连上本地wifi + (Reachability*) reachabilityForLocalWiFi; { struct sockaddr_in localWifiAddress; bzero(&localWifiAddress, sizeof(localWifiAddress)); localWifiAddress.sin_len = sizeof(localWifiAddress); localWifiAddress.sin_family = AF_INET; // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0 localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); Reachability* retVal = [self reachabilityWithAddress: &localWifiAddress]; if(retVal!= NULL) { retVal->localWiFiRef = YES; } return retVal; } #pragma mark Network Flag Handling - (NetworkStatus) localWiFiStatusForFlags: (SCNetworkReachabilityFlags) flags { PrintReachabilityFlags(flags, "localWiFiStatusForFlags"); BOOL retVal = NotReachable; if((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect)) { retVal = ReachableViaWiFi; } return retVal; } //通过flags返回当前网络状态 - (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags { PrintReachabilityFlags(flags, "networkStatusForFlags"); if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) { // if target host is not reachable return NotReachable; } BOOL retVal = NotReachable; if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0) { // if target host is reachable and no connection is required // then we'll assume (for now) that your on Wi-Fi retVal = ReachableViaWiFi; } 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 retVal = ReachableViaWiFi; } } if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) { // ... but WWAN connections are OK if the calling application // is using the CFNetwork (CFSocketStream?) APIs. retVal = ReachableViaWWAN; } return retVal; } - (BOOL) connectionRequired; { NSAssert(reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef"); SCNetworkReachabilityFlags flags; if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) { return (flags & kSCNetworkReachabilityFlagsConnectionRequired); } return NO; } //获得当前网络状态 - (NetworkStatus) currentReachabilityStatus { NSAssert(reachabilityRef != NULL, @"currentNetworkStatus called with NULL reachabilityRef"); NetworkStatus retVal = NotReachable; SCNetworkReachabilityFlags flags; if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) { if(localWiFiRef) { retVal = [self localWiFiStatusForFlags: flags]; } else { retVal = [self networkStatusForFlags: flags]; } } return retVal; } @end
以上的部分为具体实现的部分,下面我们再来看在appdelegate里面调用的部分
- (void) applicationDidFinishLaunching: (UIApplication* )application { #pragma unused(application) contentView.backgroundColor = [UIColor groupTableViewBackgroundColor]; summaryLabel.hidden = YES; //这句是设定一个回调函数reachability,当网络条件发生变化时则去调用reachabilityChanged [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(reachabilityChanged:) name: kReachabilityChangedNotification object: nil]; //Change the host name here to change the server your monitoring remoteHostLabel.text = [NSString stringWithFormat: @"Remote Host: %@", @"www.apple.com"]; //设定target地址,这里是www.apple.com hostReach = [[Reachability reachabilityWithHostName: @"www.apple.com"] retain]; //启动网络条件检测 [hostReach startNotifier]; //更新UI的网络状态显示 [self updateInterfaceWithReachability: hostReach]; //探测是否能连上internet网 internetReach = [[Reachability reachabilityForInternetConnection] retain]; [internetReach startNotifier]; [self updateInterfaceWithReachability: internetReach]; //探测wifi是否开启 wifiReach = [[Reachability reachabilityForLocalWiFi] retain]; [wifiReach startNotifier]; [self updateInterfaceWithReachability: wifiReach]; [window makeKeyAndVisible]; } //如需要查看网络状态,如下调用即可 NetworkStatus netStatus = [curReach currentReachabilityStatus]; netStatus有ReachableViaWWAN(蜂窝网络3G之类的),ReachableViaWiFi(wifi连接),NotReachable(无法连接)
相关文章推荐
- 关于在iOS设备上探测WIFI,3G,GPRS使用情况的细节
- 关于在iOS设备上探测WIFI,3G,GPRS使用情况的细节
- 关于在iOS设备上探测WIFI,3G,GPRS使用情况的细节
- 关于在iOS设备上探测WIFI,3G,GPRS使用情况的细节 .
- 关于在iOS设备上探测WIFI,3G,GPRS使用情况的细节
- 关于在iOS设备上探测WIFI,3G,GPRS使用情况的细节
- 关于iOS 设备贴图使用情况的说明
- Reachability.h 开源类的使用:判断网络环境,连接情况(无网络连接,3G,WIFI,GPRS)
- iOS开发 - 如何获取设备的总容量和可用容量 网络运营商 3g/wifi判断 手机型号
- 关于WinCE下MC55使用Unimodem进行GPRS拨号,拨上出现断开连接,检查波特率的问题的另一种可能情况
- iOS开发 - 如何获取设备的总容量和可用容量 网络运营商 3g/wifi判断 手机型号
- iOS获取设备流量使用情况 iPhone Data Usage Tracking/Monitoring
- 转载:iOS获取设备流量使用情况 iPhone Data Usage Tracking/Monitoring
- iOS设备接入WiFi和3G网络安全性分析 推荐
- iOS获取设备流量使用情况 iPhone Data Usage Tracking/Monitoring
- iOS开发之WIFI,3G/4G两种网络同时使用技巧
- 获取当前ios设备的内存使用情况,获取客户端ip地址
- iOS WIFI连接设备 同时3G/4G上网
- iOS用来获取设备上的网络状态(2G,3G,WIFI...)