iPhone erhalten SSID ohne private Bibliothek

154

Ich habe eine kommerzielle App, die einen völlig legitimen Grund hat, die SSID des Netzwerks zu sehen, mit dem sie verbunden ist: Wenn sie für ein Hardwaregerät eines Drittanbieters mit einem Adhoc-Netzwerk verbunden ist, muss sie anders funktionieren als sie ist mit dem Internet verbunden.

Alles, was ich über das Abrufen der SSID gesehen habe, sagt mir, dass ich Apple80211 verwenden muss, von dem ich verstehe, dass es eine private Bibliothek ist. Ich habe auch gelesen, dass Apple die App nicht genehmigt, wenn ich eine private Bibliothek verwende.

Bin ich zwischen einem Apfel und einem harten Ort festgefahren oder fehlt mir hier etwas?

Steve Reed Sr.
quelle
Siehe auch
Senseful

Antworten:

186

Ab iOS 7 oder 8 können Sie dies tun (benötigen Sie die Berechtigung für iOS 12+, wie unten gezeigt):

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

Beispielausgabe:

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

Beachten Sie, dass vom Simulator keine Wenns unterstützt werden. Testen Sie auf Ihrem Gerät.

iOS 12

Sie müssen den Zugriff auf WLAN-Informationen über Funktionen aktivieren.

Wichtig Um diese Funktion in iOS 12 und höher zu verwenden, aktivieren Sie die Funktion zum Zugriff auf WLAN-Informationen für Ihre App in Xcode. Wenn Sie diese Funktion aktivieren, fügt Xcode Ihrer Berechtigungsdatei und App-ID automatisch die Berechtigung zum Zugriff auf WLAN-Informationen hinzu. Dokumentationslink

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

}
Jeremy W. Sherman
quelle
8
Vielen Dank! Wenn Sie ARC verwenden, sollte es folgendermaßen aussehen: - (id) fetchSSIDInfo {NSArray * ifs = ( bridge_transfer id) CNCopySupportedInterfaces (); NSLog (@ "% s: Unterstützte Schnittstellen:% @", _func , ifs); id info = nil; für (NSString * ifnam in ifs) {info = ( bridge_transfer id) CNCopyCurrentNetworkInfo (( _bridge CFStringRef) ifnam); NSLog (@ "% s:% @ =>% @", __func , ifnam, info); if (info && [info count]) {break; }} return info; }
Elsurudo
1
+1 Funktioniert super! Vergessen Sie nicht, das [+] Framework zu Ihrem Projekt hinzuzufügen / zu verknüpfen. Wenn Sie bei dieser Methode seltsame Kompilierungsfehler sehen, ist dies wahrscheinlich Ihr Problem. Um beispielsweise die SSID aus dem zurückgegebenen Wörterbuch abzurufen, verwenden Sie // Ein Wörterbuchobjekt abrufen, das die Informationen des Netzwerks enthält, mit dem das iPhone verbunden ist. NSDictionary * networkDict = [self fetchSSIDInfo]; // Wählen Sie die SSID aus den Netzwerkinformationen aus. NSString * iPhoneNetworkSSID = [networkDict objectForKey: @ "SSID"];
Groot
Weiß jemand, was BSSID ist? Es sieht aus wie die MAC-Adresse eines Routers, ist es aber eigentlich nicht. Es ist auch nicht die MAC-Adresse des Geräts.
Peetonn
1
@Filip Der ARC-freundliche Code wurde aktualisiert, indem modulare Includes ( @importanstelle von #import) verwendet wurden. Clang verknüpft automatisch das erforderliche Framework, wenn ein Modul und nicht nur ein Header importiert wird.
Jeremy W. Sherman
1
Für die Beta-Version von iOS 13 ist jetzt zusätzlich zur Möglichkeit CNCopyCurrentNetworkInfo, nützliche Informationen zurückzugeben, eine Standortberechtigung erforderlich . Andernfalls wird es zurückgegeben nil. Siehe: stackoverflow.com/questions/56583650/…
RedMatt
61

Hier ist die bereinigte ARC-Version, die auf dem Code von @ elsurudo basiert:

- (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;
}
esad
quelle
1
Dies sollte wirklich die bevorzugte Antwort sein, da ARC verwendet wird. Ich habe dies von Anfang an verpasst, nur weil es nicht die angebotene Antwort war.
Johan Karlsson
@mindbomb ist richtig, hier ist eine Frage zu diesem Problem: stackoverflow.com/questions/31555640/…
Newenglander
Ja, Apple hat die CaptiveNetwork-API wieder aktiviert, nachdem die iOS9-Betas nicht mehr unterstützt wurden.
mindbomb
@mindbomb ist das noch der Fall? Ich habe Probleme, dies umzusetzen.
SamYoungNY
@SamYoungNY Beachten Sie, dass dies nur auf dem Gerät funktioniert, auf dem Simulator wird ein leeres zurückgegeben
esad
60

UPDATE FÜR iOS 10 und höher

CNCopySupportedInterfaces ist in iOS 10 nicht mehr veraltet. ( API-Referenz )

Sie müssen SystemConfiguration / CaptiveNetwork.h importieren und SystemConfiguration.framework zu den verknüpften Bibliotheken Ihres Ziels hinzufügen (in Erstellungsphasen).

Hier ist ein Code-Snippet in Kürze (RikiRiocmas Antwort) :

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

( Wichtig: CNCopySupportedInterfaces gibt im Simulator null zurück.)

Für Ziel-c siehe Esads Antwort hier und unten

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

UPDATE FÜR iOS 9

Ab iOS 9 ist Captive Network veraltet *. ( Quelle )

* In iOS 10 nicht mehr veraltet, siehe oben.

Es wird empfohlen, NEHotspotHelper ( Quelle ) zu verwenden.

Sie müssen Apple eine E-Mail an [email protected] senden und Berechtigungen anfordern. ( Quelle )

Beispielcode ( Nicht mein Code. Siehe Antwort von 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;
}

Randnotiz: Ja, sie haben CNCopySupportedInterfaces in iOS 9 abgelehnt und ihre Position in iOS 10 umgekehrt. Ich habe mit einem Apple-Netzwerktechniker gesprochen, und die Umkehrung erfolgte, nachdem so viele Leute Radars eingereicht und in den Apple Developer-Foren über das Problem gesprochen hatten.

Emin Israfil iOS
quelle
Ich habe von Apple die Genehmigung zur Verwendung der Netzwerkerweiterung erhalten, aber ich habe immer noch ein leeres Array von [NEHotspotHelper unterstütztNetworkInterfaces] erhalten. Kennen Sie den möglichen Grund?
JZAU
28

Dies funktioniert bei mir auf dem Gerät (nicht Simulator). Stellen Sie sicher, dass Sie das Systemkonfigurationsframework hinzufügen.

#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;
}
Chris
quelle
10

Dieser Code funktioniert gut, um die SSID zu erhalten.

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

Und das ist das Ergebnis:

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

}}

Jameel
quelle
1
Hat perfekt funktioniert.
Yomo
9

Wenn Sie iOS 12 ausführen, müssen Sie einen zusätzlichen Schritt ausführen. Ich habe mich bemüht, diesen Code zum Laufen zu bringen, und habe ihn schließlich auf Apples Website gefunden: "Wichtig Um diese Funktion in iOS 12 und höher zu verwenden, aktivieren Sie die Funktion zum Zugriff auf WLAN-Informationen für Ihre App in Xcode. Wenn Sie diese Funktion aktivieren, wird Xcode automatisch aktiviert Fügt Ihrer Berechtigungsdatei und App-ID die Berechtigung "Zugriff auf WiFi-Informationen" hinzu. " https://developer.apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo

Muvimotv
quelle
Danke, es hat mein Problem behoben!
David72
5

Hier ist die kurze und süße Swift-Version.

Denken Sie daran, das Framework zu verknüpfen und zu importieren:

import UIKit
import SystemConfiguration.CaptiveNetwork

Definieren Sie die Methode:

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

Rufen Sie die Methode auf, wenn Sie sie benötigen:

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

Wie an anderer Stelle erwähnt, funktioniert dies nur auf Ihrem iDevice. Wenn nicht über WLAN, gibt die Methode null zurück - daher die Option.

n.Drake
quelle
2

Für iOS 13

Ab iOS 13 benötigt Ihre App auch Core Location-Zugriff, um die CNCopyCurrentNetworkInfo Funktion nutzen zu können, es sei denn, sie hat das aktuelle Netzwerk konfiguriert oder verfügt über VPN-Konfigurationen:
Auszug aus https://developer.apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo?language=objc

Dies ist also das, was Sie benötigen (siehe Apple-Dokumentation ):
- Verknüpfen Sie die CoreLocation.frameworkBibliothek
- Hinzufügen location-servicesals UIRequiredDeviceCapabilitiesSchlüssel / Wert in Info.plist
- Hinzufügen eines NSLocationWhenInUseUsageDescriptionSchlüssels / Werts in Info.plist, der beschreibt, warum Ihre App Core Location benötigt
- Fügen Sie das "Access WiFi" hinzu Information "Berechtigung für Ihre App

Überprüfen Sie nun als Objective-C-Beispiel zunächst, ob der Standortzugriff akzeptiert wurde, bevor Sie die Netzwerkinformationen lesen 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];
            }
        }
    }        
        ...
    ...
}
Francois B.
quelle
Das ist unter iOS13 erforderlich, sonst hast du null für CNCopyCurrentNetworkInfo ()
Franz Wang
@ Zucker ja in der Tat iOS13 - siehe die erste Zeile meiner Antwort
Francois B