iOS Detect 3G or WiFi
Asked Answered
Y

11

110

I am not sure if this is possible, but I have this scenario.

I have a website displayed in my UIWebView which has the link set in a UISegmentedController. They website can detect if you are on wifi or on the 3g network.

Now the segmented controller points to 2 different pages: 1 - An iPhone friendly login screen 2 - The home page, once you are logged in.

Now here is the question:

Can I program my application to detect whether it is to WIFI or 3G (I know you can do this), but then based on the answer go to segment 1 or 2

Kind of like this:

if (iPhone device is on 3g) {
    Go to Segment 1;
} else {
    Go to Segment 0;
}
Yurt answered 29/10, 2011 at 11:34 Comment(1)
possible duplicate of iphone SDK detect Wifi and Carrier networkLearned
P
211

Using the code that Apple has provided here

Reachability *reachability = [Reachability reachabilityForInternetConnection];
[reachability startNotifier];

NetworkStatus status = [reachability currentReachabilityStatus];

if(status == NotReachable) 
{
    //No internet
}
else if (status == ReachableViaWiFi)
{
    //WiFi
}
else if (status == ReachableViaWWAN) 
{
    //3G
}
Patiencepatient answered 29/10, 2011 at 12:3 Comment(10)
Yes Cool it worked!!! Had to do some fixing up of the reachability files as they had errors for iOS5 in it - but I am so happy right now. Unfortunately I can only give you 1 up vote:-)Yurt
Shouldn't you call [reachability stopNotifier] after you have the status?Wornout
That depends on the scope in which you use this code. If this were just in a method, reachability would go out of scope and be dealloced at the end of the method and stopNotifier would be called implicitly.Patiencepatient
Thanks for the edit. I assume it was an old version of this code that used ReachableViaWifiNetworkPatiencepatient
That works great, but do not forget include in project general systemConfiguration.framework, otherwise you will get Linker problemMclellan
Also available on CocoaPods: pod 'Reachability'Trappist
Some know how to tell which WAN is? 3G, 4G, LTE?Blader
"Important: This document is no longer being updated. For the latest information about Apple SDKs, visit the documentation website."Helotism
Yep, that’s correct, this is a very old question/answer but the link isn’t dead, it just as old as the answer.Patiencepatient
@JamesWebster do you know of a up to date doc on this?Helotism
A
32

If you don't want to import Reachability library or deal with notifiers, you can use this simple synchronous method:

typedef enum {
    ConnectionTypeUnknown,
    ConnectionTypeNone,
    ConnectionType3G,
    ConnectionTypeWiFi
} ConnectionType;


+ (ConnectionType)connectionType
{
    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, "8.8.8.8");
    SCNetworkReachabilityFlags flags;
    BOOL success = SCNetworkReachabilityGetFlags(reachability, &flags);
    CFRelease(reachability);
    if (!success) {
        return ConnectionTypeUnknown;
    }
    BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0);
    BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0);
    BOOL isNetworkReachable = (isReachable && !needsConnection);

    if (!isNetworkReachable) {
        return ConnectionTypeNone;
    } else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) {
        return ConnectionType3G;
    } else {
        return ConnectionTypeWiFi;
    }
}
Antonyantonym answered 24/3, 2015 at 22:57 Comment(1)
To use this helpful code, you have to #import <SystemConfiguration/SystemConfiguration.h> and link to SystemConfiguration.framework.Reef
L
18

Import Apple's Reachability and try this,

#import "Reachability.h"
#import <CoreTelephony/CTTelephonyNetworkInfo.h>

//Try this
Reachability *reachability = [Reachability reachabilityForInternetConnection];
    [reachability startNotifier];

    NetworkStatus status = [reachability currentReachabilityStatus];

    if(status == NotReachable)
    {
       NSLog(@"none");
        //No internet
    }
    else if (status == ReachableViaWiFi)
    {
        NSLog(@"Wifi");
        //WiFi
    }
    else if (status == ReachableViaWWAN)
    {
        NSLog(@"WWAN");


    //connection type
    CTTelephonyNetworkInfo *netinfo = [[CTTelephonyNetworkInfo alloc] init];
    _carrier = [[netinfo subscriberCellularProvider] carrierName];

    if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyGPRS]) {
        NSLog(@"2G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyEdge]) {
        NSLog(@"2G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyWCDMA]) {
        NSLog(@"3G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSDPA]) {
        NSLog(@"3G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSUPA]) {
        NSLog(@"3G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMA1x]) {
        NSLog(@"2G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORev0]) {
        NSLog(@"3G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevA]) {
        NSLog(@"3G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevB]) {
        NSLog(@"3G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyeHRPD]) {
        NSLog(@"3G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyLTE]) {
        NSLog(@"4G");
    }

    }

References(Links may broke in future) :

Luiseluiza answered 17/12, 2015 at 11:14 Comment(1)
First add SystemConfiguration framework, open this link github.com/tonymillion/Reachabilit' and download the file and copy Reachability.h, .m to your project and import #import "Reachability.h", #import <CoreTelephony/CTTelephonyNetworkInfo.h> and finally copy paste above code.....Baynebridge
T
13

When using iOS 12 or newer, you can use NWPathMonitor instead of the pre-historic Reachabilityclass :

import Network // Put this on top of your class

let monitor = NWPathMonitor()

monitor.pathUpdateHandler = { path in
    if path.status != .satisfied {
        // Not connected
    }
    else if path.usesInterfaceType(.cellular) {
        // Cellular 3/4/5g connection
    }
    else if path.usesInterfaceType(.wifi) {
        // Wi-fi connection
    }
    else if path.usesInterfaceType(.wiredEthernet) {
        // Ethernet connection
    }
}

monitor.start(queue: DispatchQueue.global(qos: .background))
Telltale answered 3/9, 2019 at 13:27 Comment(1)
Can we define what host to test for that, like we could with Reachability.reachabilityWithHostName ?Agnostic
B
8

I made a pretty simple block based Reachability wrapper that strips all the outdated C-like Reachability code, poured into a much more Cocoa form.

Usage like:

[EPPZReachability reachHost:hostNameOrIPaddress
               completition:^(EPPZReachability *reachability)
{
    if (reachability.reachableViaCellular) [self doSomeLightweightStuff];
}];

See Reachability with blocks for everyday use at eppz!blog, or grab it directly from eppz!reachability at GitHub.

It also works with IP addresses, which turned out to be a pretty rare Reachability wrapper feature.

Botelho answered 16/12, 2013 at 16:49 Comment(2)
Ummm why the 'screenshot'?Qualifier
I had it from the blog post, candy for eyes.Calla
V
5

For swift we can use:

func getNetworkType()->String {
    do{
        let reachability:Reachability = try Reachability.reachabilityForInternetConnection()
        do{
            try reachability.startNotifier()
            let status = reachability.currentReachabilityStatus
            if(status == .NotReachable){
                return ""
            }else if (status == .ReachableViaWiFi){
                return "Wifi"
            }else if (status == .ReachableViaWWAN){
                let networkInfo = CTTelephonyNetworkInfo()
                let carrierType = networkInfo.currentRadioAccessTechnology
                switch carrierType{
                case CTRadioAccessTechnologyGPRS?,CTRadioAccessTechnologyEdge?,CTRadioAccessTechnologyCDMA1x?: return "2G"
                case CTRadioAccessTechnologyWCDMA?,CTRadioAccessTechnologyHSDPA?,CTRadioAccessTechnologyHSUPA?,CTRadioAccessTechnologyCDMAEVDORev0?,CTRadioAccessTechnologyCDMAEVDORevA?,CTRadioAccessTechnologyCDMAEVDORevB?,CTRadioAccessTechnologyeHRPD?: return "3G"
                case CTRadioAccessTechnologyLTE?: return "4G"
                default: return ""
                }

                // Get carrier name

            }else{
                return ""
            }
        }catch{
            return ""
        }

    }catch{
        return ""
    }


}
Violoncello answered 6/4, 2016 at 12:31 Comment(0)
L
3

Class method is as follow

+(NSString*)connectedNetworkType {
     Reachability *reachability = [Reachability reachabilityForInternetConnection];
        [reachability startNotifier];

        NetworkStatus status = [reachability currentReachabilityStatus];

        if(status == NotReachable) {
            NSLog(@"none");
            //No internet
        }
        else if (status == ReachableViaWiFi) {
            NSLog(@"Wifi");
            //WiFi
            return @"Wifi";
        }
        else if (status == ReachableViaWWAN){
            NSLog(@"WWAN");
            //connection type
            CTTelephonyNetworkInfo *netinfo = [[CTTelephonyNetworkInfo alloc] init];
            //    _carrier = [[netinfo subscriberCellularProvider] carrierName];
            if (([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyGPRS])
                ||([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyEdge])
                ||([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMA1x])) {
                NSLog(@"2G");
                return @"2G";
            }
            else if (([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyWCDMA])
                     ||([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSDPA])
                     ||([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSUPA])
                     ||([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORev0])
                     ||([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevA])
                     ||([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevB])
                     ||([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyeHRPD])){
                NSLog(@"3G");
                return @"3G";
            }
            else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyLTE]) {
                NSLog(@"4G");
                return @"4G";

            }
        }
        return @"-1";//default unknown
}
Legofmutton answered 11/7, 2017 at 17:57 Comment(0)
T
2
#import <ifaddrs.h>
#import <arpa/inet.h>

BOOL CheckWiFi() {

    struct ifaddrs *interfaces = NULL;
    struct ifaddrs *temp_addr = NULL;

    BOOL hasWifi = NO;

    int err = getifaddrs(&interfaces);
    if(err == 0) {

        temp_addr = interfaces; 

        while(temp_addr) {

            if(temp_addr->ifa_addr->sa_family == AF_INET) {

                struct sockaddr_in *addr = (struct sockaddr_in *)temp_addr->ifa_addr;

                if(memcmp(temp_addr->ifa_name, "en", 2) == 0) {
                    hasWifi = YES;
                    break;
                }
            }

            temp_addr = temp_addr->ifa_next;
        }
    }

    freeifaddrs(interfaces);
    return hasWifi;
}

To check if you are in a wifi, this saves the costly check of making a connection. Check for ifa_name "bridge" to check for internet sharing.

Transpire answered 28/10, 2016 at 13:2 Comment(0)
T
1

If you are using Xamarin or Monotouch you can use Reachability adapted class from Xamarin GitHub repository:

https://github.com/xamarin/monotouch-samples/blob/master/ReachabilitySample/reachability.cs

So add it to your project and call Reachability.InternetConnectionStatus()

Tinned answered 28/8, 2013 at 14:38 Comment(1)
The link is broken.Avidity
S
1

If you don't want to use Reachability or using Swift simple answer is here

https://mcmap.net/q/48801/-how-to-use-scnetworkreachability-in-swift

Sloganeer answered 10/9, 2020 at 20:54 Comment(0)
S
1

Swift version with 5G support; based on several answers.

import Foundation
import SystemConfiguration
import CoreTelephony

/// Returns current network connection type(e.g. 4G, WIFI). It may take some time; so there is the suggestion not to use it on the main queue.
static func connectionType() -> ConnectionType {
    guard let reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, "www.google.com") else {
        return .noConnection
    }
    
    var flags = SCNetworkReachabilityFlags()
    SCNetworkReachabilityGetFlags(reachability, &flags)
    
    guard flags.contains(.reachable) else { return .noConnection }
    guard flags.contains(.isWWAN) else { return .wifi }
    
    let networkInfo = CTTelephonyNetworkInfo()
    let carrierTypeName: String?
    
    if #available(iOS 12.0, *) {
        carrierTypeName = networkInfo.serviceCurrentRadioAccessTechnology?.first?.value
    } else {
        carrierTypeName = networkInfo.currentRadioAccessTechnology
    }
    
    if #available(iOS 14.0, *) {
        switch carrierTypeName {
            case CTRadioAccessTechnologyNR, CTRadioAccessTechnologyNRNSA:
                return .cellular5G
            default:
                break
        }
    }
    
    switch carrierTypeName {
        case CTRadioAccessTechnologyGPRS, CTRadioAccessTechnologyEdge, CTRadioAccessTechnologyCDMA1x:
            return .cellular2G
        case CTRadioAccessTechnologyLTE:
            return .cellular4G
        case nil:
            return .unknown
        default:
            return .cellular3G
    }
}

enum ConnectionType: CustomStringConvertible {
    case noConnection, unknown, wifi, cellular2G, cellular3G, cellular4G, cellular5G
        
    var description: String {
        switch self {
            case .noConnection:
                return "no connection"
            case .unknown:
                return "unknown"
            case .wifi:
                return "WIFI"
            case .cellular2G:
                return "2G"
            case .cellular3G:
                return "3G"
            case .cellular4G:
                return "LTE"
            case .cellular5G:
                return "5G"
        }
    }
}
Shear answered 24/1, 2021 at 19:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.