检测运营商连接类型(3G / EDGE / GPRS)

21

如何获取运营商网络的连接类型?

  • 使用Reachability类可以获取连接是WIFI还是WWAN。
  • 可以获取网络标志:

    Reachability Flag Status: WR t------ localWiFiStatusForFlags

  • 可以使用CaptiveNetwork获取WIFI SSID。

支持的接口:( en0 )

en0 => {  
    BSSID = "xx:xx:xx:xx:xx:xx";  
    SSID = MyWifiNetwork;  
    SSIDDATA = <x1x1x1x1 x1x1x1x1 x1>;  
}  

但我无法区分3G、EDGE或GPRS连接。

有没有任何想法,也可以使用iOS私有API?

谢谢。

4个回答

61

iOS 7及以上版本可使用以下方法:

CTTelephonyNetworkInfo *telephonyInfo = [CTTelephonyNetworkInfo new];
NSLog(@"Current Radio Access Technology: %@", telephonyInfo.currentRadioAccessTechnology);
[NSNotificationCenter.defaultCenter addObserverForName:CTRadioAccessTechnologyDidChangeNotification 
                                                object:nil 
                                                 queue:nil 
                                            usingBlock:^(NSNotification *note) 
{
    NSLog(@"New Radio Access Technology: %@", telephonyInfo.currentRadioAccessTechnology);
}];

我也发现这可以检测出慢或快的连接:

- (BOOL)isFast:(NSString*)radioAccessTechnology {
    if ([radioAccessTechnology isEqualToString:CTRadioAccessTechnologyGPRS]) {
        return NO;
    } else if ([radioAccessTechnology isEqualToString:CTRadioAccessTechnologyEdge]) {
        return NO;
    } else if ([radioAccessTechnology isEqualToString:CTRadioAccessTechnologyWCDMA]) {
        return YES;
    } else if ([radioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSDPA]) {
        return YES;
    } else if ([radioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSUPA]) {
        return YES;
    } else if ([radioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMA1x]) {
        return NO;
    } else if ([radioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORev0]) {
        return YES;
    } else if ([radioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevA]) {
        return YES;
    } else if ([radioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevB]) {
        return YES;
    } else if ([radioAccessTechnology isEqualToString:CTRadioAccessTechnologyeHRPD]) {
        return YES;
    } else if ([radioAccessTechnology isEqualToString:CTRadioAccessTechnologyLTE]) {
        return YES;
    }

    return YES;
}

2
别忘了在文件顶部加上 #import <CoreTelephony/CTTelephonyNetworkInfo.h>。 - Alejandro Vargas
1
谢谢 @Ben,但我怀疑CDMA1x的速度很快。 - Jason Lee
这不正确,因为在设备上我得到的是HSDPA,无论我是否在3G上或关闭了蜂窝数据。 - Kex
你是否检查了你的wifi是否已开启,并运行此代码,它返回Edge或3G而不是Wifi。当从设备中移除SIM卡时,此代码也将返回null。iPad、iPod没有SIM卡也会返回null。 - Pratik Patel
@BenGroot....我们在什么条件下可以调用上述方法...请详细解释一下如何调用该方法....- (BOOL)isFast:(NSString*)radioAccessTechnology - Priya
显示剩余3条评论

5

以下是使用私有API的SoftwareUpdateServices.frameworkOLD解决方案。

Class NetworkMonitor = NSClassFromString(@"SUNetworkMonitor");
NSLog(@"TYPE: %d", [NetworkMonitor currentNetworkType]);

它返回:
0:无数据 1:WIFI 2:GPRS/EDGE 3:3G
希望这对社区有所帮助。

实际上你需要调用 NSLog(@"TYPE: %d", [[[NetworkMonitor alloc] init] currentNetworkType]); - DanEEStar
5
苹果公司是否因为私有API而拒绝了这个原因? - Ben Groot
1
@BenGroot 可能是的。这种方法使用私有 API。 - elp
据说可以使用键值编码来确定 iOS 6 及以下版本的网络可达性值,而无需使用仅适用于 iOS 7 及以上版本的 CTTelephonyNetworkInfo。 - NicTesla
苹果将会杀掉你的应用程序 :-P,因为使用了私有API。 - byJeevan
@byJeevan 当然。但是我的应用程序不在商店里。 - elp

1
已接受的答案在iOS 10上无效。我找到了一种解决方法,并在AppDelegate中设置了一个计时器,每5秒钟检查一次currentRadioAccessTechnology属性。因此,我们还需要一个函数来检查是否有WIFI连接,而不是无线电访问技术。
检查WIFI连接是否可用:
class func isConnectedToWlan() -> Bool {
    var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, 
                         sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
    zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
    zeroAddress.sin_family = sa_family_t(AF_INET)

    let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
        $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
            SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
        }
    }

    var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0)
    if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false {
        return false
    }

    //Only Working for WIFI
     let isReachable = flags == .reachable
     let needsConnection = flags == .connectionRequired

     return isReachable && !needsConnection
}

设置计时器的方法如下:

像这样设置:

Timer.scheduledTimer(timeInterval: TimeInterval.seconds(5.0), target: self, selector:      
                           #selector(showNetworkMessage), userInfo: nil, repeats: true)

每5秒调用一次的选择器:

    guard !Reachability.isConnecteToWlan() else {
        //Connected to WLAN
        return
    }
    guard let currentRadioAccessTechnology = info.currentRadioAccessTechnology else {
        // No internet connection
        return
    }
    guard (currentRadioAccessTechnology == CTRadioAccessTechnologyGPRS 
             || currentRadioAccessTechnology == CTRadioAccessTechnologyEdge) else {
        // 3G, LTE fast radio access Technology
        return
    }

    if lastRadioAccessTechnology != nil {
        guard let lastRadioAccessTechnology = lastRadioAccessTechnology, 
            (lastInfo != currentRadioAccessTechnology || 
              lastInfo != currentRadioAccessTechnology) else {
            //Internet connection did not change
            return
        }
    }
    // Internet connection changed to Edge or GPRS
    // Store lastRadioAccessTechnology to check if internet connection changed
    lastRadioAccessTechnology = currentRadioAccessTechnology

-1

我正在开发一个iPhone应用程序,需要能够识别当前使用的互联网连接类型(Wifi、3G、Edge等)。我找到了一种简单的方法,通过使用苹果的Reachability示例代码来进行检查。关于这个问题在线上似乎缺乏信息,希望这可以帮助到某些人。

首先将Reachability.m/.h文件复制到你的项目中,并在你的类中包含#include "Reachability.h"。

Reachability *reach = [[Reachability alloc]init];
if (reach.internetConnectionStatus == NotReachable) {
    NSLog(@"No Connection Found");
} else if (reach.internetConnectionStatus == ReachableViaCarrierDataNetwork) {
    NSLog(@"3G or Edge");
} else if (reach.internetConnectionStatus == ReachableViaWiFiNetwork) {
    NSLog(@"Wifi Connection");
}
[reach release];

这段代码可能不是实现此目的的最佳方式,但它似乎是最简单的方法。


1
我已经使用了Reachability类来检测WIFI或CARRIER之间的差异。我想要检测GPRS或EDGE或3G,而不是全部在一起! - elp
1
无法识别GPRS、EDGE或3G。唯一的方法是使用标志kSCNetworkReachabilityFlagsIsWWAN一起识别。 - Michal Zaborowski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接