iPhone получит SSID без приватной библиотеки - PullRequest
149 голосов
/ 04 марта 2011

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

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

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

Ответы [ 8 ]

182 голосов
/ 04 марта 2011

Начиная с 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>;
}

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

До версии 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 и позже, включите возможность Доступа к Информации WiFi для своего приложения в 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

}
60 голосов
/ 12 января 2013

Вот очищенная версия 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;
}
58 голосов
/ 14 октября 2015

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

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

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

Вот фрагмент кода в быстром (ответ 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 устарела *.( source )

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

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

Вам нужно будет отправить электронное письмо по адресу networkextension@apple.com и запросить права.( источник )

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

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 Developer.

28 голосов
/ 06 марта 2013

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

#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;
}
10 голосов
/ 15 июля 2013

Этот код хорошо работает для получения 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>;

}

9 голосов
/ 08 июля 2018

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

7 голосов
/ 04 марта 2011
5 голосов
/ 01 июня 2015

Вот короткая и сладкая версия 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, метод вернет ноль - следовательно, необязательный.

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