iPhone özel kütüphane olmadan SSID alır


154

Bağlı olduğu ağın SSID'sini görmek için tamamen meşru bir nedeni olan ticari bir uygulamam var: 3. taraf bir donanım cihazı için bir Adhoc ağına bağlıysa, olduğundan daha farklı bir şekilde çalışması gerekir internete bağlanıldı.

SSID'yi almakla ilgili gördüğüm her şey bana özel bir kütüphane olduğunu düşündüğüm Apple80211 kullanmam gerektiğini söylüyor. Ayrıca özel bir kütüphane kullanırsam Apple'ın uygulamayı onaylamayacağını da okudum.

Bir Apple ile sert bir yer arasında mı sıkıştım, yoksa burada eksik olduğum bir şey var mı?


Yanıtlar:


186

İOS 7 veya 8'den itibaren bunu yapabilirsiniz (aşağıda gösterildiği gibi iOS 12+ için Yetki gerekir):

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

Örnek çıktı:

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

Simülatörde hiçbir ifs desteklenmediğini unutmayın. Cihazınızda test edin.

iOS 12

Erişim wifi bilgisini yeteneklerden etkinleştirmelisiniz.

Önemli Bu işlevi iOS 12 ve sonraki sürümlerde kullanmak için, Xcode'da uygulamanız için WiFi Bilgilerine Eriş özelliğini etkinleştirin. Bu özelliği etkinleştirdiğinizde Xcode, Access WiFi Information yetkisini otomatik olarak yetkiler dosyanıza ve Uygulama Kimliğinize ekler. Dokümantasyon bağlantısı

Hızlı 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
Teşekkürler! ARC kullanıyorsanız, şöyle görünmesi gerekir: - (id) fetchSSIDInfo {NSArray * ifs = ( bridge_transfer id) CNCopySupportedInterfaces (); NSLog (@ "% s: Desteklenen arabirimler:% @", _func , ifs); id bilgisi = nil; (ifs içinde NSString * ifnam) için {info = ( bridge_transfer id) CNCopyCurrentNetworkInfo (( _bridge CFStringRef) ifnam); NSLog (@ "% s:% @ =>% @", __func , ifnam, bilgi); if (info && [bilgi sayısı]) {break; } dönüş bilgisi; }
elsurudo

1
+1 Harika çalışıyor! [+] Çerçevesini projenize eklemeyi / bağlamayı unutmayın. Muhtemelen sizin probleminiz olan bu yöntemi kullanırken garip derleme hataları görüyorsanız. Örneğin, SSID'yi döndürülen sözlükten almak için // iPhone'un ağ bilgisini içeren bir sözlük nesnesi almak için NSDictionary * networkDict = [self fetchSSIDInfo]; // Ağ bilgisinden SSID'yi seçin NSString * iPhoneNetworkSSID = [networkDict objectForKey: @ "SSID"];
Groot

BSSID'in ne olduğunu bilen var mı? bir yönlendiricinin MAC adresine benziyor, ama aslında değil. ikisi de cihazın MAC adresi değil.
peetonn

1
@Filip Güncellenmiş ARC dostu kod, bunu modüler içerir ( @importyerine #import) kullanarak ele alır . Yalnızca bir başlık yerine bir modül içe aktarıldığında Clang otomatik olarak gerekli çerçeveye bağlanır.
Jeremy

1
iOS 13 beta artık CNCopyCurrentNetworkInfoyararlı bilgiler döndürme özelliğine ek olarak konum izni gerektiriyor ; aksi halde geri döner nil. Bakınız: stackoverflow.com/questions/56583650/…
RedMatt

61

@ Elsurudo'nun koduna dayanan temizlenmiş ARC sürümü:

- (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 kullandığı için bu gerçekten tercih edilen cevap olmalı. Başından beri cevap vermedim, çünkü bu cevaplanan cevap değildi.
Johan Karlsson

@mindbomb doğru, işte bu sorun hakkında bir soru: stackoverflow.com/questions/31555640/…
newenglander

Evet, Apple, iOS9 betalarında kullanımdan kaldırıldıktan sonra CaptiveNetwork API'sını yeniden etkinleştirdi ..
mindbomb

@mindbomb hala böyle mi? Bunu uygularken sorunlar yaşıyorum.
SamYoungNY

@SamYoungNY Bunun sadece cihazda çalıştığını, Simülatörde boş bir döndürüldüğünü unutmayın
esad

60

İOS 10 ve üstü için GÜNCELLEME

CNCopySupportedInterfaces artık iOS 10'da kullanımdan kaldırılmıyor ( API Başvurusu )

SystemConfiguration / CaptiveNetwork.h dosyasını içe aktarmanız ve hedefinizin Bağlantılı Kütüphanelerine (derleme aşamaları altında) SystemConfiguration.framework eklemeniz gerekir.

İşte hızlıca bir kod snippet'i (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
    }
}

( Önemli: CNCopySupportedInterfaces simülatörde sıfır döndürür.)

Objective-c için Esad'ın buradaki ve aşağıdaki cevabına bakınız.

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

İOS 9 İÇİN GÜNCELLEME

İOS 9'dan itibaren Sabit Ağ kullanımdan kaldırıldı *. ( kaynak )

* Artık iOS 10'da kullanımdan kaldırılmadı, yukarıya bakın.

NEHotspotHelper ( kaynak ) kullanmanız önerilir

Apple'a networkextension@apple.com adresinden e-posta göndermeniz ve yetkiler istemeniz gerekir. ( kaynak )

Örnek Kod ( Kodum değil. Pablo A'nın cevabına bakınız ):

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

Yan not: Evet, iOS 9'daki CNCopySupportedInterfaces'ı kullanımdan kaldırdılar ve iOS 10'daki konumlarını tersine çevirdiler. Bir Apple ağ mühendisiyle konuştum ve geri dönüş, birçok insanın Radar'ları dosyalayıp Apple Geliştirici forumlarındaki sorun hakkında konuştuktan sonra geldi.


Apple tarafından ağ uzantısını kullanmak için onaylandım, ancak yine de [NEHotspotHelper destekliNetworkInterfaces] 'den boş bir dizi aldım. Olası nedeni biliyor musun?
JZAU

28

Bu benim için cihazda çalışıyor (simülatörde değil). Sistem yapılandırma çerçevesini eklediğinizden emin olun.

#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 almak için bu kod iyi çalışır.

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

Ve bu da sonuçlar:

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

}


1
Mükemmel çalıştı.
Yomo

9

İOS 12 çalıştırıyorsanız, fazladan bir adım atmanız gerekir. Bu kodun çalışmasını sağlamak için uğraşıyorum ve nihayet bunu Apple'ın sitesinde buldum: "Önemli Bu işlevi iOS 12 ve sonraki sürümlerde kullanmak için, Xcode'da uygulamanız için Erişim WiFi Bilgisi özelliğini etkinleştirin. Bu özelliği etkinleştirdiğinizde, Xcode otomatik olarak Access WiFi Bilgileri yetkisini, yetkilendirmeler dosyanıza ve Uygulama Kimliğinize ekler. " https://developer.apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo


Teşekkür ederim, sorunumu çözdü!
david72


5

İşte kısa ve tatlı Swift versiyonu.

Çerçeveyi bağlamayı ve içe aktarmayı unutmayın:

import UIKit
import SystemConfiguration.CaptiveNetwork

Yöntemi tanımlayın:

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

İhtiyacınız olduğunda yöntemi çağırın:

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

Başka bir yerde belirtildiği gibi, bu yalnızca iDevice'inizde çalışır. WiFi'de olmadığında, yöntem isteğe bağlı olarak geri döner.


2

İOS 13 için

İOS 13'ten itibaren uygulamanız , geçerli ağı yapılandırmadıkça veya VPN yapılandırmalarına sahip olmadığı sürece CNCopyCurrentNetworkInfo işlevi kullanmak için Temel Konum erişimine ihtiyaç duyar :
https://developer.apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo?language=objc adresinden alıntı

Bu yüzden (bkz gerek budur elma belgelerine ):
- Bağlantı CoreLocation.frameworkkütüphanesi
- Ekleme location-servicesbir şekilde UIRequiredDeviceCapabilitiesAnahtar / Değer Info.plist
- Bir ekleyin NSLocationWhenInUseUsageDescriptionAnahtar / Değer Info.plist uygulama Çekirdek Konum gerektirir neden açıklayan
"Erişim WiFi Ekle - Uygulamanız için bilgi "yetkisi

Şimdi bir Objective-C örneği olarak, önce ağ bilgilerini okumadan önce konum erişiminin kabul edilip edilmediğini kontrol edin 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];
            }
        }
    }        
        ...
    ...
}

Yani aksi takdirde var iOS13 gereklidir nil için ) CNCopyCurrentNetworkInfo (
Franz Wang

Şeker Evet gerçekten iOS13 - cevabımın ilk satırına bakın
Francois B
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.