it-roy-ru.com

iPhone получит SSID без приватной библиотеки

У меня есть коммерческое приложение, которое имеет вполне законную причину для просмотра SSID сети, к которой оно подключено: если оно подключено к сети Adhoc для стороннего аппаратного устройства, оно должно функционировать не так, как если бы оно было подключен к интернету.

Все, что я видел о получении SSID, говорит мне, что я должен использовать Apple80211, который, как я понимаю, является частной библиотекой. Я также прочитал, что, если я использую личную библиотеку, Apple не одобрит приложение.

Я застрял между Apple и ​​трудным местом, или мне чего-то не хватает здесь?

149
Steve Reed Sr

Начиная с iOS 7 или 8, вы можете сделать это, используя преимущества ARC и модулей, которые будут автоматически связываться в необходимой среде:

@import SystemConfiguration.CaptiveNetwork;

/** Returns first non-empty SSID network info dictionary.
 *  @see CNCopyCurrentNetworkInfo */
- (NSDictionary *)fetchSSIDInfo
{
    NSArray *interfaceNames = CFBridgingRelease(CNCopySupportedInterfaces());
    NSLog(@"%s: Supported interfaces: %@", __func__, interfaceNames);

    NSDictionary *SSIDInfo;
    for (NSString *interfaceName in interfaceNames) {
        SSIDInfo = CFBridgingRelease(
            CNCopyCurrentNetworkInfo((__bridge CFStringRef)interfaceName));
        NSLog(@"%s: %@ => %@", __func__, interfaceName, SSIDInfo);

        BOOL isNotEmpty = (SSIDInfo.count > 0);
        if (isNotEmpty) {
            break;
        }
    }
    return SSIDInfo;
}

(Это модернизация образца кода, написанного для iOS 4.1+. Единственными изменениями были введение более понятных имен переменных и принятие ARC и модулей.)

Пример вывода:

2011-03-04 15:32:00.669 ShowSSID[4857:307] -[ShowSSIDAppDelegate fetchSSIDInfo]: Supported interfaces: (
    en0
)
2011-03-04 15:32:00.693 ShowSSID[4857:307] -[ShowSSIDAppDelegate fetchSSIDInfo]: en0 => {
    BSSID = "ca:fe:ca:fe:ca:fe";
    SSID = XXXX;
    SSIDDATA = <01234567 01234567 01234567>;
}

Обратите внимание, что в симуляторе не поддерживаются if. Протестируйте на своем устройстве.

До версии 4.1 вам, возможно, повезло в слове "Конфигурация системы". Например, используя scutil на моем Mac:

$ scutil
> show State:/Network/Interface/en1/AirPort
<dictionary> {
  Power Status : 1
  SecureIBSSEnabled : FALSE
  BSSID : <data> 0xcafecafecafe
  SSID_STR : XXXX
  SSID : <data> 0x012345670123456701234567
  Busy : FALSE
  CHANNEL : <dictionary> {
    CHANNEL : 1
    CHANNEL_FLAGS : 10
  }
}
> exit

iOS 12

Вы должны включить доступ к информации Wi-Fi из возможностей.

Важно! Чтобы использовать эту функцию в iOS 12 и более поздних версиях, включите возможность доступа к информации Wi-Fi для вашего приложения в XCode. Когда вы включаете эту возможность, XCode автоматически добавляет право доступа к информации Wi-Fi в ваш файл разрешений и идентификатор приложения. ссылка на документацию

Swift 4.2

func getConnectedWifiInfo() -> [AnyHashable: Any]? {

    if let ifs = CFBridgingRetain( CNCopySupportedInterfaces()) as? [String],
        let ifName = ifs.first as CFString?,
        let info = CFBridgingRetain( CNCopyCurrentNetworkInfo((ifName))) as? [AnyHashable: Any] {

        return info
    }
    return nil

}
182
Jeremy W. Sherman

Вот очищенная версия ARC, основанная на коде @ elsurudo:

- (id)fetchSSIDInfo {
     NSArray *ifs = (__bridge_transfer NSArray *)CNCopySupportedInterfaces();
     NSLog(@"Supported interfaces: %@", ifs);
     NSDictionary *info;
     for (NSString *ifnam in ifs) {
         info = (__bridge_transfer NSDictionary *)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
         NSLog(@"%@ => %@", ifnam, info);
         if (info && [info count]) { break; }
     }
     return info;
}
60
esad

ОБНОВЛЕНИЕ для iOS 10 и выше

CNCopySupportedInterfaces больше не поддерживается в iOS 10. ( Справочник по API )

Вам необходимо импортировать SystemConfiguration/CaptiveNetwork.h и добавить SystemConfiguration.framework к связанным библиотекам вашей цели (в стадии сборки).

Вот фрагмент кода в Swift (ответ RikiRiocma) :

import Foundation
import SystemConfiguration.CaptiveNetwork

public class SSID {
    class func fetchSSIDInfo() -> String {
        var currentSSID = ""
        if let interfaces = CNCopySupportedInterfaces() {
            for i in 0..<CFArrayGetCount(interfaces) {
                let interfaceName: UnsafePointer<Void> = CFArrayGetValueAtIndex(interfaces, i)
                let rec = unsafeBitCast(interfaceName, AnyObject.self)
                let unsafeInterfaceData = CNCopyCurrentNetworkInfo("\(rec)")
                if unsafeInterfaceData != nil {
                    let interfaceData = unsafeInterfaceData! as Dictionary!
                    currentSSID = interfaceData["SSID"] as! String
                }
            }
        }
        return currentSSID
    }
}

( Важно: CNCopySupportedInterfaces возвращает ноль на симуляторе.)

Для Objective-c см. ответ Эсада здесь и ниже

+ (NSString *)GetCurrentWifiHotSpotName {    
    NSString *wifiName = nil;
    NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces();
    for (NSString *ifnam in ifs) {
        NSDictionary *info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
        if (info[@"SSID"]) {
            wifiName = info[@"SSID"];
        }
    }
    return wifiName;
}

ОБНОВЛЕНИЕ ДЛЯ iOS 9

Начиная с iOS 9 Captive Network устарела *. ( источник )

* Больше не рекомендуется в iOS 10, см. Выше.

Рекомендуется использовать NEHotspotHelper ( источник )

Вам нужно будет отправить электронное письмо Apple по адресу [email protected] и запросить разрешения. ( источник )

Пример кода ( Не мой код. См. Ответ Пабло А ):

for(NEHotspotNetwork *hotspotNetwork in [NEHotspotHelper supportedNetworkInterfaces]) {
    NSString *ssid = hotspotNetwork.SSID;
    NSString *bssid = hotspotNetwork.BSSID;
    BOOL secure = hotspotNetwork.secure;
    BOOL autoJoined = hotspotNetwork.autoJoined;
    double signalStrength = hotspotNetwork.signalStrength;
}

Примечание: Да, они отказались от CNCopySupportedInterfaces в iOS 9 и полностью изменили свою позицию в iOS 10. Я поговорил с сетевым инженером Apple, и отмена произошла после того, как очень много людей подали заявки на Radars и высказались по поводу проблемы Apple Форумы разработчиков.

58
Emin Israfil iOS

Это работает для меня на устройстве (не симулятор). Убедитесь, что вы добавили каркас конфигурации системы.

#import <SystemConfiguration/CaptiveNetwork.h>

+ (NSString *)currentWifiSSID {
    // Does not work on the simulator.
    NSString *ssid = nil;
    NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces();
    for (NSString *ifnam in ifs) {
        NSDictionary *info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
        if (info[@"SSID"]) {
            ssid = info[@"SSID"];
        }
    }
    return ssid;
}
28
Chris

Этот код хорошо работает, чтобы получить SSID.

#import <SystemConfiguration/CaptiveNetwork.h>

@implementation IODAppDelegate

@synthesize window = _window;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{


CFArrayRef myArray = CNCopySupportedInterfaces();
CFDictionaryRef myDict = CNCopyCurrentNetworkInfo(CFArrayGetValueAtIndex(myArray, 0));
NSLog(@"Connected at:%@",myDict);
NSDictionary *myDictionary = (__bridge_transfer NSDictionary*)myDict;
NSString * BSSID = [myDictionary objectForKey:@"BSSID"];
NSLog(@"bssid is %@",BSSID);
// Override point for customization after application launch.
return YES;
}

И вот результаты:

Connected at:{
BSSID = 0;
SSID = "Eqra'aOrange";
SSIDDATA = <45717261 27614f72 616e6765>;

}

10
Jameel

Если вы используете iOS 12, вам нужно будет сделать дополнительный шаг. Я изо всех сил пытался заставить этот код работать и, наконец, нашел его на сайте Apple: "Важно! Чтобы использовать эту функцию в iOS 12 и более поздних версиях, включите функцию доступа к Wi-Fi Information для вашего приложения в XCode. Когда вы включите эту возможность, XCode автоматически добавляет право доступа к информации Wi-Fi в ваш файл разрешений и идентификатор приложения. " https://developer.Apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo

9
Muvimotv
7
onnoweb

Вот короткая и приятная Swift версия.

Не забудьте связать и импортировать Framework:

import UIKit
import SystemConfiguration.CaptiveNetwork

Определите метод:

func fetchSSIDInfo() -> CFDictionary? {
    if let
        ifs = CNCopySupportedInterfaces().takeUnretainedValue() as? [String],
        ifName = ifs.first,
        info = CNCopyCurrentNetworkInfo((ifName as CFStringRef))
    {
        return info.takeUnretainedValue()
    }
    return nil
}

Вызовите метод, когда вам это нужно:

if let
    ssidInfo = fetchSSIDInfo() as? [String:AnyObject],
    ssID = ssidInfo["SSID"] as? String
{
    println("SSID: \(ssID)")
} else {
    println("SSID not found")
}

Как уже упоминалось, это работает только на вашем iDevice. Когда не по WiFi, метод вернет ноль - следовательно, необязательный.

5
n.Drake