iPhone获得没有私人图书馆的SSID

Ste*_* Sr 153 iphone xcode ssid ios

我有一个商业应用程序有一个完全正当的理由看到它所连接的网络的SSID:如果它连接到第三方硬件设备的Adhoc网络,它需要以不同于它的方式运行连接到互联网.

我所看到的有关获取SSID的所有内容都告诉我必须使用Apple80211,我理解这是一个私有库.我还读到,如果我使用私人图书馆Apple将不会批准该应用程序.

我被困在苹果和硬地之间,还是我在这里缺少什么?

Jer*_*man 186

从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;
}
Run Code Online (Sandbox Code Playgroud)

(这是为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>;
}
Run Code Online (Sandbox Code Playgroud)

请注意,模拟器上不支持ifs.在您的设备上测试.

在4.1之前,您可能会通过系统配置字典获得一些运气.例如,__CODE__在我的Mac上使用:

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

}
Run Code Online (Sandbox Code Playgroud)

iOS 12

您必须从功能启用访问wifi信息.

重要信息要在iOS 12及更高版本中使用此功能,请在Xcode中为您的应用启用Access WiFi信息功能.启用此功能后,Xcode会自动将Access WiFi信息权利添加到您的权利文件和应用程序ID中.文档链接

  • 谢谢!如果你正在使用ARC,那么它应该是这样的: - (id)fetchSSIDInfo {NSArray*ifs =(__ bridge_transfer id)CNCopySupportedInterfaces(); NSLog(@"%s:支持的接口:%@",__ func __,ifs); id info = nil; for(ifs中的NSString*ifnam){info =(__ bridge_transfer id)CNCopyCurrentNetworkInfo((__ bridge CFStringRef)ifnam); NSLog(@"%s:%@ =>%@",__ func __,ifnam,info); if(info && [info count]){break; 返回信息; } (8认同)

esa*_*sad 60

这是清理过的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;
}
Run Code Online (Sandbox Code Playgroud)


Emi*_*iOS 58

适用于iOS 10及更新版本

iOS 10中不再弃用CNCopySupportedInterfaces.(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
    }
}
Run Code Online (Sandbox Code Playgroud)

(重要: CNCopySupportedInterfaces在模拟器上返回nil.)

对于Objective-c,请参阅Esad的答案

+ (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;
}
Run Code Online (Sandbox Code Playgroud)

适用于iOS 9的更新

截至iOS 9,Captive Network已被弃用*.(来源)

*不再在iOS 10中弃用,请参见上文.

建议你使用NEHotspotHelper(来源)

您需要通过networkextension@apple.com向Apple发送电子邮件并申请权利.(来源)

示例代码(不是我的代码.请参阅Pablo A的答案):

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;
}
Run Code Online (Sandbox Code Playgroud)

旁注:是的,他们弃用了iOS 9中的CNCopySupportedInterfaces,并改变了他们在iOS 10中的地位.我与一位Apple网络工程师进行了交谈,之后很多人提交了Radars并在Apple Developer论坛上发表了这个问题.


Chr*_*ris 28

这适用于我的设备(不是模拟器).确保添加系统配置框架.

#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;
}
Run Code Online (Sandbox Code Playgroud)


Jam*_*eel 10

此代码可以很好地获取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;
}
Run Code Online (Sandbox Code Playgroud)

这是结果:

Connected at:{
BSSID = 0;
SSID = "Eqra'aOrange";
SSIDDATA = <45717261 27614f72 616e6765>;
Run Code Online (Sandbox Code Playgroud)

}


Muv*_*otv 9

如果您运行的是iOS 12,则需要执行额外的步骤.我一直在努力使这个代码工作,最后在Apple的网站上找到了这个:"重要的是要在iOS 12及更高版本中使用此功能,请在Xcode中为您的应用启用Access WiFi信息功能.当您启用此功能时,Xcode会自动执行将Access WiFi信息权利添加到您的权利文件和应用程序ID." https://developer.apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo


n.D*_*ake 5

这是简短而甜蜜的Swift版本.

请记住链接和导入框架:

import UIKit
import SystemConfiguration.CaptiveNetwork
Run Code Online (Sandbox Code Playgroud)

定义方法:

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

在需要时调用方法:

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

如其他地方所述,这仅适用于您的iDevice.当不在WiFi上时,该方法将返回nil - 因此是可选的.


Fra*_*s B 5

适用于 iOS 13

从 iOS 13 开始,您的应用程序还需要访问 Core Location 才能使用该CNCopyCurrentNetworkInfo 功能,除非它配置了当前网络或具有 VPN 配置:
摘自 https://developer.apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo?language=objc

所以这就是您所需要的(请参阅苹果文档):
- 链接CoreLocation.framework
-在Info.plistlocation-services中添加为UIRequiredDeviceCapabilities键/值 -在Info.plist中添加键/值,描述为什么您的应用程序需要核心位置 - 添加“访问 WiFi”您的应用程序的信息”权利
NSLocationWhenInUseUsageDescription

现在作为 Objective-C 示例,在读取网络信息之前首先使用以下命令检查位置访问是否已被接受CNCopyCurrentNetworkInfo

- (void)fetchSSIDInfo {
    NSString *ssid = NSLocalizedString(@"not_found", nil);

    if (@available(iOS 13.0, *)) {
        if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
            NSLog(@"User has explicitly denied authorization for this application, or location services are disabled in Settings.");
        } else {
            CLLocationManager* cllocation = [[CLLocationManager alloc] init];
            if(![CLLocationManager locationServicesEnabled] || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined){
                [cllocation requestWhenInUseAuthorization];
                usleep(500);
                return [self fetchSSIDInfo];
            }
        }
    }

    NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces();
    id info = nil;
    for (NSString *ifnam in ifs) {
        info = (__bridge_transfer id)CNCopyCurrentNetworkInfo(
            (__bridge CFStringRef)ifnam);

        NSDictionary *infoDict = (NSDictionary *)info;
        for (NSString *key in infoDict.allKeys) {
            if ([key isEqualToString:@"SSID"]) {
                ssid = [infoDict objectForKey:key];
            }
        }
    }        
        ...
    ...
}
Run Code Online (Sandbox Code Playgroud)