Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check for local Wi-Fi (not just cellular connection) using iPhone SDK?

I'm currently using the following to check whether Wi-Fi is available for my application:

#import <SystemConfiguration/SystemConfiguration.h>
static inline BOOL addressReachable(const struct sockaddr_in *hostAddress);

BOOL localWiFiAvailable()
{
    struct sockaddr_in localWifiAddress;
    bzero(&localWifiAddress, sizeof(localWifiAddress));
    localWifiAddress.sin_len = sizeof(localWifiAddress);
    localWifiAddress.sin_family = AF_INET;
    // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0
    localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);

    return addressReachable(&localWifiAddress);
}

static inline BOOL addressReachable(const struct sockaddr_in *hostAddress)
{
    const SCNetworkReachabilityRef target =
          SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault,
                                                 (const struct sockaddr *)hostAddress);
    if (target != NULL)
    {
        SCNetworkReachabilityFlags flags = 0;
        const BOOL reachable = SCNetworkReachabilityGetFlags(target, &flags);
        CFRelease(target);
        return reachable && (flags & kSCNetworkFlagsReachable);
    }
    return NO;
}

This, however, does not return NO as it should when the iPhone is connected only to a cellular network but not a Wi-Fi network. Does anyone know how to fix this?

Edit

So this is what I ended up using:

#import <arpa/inet.h> // For AF_INET, etc.
#import <ifaddrs.h> // For getifaddrs()
#import <net/if.h> // For IFF_LOOPBACK

BOOL localWiFiAvailable()
{
    struct ifaddrs *addresses;
    struct ifaddrs *cursor;
    BOOL wiFiAvailable = NO;
    if (getifaddrs(&addresses) != 0) return NO;

    cursor = addresses;
    while (cursor != NULL) {
        if (cursor -> ifa_addr -> sa_family == AF_INET
            && !(cursor -> ifa_flags & IFF_LOOPBACK)) // Ignore the loopback address
        {
            // Check for WiFi adapter
            if (strcmp(cursor -> ifa_name, "en0") == 0) {
                wiFiAvailable = YES;
                break;
            }
        }
        cursor = cursor -> ifa_next;
    }

    freeifaddrs(addresses);
    return wiFiAvailable;
}

Thanks "unforgiven" (and Matt Brown apparently).

like image 792
Michael Avatar asked Sep 19 '09 11:09

Michael


People also ask

How do I verify network connection on iPhone?

Go to Settings > Wi-Fi and make sure that Wi-Fi is on. Tap the name of your Wi-Fi network to join. A blue checkmark beside a network name means that you're connected.

How can you identify if a device iPhone is connected to a Wi-Fi network?

Look at the top of the phone, in the status bar, and if you see the wi-fi fan icon, then the device is connected to wi-fi. Look for the WiFi symbol in the upper left of the screen.

How do I get my iPhone to use Wi-Fi over Cellular?

Go to Settings > Cellular, then turn Cellular Data on or off for any app (such as Maps) or service (such as Wi-Fi Assist) that can use cellular data. If a setting is off, iPhone uses only Wi-Fi for that service. Note: Wi-Fi Assist is on by default.

How do I get all available Wi-Fi network names in iOS?

It is not possible to get all the available wifi networks names and information. BUT it is only possible to get the SSID ( SSID is simply the technical term for a network name) of the network that you are currently connected to. To test this you need a physical device (iPhone) connected to your pc.


4 Answers

First, modify your addressReachable method. Instead of

return reachable && (flags & kSCNetworkFlagsReachable); 

add the following:

BOOL isReachable = ((flags & kSCNetworkFlagsReachable) != 0); BOOL needsConnection = ((flags & kSCNetworkFlagsConnectionRequired) != 0); return (isReachable && !needsConnection) ? YES : NO; 

This is the proper way to check for a connection available. Now, if you want to clearly distinguish between cellular and wifi, modify your method to return an int and use the following

BOOL isReachable = ((flags & kSCNetworkFlagsReachable) != 0); BOOL needsConnection = ((flags & kSCNetworkFlagsConnectionRequired) != 0);  if(isReachable && !needsConnection) // connection is available  {     // determine what type of connection is available    BOOL isCellularConnection = ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0);    NSString *wifiIPAddress = [self getWiFiIPAddress];     if(isCellularConnection)          return 1; // cellular connection available     if(wifiIPAddress)        return 2; // wifi connection available } else    return 0; // no connection at all 

The getWiFiIPAddress method is courtesy of Matt Brown, and can be found here.

One more thing. The kSCNetworkReachabilityFlagsIsDirect flag can tell you whether the network traffic goes through a gateway or arrives directly. This may be helpful in some cases.

The code works correctly on the device. On the simulator, it will declare that you are connected trough wifi when you are connected through the ethernet cable, and will declare no connection if you are connected through wifi.

like image 104
Massimo Cafaro Avatar answered Oct 04 '22 04:10

Massimo Cafaro


See this link: http://developer.apple.com/iphone/library/samplecode/Reachability/

You have to be registered developer in order to download the code sample. Also and it's important! Reachability API works for 3.0+ SDKs, it crashes for lower versions.

BTW, by new HIG all applications that rely on WiFi connection have to alert user on its absence, i.e if the device is not connected to Wifi, let user know.

like image 44
Nava Carmon Avatar answered Oct 04 '22 04:10

Nava Carmon


Swift version

import Foundation
import SystemConfiguration

public class Reachability {
    class func isInternetAvailable() -> Bool {
        let IPaddress = "google.com"//WebServicesUtil.sharedInstance.getHostIPAddress()
        if let host_name = IPaddress.cStringUsingEncoding(NSASCIIStringEncoding) {
            let reachability  =
                SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, host_name).takeRetainedValue()

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

            let isReachable = (flags & UInt32(kSCNetworkFlagsReachable)) != 0
            let needsConnection = (flags & UInt32(kSCNetworkFlagsConnectionRequired)) != 0

            return (isReachable && !needsConnection)
        }
        else {
            return false
        }
    }
}
like image 34
Prabhu.Somasundaram Avatar answered Oct 04 '22 03:10

Prabhu.Somasundaram


Check out the Reachability class provided by Apple. This allows you to check what connectivity the device currently has, between Wifi, cellular or none. You can even register for notifications when the connectivity changes.

Unfortunately, Google is down for me at the moment, but Googling "iPhone reachability" will get you what you need.

like image 23
iKenndac Avatar answered Oct 04 '22 03:10

iKenndac