Как проверить локальный Wi-Fi (не только сотовую связь) с помощью iPhone SDK?
В настоящее время я использую следующее, чтобы проверить, доступен ли Wi-Fi для моего приложения:
#import 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 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. Кто-нибудь знает, как это исправить?
редактировать
Так вот что я в итоге использовал:
- Как анализировать длительность ISO-8601 в Objective C?
- Можем ли мы пригласить людей использовать наше приложение или отправить запрос друга из приложения через Facebook в iOS 5?
- Как получить счетчик ссылок NSObject?
- Представление controllerа модального вида сразу после отклонения другого
- Одновременные распознаватели жестов в Iphone SDK
#import // For AF_INET, etc. #import // For getifaddrs() #import // 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; }
Спасибо «непрощенный» (и, по-видимому, Мэтт Браун).
- Программный пример UIPickerView?
- Cocoa Touch: как изменить цвет и толщину границ UIView?
- Получение времени, прошедшего в Objective-C
- QLPreviewController удаляет или добавляет UIBarButtonItems
- Как написать данные в plist?
- Почему NSError нуждается в двойной косвенности? (указатель на указатель)
- iPhone: конвертировать строку даты в относительную отметку времени
- Содержимое HTML соответствует UIWebview без масштабирования
Во-первых, измените свой метод 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.
См. Эту ссылку: http://developer.apple.com/iphone/library/samplecode/Reachability/
Вы должны быть зарегистрированным разработчиком, чтобы загрузить образец кода. Также и это важно! API API для повышения производительности работает для SDK 3.0+, он выходит из строя для более низких версий.
BTW, новым HIG, все приложения, которые полагаются на соединение WiFi, должны предупредить пользователя об его отсутствии, то есть, если устройство не подключено к Wi-Fi, сообщите об этом пользователю.
Быстрая версия
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 } } }
Ознакомьтесь с classом Reachability, предоставляемым Apple. Это позволяет вам проверить, какое подключение имеет устройство в настоящее время, между Wi-Fi, сотовой или нет. Вы можете даже зарегистрироваться для уведомлений при изменении связи.
К сожалению, Google сейчас для меня не работает, но Googling «Достижение iPhone» поможет вам в том, что вам нужно.
-(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; }