iPhone dostaje SSID bez prywatnej biblioteki

Mam komercyjną aplikację, która ma całkowicie uzasadniony powód, aby zobaczyć identyfikator SSID sieci, do której jest podłączona: jeśli jest podłączona do sieci Adhoc dla urządzenia sprzętowego innej firmy, musi działać w inny sposób niż w przypadku, gdy jest podłączona do Internetu.

Wszystko, co widziałem o uzyskaniu SSID mówi mi, że muszę używać Apple80211, co rozumiem jest prywatną biblioteką. Czytałem też, że jeśli korzystam z prywatnej biblioteki Apple nie zatwierdzi app.

Utknąłem między jabłkiem a twardym miejscem, czy coś mi tu umyka?

 144
Author: Steve Reed Sr, 2011-03-04

8 answers

W systemie iOS 7 lub 8 możesz to zrobić, wykorzystując ARC i moduły, które automatycznie połączą się w wymaganym frameworku:

@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;
}
[[4]}(jest to modernizacja przykładowego kodu napisanego dla iOS 4.1+. Jedynymi zmianami było wprowadzenie jaśniejszych nazw zmiennych oraz przyjęcie ARC i modułów.)

Przykładowe wyjście:

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

Zauważ, że symulator nie obsługuje żadnych ifs. Przetestuj na swoim urządzeniu.

Przed 4.1, możesz mieć trochę szczęścia spelunking przez Słownik konfiguracji systemu. Na przykład użycie scutil na moim Macu:

$ scutil
> show State:/Network/Interface/en1/AirPort
<dictionary> {
  Power Status : 1
  SecureIBSSEnabled : FALSE
  BSSID : <data> 0xcafecafecafe
  SSID_STR : XXXX
  SSID : <data> 0x012345670123456701234567
  Busy : FALSE
  CHANNEL : <dictionary> {
    CHANNEL : 1
    CHANNEL_FLAGS : 10
  }
}
> exit
 173
Author: Jeremy W. Sherman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-22 15:13:43

Oto wyczyszczona wersja ARC, oparta na kodzie @ 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;
}
 60
Author: esad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-14 22:00:26

Aktualizacja dla systemu iOS 10 i nowszych]}

CNCopySupportedInterfaces nie jest już przestarzały w systemie iOS 10. ( API Reference )

Musisz zaimportować SystemConfiguration / CaptiveNetwork.h i dodaj konfigurację systemu.framework do połączonych bibliotek Twojego celu (w fazie budowania).

Oto fragment kodu w języku swift (odpowiedź Rikiriocmy):

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

(Ważne: CNCopySupportedInterfaces zwraca zero na symulator.)

Aby zapoznać się z Objective-c, Zobacz odpowiedź Esada tutaj i poniżej

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

Aktualizacja dla iOS 9

[[5]}od iOS 9 sieć wewnętrzna jest przestarzała*. (source ) [5]} * nie jest już przestarzały w systemie iOS 10, patrz powyżej.

Zaleca siÄ™ stosowanie NEHotspotHelper (source )

BÄ™dziesz musiaÅ‚ wysÅ‚ać e-mail do apple na [email protected] i żądać uprawnieÅ„. (source )

Przykładowy kod ( nie mój kod. # Patrz Pablo A ODPOWIEDŹ):

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

Uwaga na marginesie: tak, wycofali CNCopySupportedInterfaces w iOS 9 i odwrócili swoją pozycję w iOS 10. Rozmawiałem z inżynierem sieciowym Apple, a odwrócenie nastąpiło po tym, jak wiele osób złożyło radary i wypowiedziało się o tym problemie na forach programistów Apple.

 57
Author: Emin Israfil iOS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-22 21:38:27

To działa u mnie na urządzeniu (nie symulatorze). Upewnij się, że dodałeś systemconfiguration framework.

#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;
}
 27
Author: Chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-06 00:10:35

Ten kod działa dobrze, aby uzyskać 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;
}

A oto wyniki:

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

}

 10
Author: Jameel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-14 21:26:46
 7
Author: onnoweb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-04 20:32:51

Oto krótka i słodka wersja Swift.

Pamiętaj, aby połączyć i zaimportować Framework:

import UIKit
import SystemConfiguration.CaptiveNetwork

Zdefiniuj metodÄ™:

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

Wywołaj metodę, gdy jej potrzebujesz:

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

Jak wspomniano w innym miejscu, działa to tylko na Twoim urządzeniu iDevice. Gdy nie ma WiFi, metoda zwróci nil – stąd opcjonalne.

 6
Author: n.Drake,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-01 14:02:47

Jeśli używasz iOS 12, musisz wykonać dodatkowy krok. Starałem się, aby ten kod działał i w końcu znalazłem to na stronie Apple: "Ważne Aby korzystać z tej funkcji w systemie iOS 12 i nowszym, włącz funkcję dostępu do informacji Wi-Fi dla aplikacji w Xcode. Po włączeniu tej funkcji Xcode automatycznie dodaje uprawnienia dostępu do informacji Wi-Fi do pliku uprawnień i aplikacji Dowód osobisty." https://developer.apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo

 6
Author: Muvimotv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-08 17:06:22