在CaptiveNetwork被弃用并且对Wifi名称的调用已经被阻止后,如何在iOS9中获取Wifi SSID

36

直到今天,我使用CaptiveNetwork接口来显示当前连接的Wifi名称。iOS 9预发布参考资料已经说明,CaptiveNetwork方法现在被废弃了,但它们一开始还是可以使用的。

最新版本似乎已经阻止了这些调用(可能是出于隐私方面的考虑?)

还有其他方法可以获取当前Wifi的名称吗?

这就是我直到今天获取SSID的方式,但现在你只会得到nil:

#import <SystemConfiguration/CaptiveNetwork.h>

NSString *wifiName = nil;  
NSArray *interFaceNames = (__bridge_transfer id)CNCopySupportedInterfaces(); 

for (NSString *name in interFaceNames) { 
    NSDictionary *info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)name); 

    if (info[@"SSID"]) { 
        wifiName = info[@"SSID"]; 
    } 
} 
8个回答

32

注册您的应用程序作为热点助手。

#import <NetworkExtension/NetworkExtension.h>  

NSArray * networkInterfaces = [NEHotspotHelper supportedNetworkInterfaces];  
NSLog(@"Networks %@",networkInterfaces);  

更新(2015年9月11日)

以下被禁用的网络托管API已经在最新版的iOS 9中重新启用:

  • CNCopySupportedInterfaces
  • CNCopyCurrentNetworkInfo

更新(2015年9月16日)

如果您仍然喜欢使用NetworkExtension并获得了苹果授权添加权限,则可以通过以下方式获取WiFi信息:

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

NetworkExtension 提供了一些额外的信息,例如安全性、自动加入或信号强度。同时它还允许您在后台模式下为WiFi设置凭证,当用户扫描周围的WiFi时。


好的,看起来这可能是一种可行的方法。 但是,我们是否被允许使用热点助手授权来显示当前的WiFi SSID还有待商榷,因为这个授权需要通过电子邮件向苹果申请。你已经以这种方式使用过它吗? - Thyraz
2
它不起作用了... 它返回NIL,因为CNCopySupportedInterfaces()也是如此。 - Wasim Ahmed
你首先需要通过电子邮件将你的应用程序注册为热点助手 https://forums.developer.apple.com/message/30657#30657 - Pablo A.
4
@Forke Lewiguez是第一个回答苹果已重新启用旧方法的人。 如果您不是热点助手应用程序,苹果会拒绝请求热点助手授权。所以Lewiguez在苹果给我发邮件告诉我他们不会给我授权但由于收到了大量请求,他们重新激活了旧方法时,回答了同一时间的问题。 - Thyraz
1
我不确定,您是否能够在分发的配置文件中使用企业应用程序的权限?我没有找到相关信息,也无法使其正常工作... - lewiguez
显示剩余3条评论

11
在iOS 9的GM版本中,看起来这个功能已经重新启用了。事实上,在在线文档中它甚至没有被列为弃用,但是CaptiveNetwork头文件确实有以下内容:
CNCopySupportedInterfaces (void) __OSX_AVAILABLE_BUT_DEPRECATED_MSG(__MAC_10_8, __MAC_NA, __IPHONE_4_1, __IPHONE_9_0, CN_DEPRECATION_NOTICE);

所以,在 iOS 9 GM 上可以工作,但不确定能持续多久 :)


是的,我们的应用程序刚刚检查过了。在测试版中,它被禁用了。太好了。 - bk138
是的,我甚至收到了苹果公司回复我的邮件,他们在最新版本中重新启用了它。 :) - Thyraz
它在在线文档中被列为已弃用:https://developer.apple.com/library/prerelease/ios/documentation/SystemConfiguration/Reference/CaptiveNetworkRef/index.html - user102008
现在它没有启用!似乎在最终版本中出现了故障。 - MatterGoal
@MatterGoal,使用最终版本在这里运行良好。 - Thyraz

9

即使在Swift 4.1和4.2中,abdullahselek的答案仍然是正确的。

一个小细节是,在iOS 12中,您必须进入应用程序项目的功能部分,并启用访问WiFi信息功能。它将向您的项目添加一个授权条目,并允许函数调用CNCopyCurrentNetworkInfo正常工作。

如果您不这样做,该函数将只返回nil。运行时不会显示有关缺少授权的错误或警告。

有关更多信息,请参见下面的链接到苹果文档。

https://developer.apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo


谢谢你! - Brandon Shega
很高兴能帮到你,Brandon。第一次尝试时,它确实让人沮丧,因为它没有抛出任何错误或提供有关为什么最初无法工作的信息。 - FerrousGuy
此外,应用程序应该向CLLocationManager请求权限,否则它也无法工作。 - Samball

8

确认在2017年4月27日,Captive Network仍然适用于Swift 3.1XCode 8.3

对于 Swift > 3.0 的版本

func printCurrentWifiInfo() {
  if let interface = CNCopySupportedInterfaces() {
    for i in 0..<CFArrayGetCount(interface) {
      let interfaceName: UnsafeRawPointer = CFArrayGetValueAtIndex(interface, i)
      let rec = unsafeBitCast(interfaceName, to: AnyObject.self)
      if let unsafeInterfaceData = CNCopyCurrentNetworkInfo("\(rec)" as CFString), let interfaceData = unsafeInterfaceData as? [String : AnyObject] {
        // connected wifi
        print("BSSID: \(interfaceData["BSSID"]), SSID: \(interfaceData["SSID"]), SSIDDATA: \(interfaceData["SSIDDATA"])")
      } else {
        // not connected wifi
      }
    }
  }
}

对于Objective-C


NSArray *interFaceNames = (__bridge_transfer id)CNCopySupportedInterfaces();

for (NSString *name in interFaceNames) {
  NSDictionary *info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)name);

  NSLog(@"wifi info: bssid: %@, ssid:%@, ssidData: %@", info[@"BSSID"], info[@"SSID"], info[@"SSIDDATA"]);
 }

4
如前所述,CaptiveNetwork与Xcode 8.3及以上版本兼容。以下是针对Swift 3Swift 4Objective-C的代码片段。

Swift 3 & 4

import SystemConfiguration.CaptiveNetwork

internal class SSID {

    class func fetchSSIDInfo() -> [String: Any] {
        var interface = [String: Any]()
        if let interfaces = CNCopySupportedInterfaces() {
            for i in 0..<CFArrayGetCount(interfaces){
                let interfaceName = CFArrayGetValueAtIndex(interfaces, i)
                let rec = unsafeBitCast(interfaceName, to: AnyObject.self)
                guard let unsafeInterfaceData = CNCopyCurrentNetworkInfo("\(rec)" as CFString) else {
                    return interface
                }
                guard let interfaceData = unsafeInterfaceData as? [String: Any] else {
                    return interface
                }
                interface = interfaceData
            }
        }
        return interface
    }

}

Objective-C

#import <SystemConfiguration/CaptiveNetwork.h>

+ (NSDictionary *)fetchSSIDInfo
{
    NSArray *interFaceNames = (__bridge_transfer id)CNCopySupportedInterfaces();
    for (NSString *name in interFaceNames)
    {
        NSDictionary *info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)name);
        return info;
    }
    return nil;
}

我能否使用“CaptiveNetwork”获取wifi网络的接收信号强度指示器(RSSI)以及SSID?是否有此方面的示例代码可用?我在Xcode 9.0.1中使用Objective-C。 - santobedi
据我所知,在不使用NEHotspotHelper的应用程序中,无法获取WiFi信号强度。您可以从NEHotspotNetworksignalStrength属性中找到信号强度。 - abdullahselek
它建议我需要从苹果获得许可才能使用NEHotspotHelper。这是真的吗?我只为研究目的编写我的iOS应用程序(我不会提交到App Store),因此我没有付费的iOS证书。我仍然可以使用NEHotspotHelper吗? - santobedi
是的,这是真的。我认为你不能使用。 - abdullahselek
我知道CLBeacon,并且正在使用它来访问iBeacons的RSS信息。我也想访问Wi-Fi设备的RSS信息。目前在iPhone上是否有可能实现?我能够使用Android手机做到这一点。 - santobedi
显示剩余3条评论

2

现在应该可以在iOS 13.3上正常运行。我正在使用一个相关的Pod库,它使用Objc中的确切函数,并带有Swift包装器。

https://github.com/Feghal/FGRoute


很好!但是现在我该怎么获取列表呢? - ink
@ink 你无法从iOS获取Wifi列表。请参考此线程。https://dev59.com/b1UL5IYBdhLWcg3w-cLr我使用的解决方案是一个硬件设备,它具有独立的wifi接入点和板上的REST服务。它获取wifi列表并通过REST返回。这是一个物联网用例,例如远程门禁应用程序。 - Nick N

1
CaptiveNetwork仍在工作。由于许多请求,苹果可能已经恢复了API。 使用CaptiveNetwork,我们可以获取WiFi网络的SSID。 它甚至在iOS 10中也可以工作。
#import <SystemConfiguration/CaptiveNetwork.h>

NSDictionary *info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)name);

这是输出结果:
Printing description of info:
{
    BSSID = "5*:**:**:**:**:**";
    SSID = Cisco12814;
    SSIDDATA = <43697363 6f313238 3134>;
}

你好,我想知道SSIDDATA是什么意思。谢谢^_^ - beautifulcode
SSIDDATA是SSID的十六进制表示形式。 - Ranjith
@Ranjith,我们能否使用CaptiveNetwork获取接收信号强度指示(RSSI)以及SSID?请提供任何示例代码。 - santobedi

1
CaptiveNetwork仍在工作。但是您需要添加以下内容:

在Entitlements.plist中添加com.apple.developer.networking.wifi-info = true。

此外,您需要在developer.apple.com门户的App ID部分启用访问WiFi信息。

请确保在启用“访问WiFi信息”选项后清理您的环境,并生成新的配置文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接