iOS Detect 3G or WiFi

IosObjective CWifiReachability3g

Ios Problem Overview


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

Ios Solutions


Solution 1 - Ios

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
}

Solution 2 - Ios

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

Solution 3 - Ios

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) :

Solution 4 - Ios

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))
 

Solution 5 - Ios

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.

Solution 6 - Ios

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 ""
    }
    
    
}

Solution 7 - Ios

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
}

Solution 8 - Ios

#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.

Solution 9 - Ios

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()

Solution 10 - Ios

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

https://stackoverflow.com/a/63837522/6342609

Solution 11 - Ios

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"
        }
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjwknzView Question on Stackoverflow
Solution 1 - IosJames WebsterView Answer on Stackoverflow
Solution 2 - IosPavel AlexeevView Answer on Stackoverflow
Solution 3 - IosMohammad Zaid PathanView Answer on Stackoverflow
Solution 4 - IosElyView Answer on Stackoverflow
Solution 5 - IosGeri BorbásView Answer on Stackoverflow
Solution 6 - IosSachin AgarwalView Answer on Stackoverflow
Solution 7 - IosHDdeveloperView Answer on Stackoverflow
Solution 8 - IosHogdotmacView Answer on Stackoverflow
Solution 9 - IosorafaelreisView Answer on Stackoverflow
Solution 10 - IosMithra SingamView Answer on Stackoverflow
Solution 11 - IosDmytro ShvetsovView Answer on Stackoverflow