Как проверить локальный Wi-Fi (а не только сотовую связь) с помощью iPhone SDK? - PullRequest
25 голосов
/ 19 сентября 2009

В настоящее время я использую следующее, чтобы проверить, доступен ли 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;
}

Это, однако, не возвращает NO, как это должно быть, когда iPhone подключен только к сотовой сети, но не к сети Wi-Fi. Кто-нибудь знает как это исправить?

Редактировать

Итак, вот что я использовал:

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

Спасибо "Непрощенный" (и, очевидно, Мэтт Браун).

Ответы [ 5 ]

30 голосов
/ 26 сентября 2009

Сначала измените ваш метод addressReachable. Вместо

return reachable && (flags & kSCNetworkFlagsReachable);

добавить следующее:

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

Это правильный способ проверить доступное соединение. Теперь, если вы хотите четко различать сотовую связь и Wi-Fi, измените ваш метод, чтобы он возвращал 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

Метод getWiFiIPAddress любезно предоставлен Мэттом Брауном и может быть найден здесь .

Еще одна вещь. Флаг kSCNetworkReachabilityFlagsIsDirect может указывать, проходит ли сетевой трафик через шлюз или поступает напрямую. Это может быть полезно в некоторых случаях.

Код правильно работает на устройстве. На симуляторе он объявит, что вы подключены через Wi-Fi, когда вы подключены через кабель Ethernet, и не будет сообщать, если вы подключены через Wi-Fi.

4 голосов
/ 24 сентября 2009

Смотрите эту ссылку: http://developer.apple.com/iphone/library/samplecode/Reachability/

Вы должны быть зарегистрированным разработчиком, чтобы загрузить пример кода. Также и это важно! API достижимости работает для 3.0+ SDK, сбой для более низких версий.

Кстати, новым HIG все приложения, использующие WiFi-соединение, должны предупреждать пользователя об его отсутствии, т. Е. Если устройство не подключено к Wi-Fi, сообщите пользователю.

2 голосов
/ 24 апреля 2015

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
        }
    }
}
1 голос
/ 08 октября 2012
-(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;

}
1 голос
/ 22 сентября 2009

Проверьте класс Reachability, предоставленный Apple. Это позволяет вам проверить, какое соединение у устройства в настоящее время есть, между Wi-Fi, сотовой связью или без него. Вы даже можете зарегистрироваться для получения уведомлений при изменении подключения.

К сожалению, в данный момент Google отключен для меня, но поиск в Google «iPhone» даст вам то, что вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...