iOS 判断网络连接状态之重写Reachability

  获取网络连接状态目前有多种方法,其他的都比较好理解,不过都有些局限性,利用statusBar的subViews的信息来获取网络状态是比较简明的,但是在隐藏状态栏的情况下失效,还有使用私有API的方法,这里我们谈谈怎么用Reachability实现判断当前网络状态,包含无连接/2G/3G/4G/wifi。

  首先了解下 网络连接标识 SCNetworkReachabilityFlags

  typedef CF_OPTIONS(uint32_t, SCNetworkReachabilityFlags) {

    kSCNetworkReachabilityFlagsTransientConnection = 1<<0,  // 可以通过瞬时连接(例如PPP---点对点通讯协议) 链接到给定的节点名和地址

    kSCNetworkReachabilityFlagsReachable = 1<<1,         // 当前网络配置可以请求到给定的节点名和地址

    kSCNetworkReachabilityFlagsConnectionRequired = 1<<2,  // 当前网络配置可以请求到给定的节点名和地址,但必须先创建一个连接。如果创建这个标识,需要象征性地生成kSCNetworkReachabilityFlagsConnectionOnTraffickSCNetworkReachabilityFlagsConnectionOnDemand, 或者 kSCNetworkReachabilityFlagsIsWWAN 等标识来指明需要创建的连接类型。如果用户需要手动创建连接,kSCNetworkReachabilityFlagsInterventionRequired标识也将被生成

    kSCNetworkReachabilityFlagsConnectionOnTraffic = 1<<3,  //当前网络配置可以请求到给定的节点名和地址,但必须先创建一个连接。定向到指定节点或地址的通信将发起该连接,该标识原来名为kSCNetworkReachabilityFlagsConnectionAutomatic

    kSCNetworkReachabilityFlagsInterventionRequired = 1<<4, //当前网络配置可以请求到给定的节点名和地址,但必须先创建一个连接
用户需要通过某些方式的介入来创建该连接,比如提供密码、认证口令等。一般的,只有在一个拨号通信的配置中,在自动连接过程中发生某些错误(比如没有拨号音,没有回应,无效的密码等),这种情况下,PPP通信将会终止连接直到用户介入。

    kSCNetworkReachabilityFlagsConnectionOnDemand = 1<<5, //当前网络配置可以请求到给定的节点名和地址,但必须先创建一个连接。请求一经CFSocketStream程序接口请求就创建,其他的函数不会创建该连接

    kSCNetworkReachabilityFlagsIsLocalAddress = 1<<16,   // 所请求的节点或地址为连接到当前系统的网络节点  

    kSCNetworkReachabilityFlagsIsDirect = 1<<17,     // 网络通信不会通过网关连接给定的节点名和地址,而是直接路由到系统中的一个接口上。

  #if TARGET_OS_IPHONE

    kSCNetworkReachabilityFlagsIsWWAN = 1<<18,      // 可通过蜂窝数据网络访问给定的节点或地址

  #endif // TARGET_OS_IPHONE

    kSCNetworkReachabilityFlagsConnectionAutomatic = kSCNetworkReachabilityFlagsConnectionOnTraffic

  };

 

然后就是通过这些标识来判断当前网络类型了。

 

那么第一步就是获取这些标识

 

  SCNetworkReachabilityFlags flags;

 

    

 

    if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags))

 

    {

 

        // 此处获得的flags即能指示当前网络环境的标识

 

    }

 

再对flags进行分析判断,了解网络类型

 

    if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)

    {

   // 无法连接网络

    }    

    if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)

    {

        // 给定的节点或地址是可达的,并且不需要先请求一个多余的连接,那么我们可以判断是通过Wi-Fi连接的(不需要密码)

    }

    

    if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||

         (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))

    {

        // 通过CFSocketStream或者更高级的APIs发起on-demand (或者 on-traffic)请求

        if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)

        {

            // 不需要用户介入的情况下,我们判断为Wi-Fi

        }

    }

    if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)

    {

        /*

         通过CFNetwork APIs发起蜂窝数据网络请求

         */

        if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

        {

            

      /*

             蜂窝数据网络分2/3/4G,此处使用CTTelephonyNetworkInfo来判断,只适用于iOS 7及以上

           */

            CTTelephonyNetworkInfo * info = [[CTTelephonyNetworkInfo alloc] init];

            NSString *currentRadioAccessTechnology = info.currentRadioAccessTechnology;

            if (currentRadioAccessTechnology)

            {

                if ([currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyLTE])

                {

                    // 4G

                }

                else if ([currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyEdge] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyGPRS] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMA1x])

                {

                    // 2G

                }

                else

                {

                    // 3G

                }

            }

        }

        if ((flags & kSCNetworkReachabilityFlagsTransientConnection) == kSCNetworkReachabilityFlagsTransientConnection)

        {

            if((flags & kSCNetworkReachabilityFlagsConnectionRequired) == kSCNetworkReachabilityFlagsConnectionRequired)

            {

                // 2G

            }

            // 3G

        }

        // 由于flags标识中不能提供4G的具体标识,故走到这一步即可认为当前为4G网络环境

        // 4G

    }

 

posted @ 2015-12-28 10:15  Jacue  阅读(779)  评论(0编辑  收藏  举报