iPhone mendapatkan SSID tanpa perpustakaan pribadi

154

Saya memiliki aplikasi komersial yang memiliki alasan yang sepenuhnya sah untuk melihat SSID dari jaringan yang terhubung: Jika terhubung ke jaringan Adhoc untuk perangkat perangkat keras pihak ke-3, ia harus berfungsi dengan cara yang berbeda daripada jika itu adalah terhubung ke internet.

Semua yang saya lihat tentang mendapatkan SSID memberitahu saya bahwa saya harus menggunakan Apple80211, yang saya pahami adalah perpustakaan pribadi. Saya juga membaca bahwa jika saya menggunakan perpustakaan pribadi Apple tidak akan menyetujui aplikasi.

Apakah saya terjebak di antara Apple dan tempat yang sulit, atau ada sesuatu yang saya lewatkan di sini?

Steve Reed Sr
sumber

Jawaban:

186

Pada iOS 7 atau 8, Anda dapat melakukan ini (perlu Hak untuk iOS 12+ seperti yang ditunjukkan di bawah ini):

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

Contoh output:

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

Perhatikan bahwa tidak ada jika didukung pada simulator. Uji pada perangkat Anda.

iOS 12

Anda harus mengaktifkan akses info wifi dari kemampuan.

Penting Untuk menggunakan fungsi ini di iOS 12 dan yang lebih baru, aktifkan kapabilitas Akses Informasi WiFi untuk aplikasi Anda di Xcode. Ketika Anda mengaktifkan kemampuan ini, Xcode secara otomatis menambahkan hak Akses Informasi WiFi ke file hak Anda dan ID Aplikasi. Tautan dokumentasi

Cepat 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
sumber
8
Terima kasih! Jika Anda menggunakan ARC, berikut ini tampilannya: - (id) fetchSSIDInfo {NSArray * ifs = ( bridge_transfer id) CNCopySupportedInterfaces (); NSLog (@ "% s: Antarmuka yang didukung:% @", _func , ifs); id info = nil; for (NSString * ifnam in ifs) {info = ( bridge_transfer id) CNCopyCurrentNetworkInfo (( _bridge CFStringRef) ifnam); NSLog (@ "% s:% @ =>% @", __func , ifnam, info); if (info && [info count]) {break; }} kembalikan info; }
elsurudo
1
+1 Bermanfaat! Jangan lupa untuk menambahkan / menautkan kerangka kerja [+] ke proyek Anda. Jika Anda melihat kesalahan kompilasi yang aneh saat menggunakan metode ini, itu mungkin masalah Anda. Untuk misalnya mendapatkan SSID dari kamus yang dikembalikan gunakan // Mendapatkan objek kamus yang berisi informasi jaringan yang terhubung dengan iPhone ke NSDictionary * networkDict = [self fetchSSIDInfo]; // Pilih SSID dari informasi jaringan NSString * iPhoneNetworkSSID = [networkDict objectForKey: @ "SSID"];
Groot
apakah ada yang tahu apa itu BSSID? sepertinya alamat MAC dari router, tetapi sebenarnya tidak. juga bukan alamat MAC perangkat.
peetonn
1
@Filip Diperbarui. Alamat kode ramah ARC ini dengan menggunakan modular termasuk ( @importbukan #import). Dentang akan secara otomatis ditautkan dalam kerangka kerja yang diperlukan ketika modul, bukan hanya header, diimpor.
Jeremy W. Sherman
1
iOS 13 beta sekarang memerlukan izin lokasi selain kemampuan untuk CNCopyCurrentNetworkInfomengembalikan informasi yang berguna; jika tidak kembali nil. Lihat: stackoverflow.com/questions/56583650/…
RedMatt
61

Ini versi ARC yang dibersihkan, berdasarkan pada kode @ 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;
}
esad
sumber
1
Ini harus benar-benar jawaban yang disukai karena menggunakan ARC. Saya melewatkan ini sejak awal hanya karena itu bukan jawaban yang disodorkan.
Johan Karlsson
@mindbomb benar, berikut adalah pertanyaan tentang masalah itu: stackoverflow.com/questions/31555640/…
newenglander
ya, Apple mengaktifkan kembali API CaptiveNetwork setelah usang dalam pada iOS9 beta ..
mindbomb
@mbombb apakah ini masih terjadi? Saya mengalami masalah dalam mengimplementasikan ini.
SamYoungNY
@ SamYoungNY Perhatikan bahwa ini hanya berfungsi pada perangkat, pada Simulator yang kosong dikembalikan
esad
60

UPDATE UNTUK iOS 10 dan lebih tinggi

CNCopySupportedInterfaces tidak lagi ditinggalkan di iOS 10. ( Referensi API )

Anda perlu mengimpor SystemConfiguration / CaptiveNetwork.h dan menambahkan SystemConfiguration.framework ke Pustaka Tertaut target Anda (dalam tahap pembuatan).

Berikut ini cuplikan kode dalam swift (Jawaban 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
    }
}

( Penting: CNCopySupportedInterfaces mengembalikan nol pada simulator.)

Untuk Objective-c, lihat jawaban Esad di sini dan di bawah

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

PEMBARUAN UNTUK iOS 9

Pada iOS 9 Captive Network sudah usang *. ( sumber )

* Tidak lagi ditinggalkan di iOS 10, lihat di atas.

Disarankan Anda menggunakan NEHotspotHelper ( sumber )

Anda perlu mengirim email ke apple di [email protected] dan meminta hak. ( sumber )

Kode Contoh ( Bukan kode saya. Lihat jawaban 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;
}

Catatan: Yup, mereka mencela CNCopySupportedInterfaces di iOS 9 dan membalikkan posisi mereka di iOS 10. Saya berbicara dengan insinyur jaringan Apple dan pembalikan itu terjadi setelah begitu banyak orang yang mengajukan Radars dan berbicara tentang masalah ini di forum Pengembang Apple.

Emin Israfil iOS
sumber
Saya mendapat persetujuan Apple untuk menggunakan ekstensi jaringan, tetapi saya masih mendapatkan array kosong dari [NEHotspotHelper didukungNetworkInterfaces]. Apakah Anda tahu kemungkinan alasannya?
JZAU
28

Ini berfungsi untuk saya di perangkat (bukan simulator). Pastikan Anda menambahkan kerangka konfigurasi sistem.

#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
sumber
10

Kode ini berfungsi dengan baik untuk mendapatkan 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;
}

Dan ini hasilnya:

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

}

Jameel
sumber
1
Bekerja dengan sempurna.
Yomo
9

Jika Anda menjalankan iOS 12, Anda perlu melakukan langkah ekstra. Saya telah berjuang untuk membuat kode ini berfungsi dan akhirnya menemukan ini di situs Apple: "Penting Untuk menggunakan fungsi ini di iOS 12 dan yang lebih baru, aktifkan kapabilitas Akses Informasi WiFi untuk aplikasi Anda di Xcode. Ketika Anda mengaktifkan kemampuan ini, Xcode secara otomatis menambahkan hak Akses Informasi WiFi ke file hak dan ID Aplikasi Anda. " https://developer.apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo

Muvimotv
sumber
Terima kasih, ini memperbaiki masalah saya!
david72
5

Inilah versi singkat & manis Swift.

Ingatlah untuk menautkan dan mengimpor Kerangka Kerja:

import UIKit
import SystemConfiguration.CaptiveNetwork

Tetapkan metode:

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

Panggil metode ketika Anda membutuhkannya:

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

Seperti disebutkan di tempat lain, ini hanya berfungsi pada iDevice Anda. Ketika tidak menggunakan WiFi, metode ini akan mengembalikan nol - karenanya opsional.

n.Buat remake
sumber
2

Untuk iOS 13

Mulai dari iOS 13 aplikasi Anda juga membutuhkan akses Lokasi Inti untuk menggunakan CNCopyCurrentNetworkInfo fungsi kecuali jika mengkonfigurasi jaringan saat ini atau memiliki konfigurasi VPN:
kutipan dari https://developer.apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo?language=objc

Jadi inilah yang Anda butuhkan (lihat dokumentasi apel ):
- Tautkan CoreLocation.frameworkperpustakaan
- Tambahkan location-servicessebagai UIRequiredDeviceCapabilitiesKunci / Nilai di Info.plist
- Tambahkan NSLocationWhenInUseUsageDescriptionKunci / Nilai di Info.plist yang menjelaskan mengapa aplikasi Anda memerlukan Lokasi Inti
- Tambahkan "Akses WiFi Hak informasi "untuk aplikasi Anda

Sekarang sebagai contoh Objective-C, periksa dulu apakah akses lokasi telah diterima sebelum membaca info jaringan menggunakan 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
sumber
Itu diperlukan di iOS13, jika tidak Anda mendapat nol untuk CNCopyCurrentNetworkInfo ()
Franz Wang
@Sugar ya memang iOS13 - lihat baris pertama jawaban saya
Francois B