155

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

我所看到的有关获取 SSID 的所有信息都告诉我必须使用 Apple80211,据我所知,它是一个私有库。我还读到,如果我使用私人图书馆,Apple 将不会批准该应用程序。

我是被困在苹果和困难的地方之间,还是我在这里遗漏了什么?

4

9 回答 9

187

从 iOS 7 或 8 开始,您可以执行此操作(需要 iOS 12+ 的权利,如下所示):

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

示例输出:

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。在您的设备上进行测试。

iOS 12

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

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

斯威夫特 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

}
于 2011-03-04T20:34:47.780 回答
62

iOS 10 及更高版本的更新

CNCopySupportedInterfaces 在 iOS 10 中不再被弃用。(API 参考

您需要导入SystemConfiguration/CaptiveNetwork.h并将SystemConfiguration.framework添加到目标的链接库(在构建阶段)。

这是 swift (RikiRiocma's Answer)中的代码片段:

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 在模拟器上返回 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;
}

iOS 9 更新

自 iOS 9 起,强制网络已弃用*。(来源

*在 iOS 10 中不再被弃用,见上文。

建议您使用 NEHotspotHelper ( source )

您需要通过 networkextension@apple.com 向苹果发送电子邮件并请求授权。(来源

示例代码(不是我的代码。见 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;
}

旁注:是的,他们在 iOS 9 中弃用了 CNCopySupportedInterfaces 并在 iOS 10 中改变了他们的立场。我与一位 Apple 网络工程师进行了交谈,在这么多人提交 Radars 并在 Apple 开发者论坛上谈论这个问题之后,他们的立场发生了逆转。

于 2015-10-14T18:06:12.740 回答
61

这是清理后的 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;
}
于 2013-01-12T00:05:17.190 回答
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;
}
于 2013-03-06T00:10:35.430 回答
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;
}

这是结果:

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

}

于 2013-07-14T21:26:46.223 回答
9

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

于 2018-07-08T17:06:22.090 回答
7

请参阅 CaptiveNetwork 中的 CNCopyCurrentNetworkInfo:http: //developer.apple.com/library/ios/#documentation/SystemConfiguration/Reference/CaptiveNetworkRef/Reference/reference.html

于 2011-03-04T20:32:51.167 回答
5

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

记得链接并导入框架:

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 上时,该方法将返回 nil - 因此是可选的。

于 2015-06-01T14:02:47.960 回答
5

对于 iOS 13

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

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

现在作为一个 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];
            }
        }
    }        
        ...
    ...
}
于 2019-10-15T08:41:06.983 回答