iPhone รับ SSID โดยไม่ต้องมีห้องสมุดส่วนตัว


154

ฉันมีแอพเชิงพาณิชย์ที่มีเหตุผลที่ถูกต้องสมบูรณ์ในการดู SSID ของเครือข่ายที่เชื่อมต่อกับ: หากมีการเชื่อมต่อกับเครือข่าย Adhoc สำหรับอุปกรณ์ฮาร์ดแวร์ของบุคคลที่สามจะต้องทำงานในลักษณะที่แตกต่างจากที่เป็น เชื่อมต่อกับอินเทอร์เน็ต

ทุกสิ่งที่ฉันเห็นเกี่ยวกับการได้รับ SSID บอกฉันว่าฉันต้องใช้ Apple80211 ซึ่งฉันเข้าใจว่าเป็นห้องสมุดส่วนตัว ฉันยังอ่านด้วยว่าถ้าฉันใช้ห้องสมุดส่วนตัว Apple จะไม่อนุมัติแอพ

ฉันติดอยู่ระหว่าง Apple กับสถานที่ที่ยากลำบากหรือมีบางสิ่งที่ฉันขาดหายไปที่นี่หรือไม่?


ที่เกี่ยวข้อง: stackoverflow.com/questions/351954/…
Senseful

คำตอบ:


186

ตั้งแต่ 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>;
}

โปรดทราบว่าไม่มีการสนับสนุน ifs บนตัวจำลอง ทดสอบบนอุปกรณ์ของคุณ

iOS 12

คุณต้องเปิดใช้งานการเข้าถึงข้อมูล wifi จากความสามารถ

สิ่งสำคัญหากต้องการใช้ฟังก์ชันนี้ใน iOS 12 และใหม่กว่าให้เปิดใช้งานความสามารถในการเข้าถึงข้อมูล WiFi สำหรับแอปของคุณใน Xcode เมื่อคุณเปิดใช้งานความสามารถนี้ Xcode จะเพิ่มการให้สิทธิ์ Access WiFi Information ลงในไฟล์การให้สิทธิ์และรหัสแอปของคุณโดยอัตโนมัติ ลิงค์เอกสาร

สวิฟท์ 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

}

8
ขอบคุณ! หากคุณใช้ ARC นี่คือสิ่งที่ควรมีลักษณะ: - (id) fetchSSIDInfo {NSArray * ifs = ( bridge_transfer id) CNCopySupportedInterfaces (id) NSLog (@ "% s: อินเทอร์เฟซที่รองรับ:% @", _func , ifs); id ข้อมูล = ไม่มี; สำหรับ (NSString * ifnam ใน ifs) {info = ( bridge_transfer id) CNCopyCurrentNetworkInfo (( _bridge CFStringRef) ifnam); NSLog (@ "% s:% @ =>% @", __func , ifnam, info); if (info && [นับข้อมูล]) {break; }} ส่งคืนข้อมูล }
elsurudo

1
+1 ใช้งานได้ดี! อย่าลืมเพิ่ม / เชื่อมโยงกรอบ [+] กับโครงการของคุณ หากคุณเห็นข้อผิดพลาดในการรวบรวมแปลก ๆ เมื่อใช้วิธีนี้ซึ่งอาจเป็นปัญหาของคุณ หากต้องการรับ SSID จากการใช้พจนานุกรมที่ส่งคืน // การรับวัตถุพจนานุกรมที่มีข้อมูลของเครือข่ายที่ iPhone เชื่อมต่อกับ NSDictionary * networkDict = [self fetchSSIDInfo]; // เลือก SSID จากข้อมูลเครือข่าย NSString * iPhoneNetworkSSID = [networkDict objectForKey: @ "SSID"];
Groot

ไม่มีใครรู้ว่า BSSID คืออะไร? ดูเหมือนว่าที่อยู่ MAC ของเราเตอร์ แต่จริง ๆ แล้วไม่ใช่ ไม่ใช่ที่อยู่ MAC ของอุปกรณ์
peetonn

1
@Filip อัปเดตโค้ดที่เป็นมิตรกับ ARC แล้วโดยใช้โมดูลแบบรวม ( @importแทน#import) เสียงดังกราวจะเชื่อมโยงโดยอัตโนมัติในกรอบงานที่จำเป็นเมื่อมีการนำเข้าโมดูลแทนที่จะเป็นเพียงส่วนหัว
Jeremy W. Sherman

1
iOS 13 เบต้าต้องได้รับอนุญาตจากตำแหน่งนอกเหนือจากความสามารถในCNCopyCurrentNetworkInfoการส่งคืนข้อมูลที่เป็นประโยชน์ nilมิฉะนั้นก็จะส่งกลับ ดู: stackoverflow.com/questions/56583650/…
RedMatt

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

1
นี่ควรเป็นคำตอบที่ต้องการเนื่องจากใช้ ARC ฉันพลาดสิ่งนี้ตั้งแต่เริ่มต้นเพียงเพราะมันไม่ใช่คำตอบที่ถูกเสนอ
Johan Karlsson

@mindbomb ถูกต้องต่อไปนี้เป็นคำถามเกี่ยวกับปัญหานี้: stackoverflow.com/questions/31555640/…
newenglander

ใช่, Apple เปิดใช้งาน CaptiveNetwork API อีกครั้งหลังจากที่เลิกใช้งานใน iOS9 betas ..
mindbomb

@mindbomb ยังคงเป็นกรณีนี้หรือไม่? ฉันมีปัญหาในการใช้งานสิ่งนี้
SamYoungNY

@SamYoungNY โปรดทราบว่ามันใช้งานได้บนอุปกรณ์เท่านั้นใน Simulator จะคืนค่าว่างเปล่า
esad

60

อัปเดตสำหรับ 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 ดูคำตอบของ 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 Captive Network เลิกใช้แล้ว (ที่มา )

* ไม่เลิกใช้แล้วใน iOS 10 ดูด้านบน

ขอแนะนำให้คุณใช้ NEHotspotHelper (ต้นฉบับ )

คุณจะต้องส่งอีเมลแอปเปิ้ลที่ 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;
}

หมายเหตุด้านข้าง: ใช่พวกเขาเลิกใช้ CNCopySupportedInterfaces ใน iOS 9 และกลับตำแหน่งใน iOS 10 ฉันได้พูดคุยกับวิศวกรเครือข่ายของ Apple และการพลิกกลับเกิดขึ้นหลังจากผู้คนจำนวนมากยื่น Radars และพูดถึงปัญหาในฟอรัม Apple Developer


ฉันได้รับการอนุมัติจาก apple ให้ใช้ส่วนขยายเครือข่าย แต่ฉันยังคงได้รับอาร์เรย์ว่างจาก [NEHotspotHelper รองรับ NetworkInterfaces] คุณรู้เหตุผลที่เป็นไปได้หรือไม่
JZAU

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

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

}


1
ทำงานได้อย่างสมบูรณ์แบบ
Yomo

9

หากคุณใช้ iOS 12 คุณจะต้องทำขั้นตอนเพิ่มเติม ฉันพยายามอย่างหนักที่จะทำให้รหัสนี้ใช้งานได้และในที่สุดก็พบสิ่งนี้บนเว็บไซต์ของ Apple: "สิ่งสำคัญในการใช้ฟังก์ชั่นนี้ใน iOS 12 และใหม่กว่าเปิดใช้งานความสามารถในการเข้าถึงข้อมูล WiFi สำหรับแอปของคุณใน Xcode เมื่อคุณเปิดใช้งาน เพิ่มสิทธิ์การเข้าถึงข้อมูล Access WiFi ให้กับไฟล์การให้สิทธิ์และรหัสแอปของคุณ " https://developer.apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo


ขอบคุณมันแก้ไขปัญหาของฉัน!
david72

7

ดู CNCopyCurrentNetworkInfo ใน CaptiveNetwork: http://developer.apple.com/library/ios/#documentation/SystemConfiguration/Reference/CaptiveNetworkRef/Reference/reference.html


5

นี่คือเวอร์ชั่น 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 วิธีนี้จะคืนค่าเป็นศูนย์ซึ่งเป็นตัวเลือก


2

สำหรับ iOS 13

ตั้งแต่ iOS 13 แอปของคุณยังต้องมีการเข้าถึงตำแหน่งหลักเพื่อที่จะใช้CNCopyCurrentNetworkInfo ฟังก์ชั่นนอกจากจะกำหนดค่าเครือข่ายปัจจุบันหรือมีการกำหนดค่า VPN:
ตัดตอนมาจาก https://developer.apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo?language=objc

นี่คือสิ่งที่คุณต้องการ (ดูเอกสารประกอบของ Apple ):
- เชื่อมโยงCoreLocation.frameworkไลบรารี
- เพิ่มlocation-servicesเป็นUIRequiredDeviceCapabilitiesคีย์ / ค่าในInfo.plist
- เพิ่มNSLocationWhenInUseUsageDescriptionคีย์ / ค่าในInfo.plistอธิบายว่าทำไมแอปของคุณต้องใช้ตำแหน่งหลัก
- เพิ่ม "Access WiFi" ข้อมูล "สิทธิ์สำหรับแอปของคุณ

ตอนนี้เป็นตัวอย่างวัตถุประสงค์ -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];
            }
        }
    }        
        ...
    ...
}

ที่จำเป็นสำหรับ iOS13 ไม่เช่นนั้นคุณจะได้รับศูนย์สำหรับCNCopyCurrentNetworkInfo ()
Franz Wang

@Sugar ใช่ iOS13 แน่นอน - ดูบรรทัดแรกของคำตอบของฉัน
Francois B
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.