iOS获取网络类型的方法汇总

Reachability类只能区分WIFI和WWAN类型,却无法区分2G网和3G网。

网上也有些方法,却都存在Bug。

经过网上查找资料和测试,基本上总结了以下几种方法:

1、使用导航栏的方式:(私有API)

代码:

代码如下:

typedef enum {
    NetWorkType_None = 0,
    NetWorkType_WIFI,
    NetWorkType_2G,
    NetWorkType_3G,
} NetWorkType;

UIApplication *application = [UIApplication sharedApplication];
NSArray *subviews = [[[application valueForKey:@"statusBar"] valueForKey:@"foregroundView"]subviews];
NSNumber *dataNetWorkItemView = nil;
for (id subView in subviews) {
  if ([subView isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView") class]]) {
      dataNetWorkItemView = subView;
      break;
    }
  }
  NetWorkType networkType = NetWorkType_None;
  switch ([[dataNetWorkItemView valueForKey:@"dataNetworkType"] integerValue]) {
    case 0:
      NSLog(@"No wifi or cellular");
      networkType = NetWorkType_None;
      break;
    case 1:
      NSLog(@"2G");
      networkType = NetWorkType_2G;
      break;
    case 2:
      NSLog(@"3G");
      networkType = NetWorkType_3G;
      break;
    default:
      NSLog(@"Wifi");
      networkType = NetWorkType_WIFI;
      break;
  }
return networkType;   

使用这种方法要确保导航栏没有被隐藏,如果导航栏被隐藏则取不到值。另外,该方法存在Bug,通过Reachability类,在网络类型发生改变时,再执行该代码,获取的网络类型数据没有更新。如果程序进入后台再转到前台,重新执行该代码时,便可以重新获取最新的网络类型数据。这样用户体验不好,当用户在移动中,网络类型发生改变,无法获取最新的网络类型,则页面数据无法更新。(PS:如果哪位大神知道,有什么方法可以刷新数据值,望不吝赐教,感谢!)

2、通过SCNetworkReachability类

代码:

struct sockaddr_in zeroAddress;
 bzero(&zeroAddress, sizeof(zeroAddress));
 zeroAddress.sin_len = sizeof(zeroAddress);
 zeroAddress.sin_family = AF_INET;
 SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress); //创建测试连接的引用:
 SCNetworkReachabilityFlags flags;
 SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
 {
   return NetWorkType_None;
 }
 NetWorkType retVal = 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;
       }
     }
   }
 }
 return retVal;

这种方法跟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的search path 时要设置真实的私有库路径,因为我们要用它的可执行文件,只有头文件是不行的。

代码:

NSBundle *b = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/SoftwareUpdateServices.framework"];
   if ([b load]) {
    // load Class from STRING
   SUNetworkMonitor *networkMonitor = [SUNetworkMonitor sharedInstance];
     int netType = [networkMonitor currentNetworkType];
     NetWorkType networkType = NetWorkType_None;
     switch ( netType ) {
       case 0:
         NSLog(@"No wifi or cellular");
         networkType = NetWorkType_None;
         break;
       case 1:
         NSLog(@"WIFI");
         networkType = NetWorkType_WIFI;
        break;
       case 2:
         NSLog(@"2G");
         networkType = NetWorkType_2G;
        break;
       case 3:
         NSLog(@"3G");
         networkType = NetWorkType_3G;
         break;
       default:
         break;
    }<br>
    return networkType;
  }
  return NetWorkType_None;

这种方法可以获取网络类型,并且在网络类型改变时,获取最新的网络类型。目前还没有发现Bug,只是准备阶段的工作比较麻烦。

4、最后一种方法,就是利用IOS7系统自带的API获取。只是,IOS7以下的系统版本需要上述的方法获取网络类型。

以上所述就是本文的全部内容了,希望大家能够喜欢。

(0)

相关推荐

  • iOS获取当前网络环境的实现方法(推荐)

    实例如下: // 获取网络环境的方法 + (NSString *)networktype{ NSArray *subviews = [[[[UIApplication sharedApplication] valueForKey:@"statusBar"] valueForKey:@"foregroundView"]subviews]; NSNumber *dataNetworkItemView = nil; for (id subview in subviews)

  • iOS获取网络类型的方法汇总

    Reachability类只能区分WIFI和WWAN类型,却无法区分2G网和3G网. 网上也有些方法,却都存在Bug. 经过网上查找资料和测试,基本上总结了以下几种方法: 1.使用导航栏的方式:(私有API) 代码: 复制代码 代码如下: typedef enum {     NetWorkType_None = 0,     NetWorkType_WIFI,     NetWorkType_2G,     NetWorkType_3G, } NetWorkType; UIApplicatio

  • java获取网络类型的方法

    本文实例讲述了java获取网络类型的方法.分享给大家供大家参考.具体如下: /**** * 获取网络类型 * * @param context * @return */ public static String getNetType(Context context) { try { ConnectivityManager connectMgr = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVIC

  • 微信小程序获取网络类型的方法示例 原创

    本文实例讲述了微信小程序获取网络类型的方法.分享给大家供大家参考,具体如下: 这里主要演示通过wx.getNetworkType获取当前网络类型的操作方法.代码如下: index.js: Page({ /** * 页面的初始数据 */ data: { netType:'' }, /** * 生命周期函数--监听页面加载 */ onLoad: function () { var that = this; try { wx.getNetworkType({ success: function(res

  • PHP获取ip对应地区和使用网络类型的方法

    本文实例讲述了PHP获取ip对应地区和使用网络类型的方法.分享给大家供大家参考.具体分析如下: 这里测试的时候因为ip168网站禁止,所以试着在原有代码上修改为ip138数据库的数据调用,代码如下: <?php //原程序有问题,现修改为ip138数据库 /** * 获取IP地区 * Enter description here ... * @param unknown_type $ip */ function GetArea($ip){ $url = "http://www.ip138.

  • Android判断网络类型的方法(2g,3g还是wifi)

    本文实例讲述了Android判断网络类型的方法.分享给大家供大家参考,具体如下: 判断网络类型是wifi,还是3G,还是2G网络,对不同的网络进行不同的处理,现将判断方法整理给大家,以供参考 说明:下面用到的数据移动2G,联通2G,联通3G,wifi我都已经测试过,暂时手上没有电信的卡,所以没有验证,有电信手机的同事,可以验证一下,验证后将结果发送给大家. ConnectivityManager connectMgr = (ConnectivityManager) this .getSystem

  • Android中Java根据文件头获取文件类型的方法

    本文实例讲述了Android中Java根据文件头获取文件类型的方法.分享给大家供大家参考,具体如下: 前面讲过Android系统内部的MediaFile类来获取文件类型的办法,这个类主要是根据文件的扩展名来判断,其准确性不是很好.具体可查看Android系统使用MediaFile类判断音频文件类型.其实,获取文件类型最好的办法便是根据文件头信息来判断.下面贴出相关代码: public class FileType { public static final HashMap<String, Str

  • iOS获取手机通讯录方式方法(最新)

    最近学习了iOS获取手机通讯录方式方法,现在分享给大家.希望此文章对各位有所帮助. 一.iOS 9 以前的通讯录框架 AddressBookUI框架:提供了联系人列表界面.联系人详情界面.添加联系人界面等,一般用于选择联系人. AddressBook 框架:纯 C 语言的 API,仅仅是获得联系人数据.没有提供 UI 界面展示,需要自己搭建联系人展示界面. 二. iOS 9 以后最新通讯录框架 ContactsUI 框架:拥有 AddressBookUI 框架的所有功能,使用起来更加的面向对象.

  • Android检查手机网络状态及网络类型的方法

    本文实例讲述了Android检查手机网络状态及网络类型的方法.分享给大家供大家参考.具体分析如下: //judge network status is connecting or not public static boolean checkNetworkConnected(Context context) { if (null!=context) { ConnectivityManager connectivityManager = (ConnectivityManager) context

  • C++获取本地时间常见方法汇总

    1.跨平台方法 1.1方法一:手动暴力法 #include <iostream> using namespace std; #include <time.h> time_t t = time(NULL); struct tm* stime=localtime(&t); char tmp[32]={NULL}; sprintf(tmp, "%04d-%02d-%02d %02d:%02d:%02d",1900+stime->tm_year,1+sti

  • iOS测试手机APP的方法汇总:真机运行,打ipa包,testFlighe,蒲公英

    目录 一.真机运行 二.打.ipa包测试 三.通过testFlight添加测试员 四.蒲公英测试 Android APP 的测试开发直接打包一个 apk 包发送给测试,测试可以安装到任何 Android 设备开始测试工作:但是 iOS 不可以,想要在 iOS 系统里安装 APP,必须要得到苹果的授权.iOS 因为苹果系统的私密性,导致 iOS 测试的教程相对来说少很多. 通常测试手机APP的四种方法:真机运行,打ipa包,(testFlighe)邮件,蒲公英测试. 一.真机运行 用数据线真机调试

随机推荐