简体   繁体   English

如何使用iPhone SDK检查本地Wi-Fi(不仅仅是蜂窝连接)?

[英]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: 我目前正在使用以下内容检查我的应用程序是否可以使用Wi-Fi

#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. 然而,当iPhone仅连接到蜂窝网络但不连接到Wi-Fi网络时,这不会返回NO。 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). 谢谢“unforgiven”(和马特·布朗显然)。

First, modify your addressReachable method. 首先,修改addressReachable方法。 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 现在,如果您想清楚地区分蜂窝和wifi,请修改您的方法以返回int并使用以下内容

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 . getWiFiIPAddress方法由Matt Brown提供,可以在这里找到。

One more thing. 还有一件事。 The kSCNetworkReachabilityFlagsIsDirect flag can tell you whether the network traffic goes through a gateway or arrives directly. kSCNetworkReachabilityFlagsIsDirect标志可以告诉您网络流量是通过网关还是直接到达。 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. 在模拟器上,当您通过以太网电缆连接时,它将声明您通过wifi连接,并且如果您通过wifi连接将声明没有连接。

See this link: http://developer.apple.com/iphone/library/samplecode/Reachability/ 请看这个链接: 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. Reachability API适用于3.0+ SDK,对于较低版本而言崩溃。

BTW, by new HIG all applications that rely on WiFi connection have to alert user on its absence, ie if the device is not connected to Wifi, let user know. 顺便说一下,新的HIG所有依赖WiFi连接的应用都必须提醒用户没有,即如果设备没有连接到Wifi,请让用户知道。

Swift version Swift版本

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
        }
    }
}
-(Bool)isDataSourceAvailableNow
{ 

    BOOL isDataSourceAvailable;

    bool success = false;

    const char *host_name = [@"www.google.com" cStringUsingEncoding:NSASCIIStringEncoding];

    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL,  host_name);

    if (reachability) 
    {

        SCNetworkReachabilityFlags flags;
        success = SCNetworkReachabilityGetFlags(reachability, &flags);

        isDataSourceAvailable = success && (flags & kSCNetworkFlagsReachable) &&  !(flags & kSCNetworkFlagsConnectionRequired);

        CFRelease(reachability);

    }  return isDataSourceAvailable;

}

Check out the Reachability class provided by Apple. 查看Apple提供的Reachability类。 This allows you to check what connectivity the device currently has, between Wifi, cellular or none. 这允许您检查设备当前具有的连接,Wifi,蜂窝或无。 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. 不幸的是,谷歌此刻对我不利,但谷歌搜索“iPhone可达性”将为您提供所需。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM