21

How can i get the type of connection of a carrier network?

  • I'm able to get if connection is WIFI or WWAN using Reachability class
  • I'm able to get network flags

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

  • I'm able to get WIFI SSID using CaptiveNetwork

Supported interfaces: ( en0 )

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

But i'm not able to differenziate 3G, EDGE or GPRS connection.

Any idea also using iOS private API?

thanks.

elp
  • 8,021
  • 7
  • 61
  • 120

4 Answers4

61

From iOS 7 on you can use:

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);
}];

I have also found this to detect a slow or fast connection:

- (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;
}
Ben Groot
  • 5,040
  • 3
  • 40
  • 47
  • 2
    Don't forget to put #import at the top of your file. – Alejandro Vargas Oct 27 '14 at 11:12
  • Is this a private API? I don't see it documented in CTTelephonyNetworkInfo class. – nyus2006 Nov 11 '14 at 19:57
  • 1
    Thanks @Ben , but I doubt that CDMA1x is fast – Jason Lee Jan 28 '15 at 02:45
  • You are right, I'll change it to NO. The speed seems to be at most 144kbps, which can be compared with Edge speeds. Thanks Jason Lee :) +1 – Ben Groot Jan 28 '15 at 10:44
  • This is not correct, since on device I get HSDPA, no matter if I'm on 3G or I have Cellular Data turned off. – Kex Sep 13 '15 at 19:52
  • Have you checked when your wifi is on and run this code, it returns Edge or 3G instead of Wifi. Also this code retuns null when remove SIM from device. iPad, iPod without SIM are also returns null. – Pratik Patel Nov 23 '15 at 07:36
  • @BenGroot can we switch LTE to 3g/2g using MDM commands? for a enteprise apps. – vishy Apr 14 '16 at 06:50
  • @BenGroot....On which condition we can call above method...pls explain little bit more how to call that method....- (BOOL)isFast:(NSString*)radioAccessTechnology – Priya May 29 '17 at 07:47
5

Here the OLD solution, using private API, in particular SoftwareUpdateServices.framework

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

It returns:

0: NO DATA
1: WIFI
2: GPRS/EDGE
3: 3G

hope this helps community.

elp
  • 8,021
  • 7
  • 61
  • 120
1

The accepted answer isn't working on iOS 10. I found a workaround and setup a timer in AppDelegate which is checking the property currentRadioAccessTechnology every 5 seconds. Therefore we also need a function to check if WIFI connection is available instead of radio access technology.

Check if WIFI Connection is available:

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
}

Setup the timer like this:

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

Selector which is called every 5 seconds:

    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
cb89
  • 161
  • 13
-1

I am working on an iPhone application that requires the ability to recognize which type of internet connection is currently being used (Wifi, 3G, Edge, etc). I found a simple way to check by using Apples Reachability sample code. There seems to be a shortage of information about this online, I hope this can help someone.

First copy Reachability.m/.h into your project and include #include "Reachability.h" into your class.

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];

This code may not be the best way to accomplish this, but it appears to be the most simple approach.

Tiffany
  • 227
  • 2
  • 6
  • 17
  • 1
    I already use Reachability class to detect difference between WIFI or CARRIER. I want to detect GPRS or EDGE or 3G, not all toghether! – elp Jun 15 '12 at 11:23
  • 1
    There is no possible to recognize GPRS or EDGE or 3G. Only way is recognize all together with flag kSCNetworkReachabilityFlagsIsWWAN – Michal Zaborowski Jun 15 '12 at 12:17