OC-WiFi

引入

#import <ifaddrs.h>
#import <net/if.h>
#import <SystemConfiguration/CaptiveNetwork.h>
#import <CoreLocation/CoreLocation.h>

info.plist

Privacy - Location Always Usage Description
Privacy - Location When In Use Usage Description
//
//  WiFiManager.h
//  SmartPrint
//
//  Created by mac on 2021/7/11.
//

#import <Foundation/Foundation.h>
///wifi網(wǎng)絡(luò)框架
#import <NetworkExtension/NetworkExtension.h>

NS_ASSUME_NONNULL_BEGIN

///WiFi
@interface WiFiManager : NSObject

///wifi是否開啟
+ (BOOL)isWiFiEnabled;
/// 打開wifi設(shè)置界面
+ (void)openWiFiSetting;
///獲取當(dāng)前連接的wifi信息
+ (NSDictionary *)getCurrentConnectionWiFiInfo;
///獲取wifi列表
+ (NSMutableArray *)getWiFiList;

///連接指定WiFi
/// @param cmd 命令
/// @param network 網(wǎng)絡(luò)
/// @param password wifi密碼
+ (void)connectWiFiforCmd:(NEHotspotHelperCommand *)cmd network:(NEHotspotNetwork *)network  password:(NSString *)password;

///斷開指定WiFi
+ (void)disconnectWiFiforCmd:(NEHotspotHelperCommand *)cmd network:(NEHotspotNetwork *)network  password:(NSString *)password;

+ (NSString *)getWiFiName;

@end

NS_ASSUME_NONNULL_END

//
//  WiFi.m
//  SmartPrint
//
//  Created by mac on 2021/7/11.
//


#import "WiFiManager.h"
#import <UIKit/UIKit.h>
#import <ifaddrs.h>
#import <net/if.h>
#import <SystemConfiguration/CaptiveNetwork.h>
#import <CoreLocation/CoreLocation.h>

@implementation WiFiManager

//
//    func getInterfaces() -> Bool {
//        guard let unwrappedCFArrayInterfaces = CNCopySupportedInterfaces() else {
//            print("this must be a simulator, no interfaces found")
//            //這必須是模擬器,沒有找到接口
//            return false
//        }
//        guard let swiftInterfaces = (unwrappedCFArrayInterfaces as NSArray) as? [String] else {
//            //系統(tǒng)錯(cuò)誤:沒有以字符串?dāng)?shù)組的形式返回
//            print("System error: did not come back as array of Strings")
//            return false
//        }
//        for interface in swiftInterfaces {
//            //查找\(接口)的SSID信息
//            print("Looking up SSID info for \(interface)") // en0
//            guard let unwrappedCFDictionaryForInterface = CNCopyCurrentNetworkInfo(interface as CFString) else {
//                //系統(tǒng)錯(cuò)誤:\(接口)沒有信息
//                print("System error: \(interface) has no information")
//                return false
//            }
//            guard let SSIDDict = (unwrappedCFDictionaryForInterface as NSDictionary) as? [String: AnyObject] else {
//                //系統(tǒng)錯(cuò)誤:接口信息不是字符串鍵控字典
//                print("System error: interface information is not a string-keyed dictionary")
//                return false
//            }
//            for d in SSIDDict.keys {
//                //打印ssid
//                print("\(d): \(SSIDDict[d]!)")
//            }
//        }
//        return true
//    }
    
    
//    func getWifiName() -> String? {
//
//   let interfaces: CFArray! = CNCopySupportedInterfaces()
//
//   if interfaces == nil { return nil }
//
//    let if0: UnsafePointer? = CFArrayGetValueAtIndex(interfaces, 0)
//
//    if if0 == nil { return nil }
//
//   let interfaceName: CFStringRef = unsafeBitCast(if0!, CFStringRef.self)
//
//    let dictionary = CNCopyCurrentNetworkInfo(interfaceName) as NSDictionary?
//
//    if dictionary == nil { return nil }
//
//    return dictionary?[kCNNetworkInfoKeySSID as String] as? String
//
//    }


+ (NSString *)getWiFiName {
    if (@available(iOS 13.0, *)) {
        //用戶明確拒絕安岂,可以彈窗提示用戶到設(shè)置中手動(dòng)打開權(quán)限
        if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
            NSLog(@"User has explicitly denied authorization for this application, or location services are disabled in Settings.");
            //使用下面接口可以打開當(dāng)前應(yīng)用的設(shè)置頁面
            //[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
            return nil;
        }
        CLLocationManager* cllocation = [[CLLocationManager alloc] init];
        if(![CLLocationManager locationServicesEnabled] || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined){
            //彈框提示用戶是否開啟位置權(quán)限
            [cllocation requestWhenInUseAuthorization];
            usleep(50);
            //遞歸等待用戶選選擇
            //return [self getWifiSsidWithCallback:callback];
        }
    }
    NSString *wifiName = nil;
    CFArrayRef wifiInterfaces = CNCopySupportedInterfaces();
    if (!wifiInterfaces) {
        return nil;
    }
    NSArray *interfaces = (__bridge NSArray *)wifiInterfaces;
    for (NSString *interfaceName in interfaces) {
        CFDictionaryRef dictRef = CNCopyCurrentNetworkInfo((__bridge CFStringRef)(interfaceName));
        
        if (dictRef) {
            NSDictionary *networkInfo = (__bridge NSDictionary *)dictRef;
            NSLog(@"network info -> %@", networkInfo);
            wifiName = [networkInfo objectForKey:(__bridge NSString *)kCNNetworkInfoKeySSID];
            CFRelease(dictRef);
        }
    }
    
    CFRelease(wifiInterfaces);
    return wifiName;
}

///獲取SSID --wifi名稱
+ (NSString *)ssid

{
    
    NSString *ssid = @"Not Found";
    
    CFArrayRef myArray = CNCopySupportedInterfaces();
    
    if (myArray != nil) {
        
        CFDictionaryRef myDict = CNCopyCurrentNetworkInfo(CFArrayGetValueAtIndex(myArray, 0));
        
        if (myDict != nil) {
            
            NSDictionary *dict = (NSDictionary*)CFBridgingRelease(myDict);
            
            ssid = [dict valueForKey:@"SSID"];
            
        }
        
    }
    
    return ssid;
    
}

///獲取MAC --MAC為網(wǎng)絡(luò)接口物理地址凑阶,一般指電腦網(wǎng)卡的物理地址
///獲取macIP
+ (NSString *)bssid

{
    
    NSString *bssid = @"Not Found";
    
    CFArrayRef myArray = CNCopySupportedInterfaces();
    
    if (myArray != nil) {
        
        CFDictionaryRef myDict = CNCopyCurrentNetworkInfo(CFArrayGetValueAtIndex(myArray, 0));
        
        if (myDict != nil) {
            
            NSDictionary *dict = (NSDictionary*)CFBridgingRelease(myDict);
            
            bssid = [dict valueForKey:@"BSSID"];
            
        }
        
    }
    
    return bssid;
    
}



///當(dāng)前設(shè)備的wifi列表
+ (void)queryDeviceWiFiInfoList {
    dispatch_queue_t q = dispatch_queue_create("com.leopardpan.HotspotHelper", 0);
    [NEHotspotHelper registerWithOptions:nil queue:q handler:^(NEHotspotHelperCommand * _Nonnull cmd) {
        if (cmd.commandType == kNEHotspotHelperCommandTypeFilterScanList) {
            for (NEHotspotNetwork *network in cmd.networkList) {
                NSLog(@"SSID = %@",network.SSID);
                NSLog(@"BSSID = %@",network.BSSID);
            }
        }
    }];
}


+ (void)scanWifiInfos{
    NSLog(@"1.Start");
    
    NSMutableDictionary* options = [[NSMutableDictionary alloc] init];
    [options setObject:@"SmartPrint" forKey: kNEHotspotHelperOptionDisplayName];
    dispatch_queue_t queue = dispatch_queue_create("SmartPrint", NULL);
    
    NSLog(@"2.Try");
    BOOL returnType = [NEHotspotHelper registerWithOptions: options queue: queue handler: ^(NEHotspotHelperCommand * cmd) {
        
        NSLog(@"4.Finish");
        NEHotspotNetwork* network;
        if (cmd.commandType == kNEHotspotHelperCommandTypeEvaluate || cmd.commandType == kNEHotspotHelperCommandTypeFilterScanList) {
            // 遍歷 WiFi 列表泪掀,打印基本信息
            for (network in cmd.networkList) {
                NSString* wifiInfoString = [[NSString alloc] initWithFormat: @"---------------------------\nSSID: %@\nMac地址: %@\n信號強(qiáng)度: %f\nCommandType:%ld\n---------------------------\n\n", network.SSID, network.BSSID, network.signalStrength, (long)cmd.commandType];
                NSLog(@"%@", wifiInfoString);
                
                // 檢測到指定 WiFi 可設(shè)定密碼直接連接
                if ([network.SSID isEqualToString: @"測試 WiFi"]) {
                    [network setConfidence: kNEHotspotHelperConfidenceHigh];
                    [network setPassword: @"123456789"];
                    NEHotspotHelperResponse *response = [cmd createResponse: kNEHotspotHelperResultSuccess];
                    NSLog(@"Response CMD: %@", response);
                    [response setNetworkList: @[network]];
                    [response setNetwork: network];
                    [response deliver];
                }
            }
        }
    }];
    
    // 注冊成功 returnType 會返回一個(gè) Yes 值吹艇,否則 No
    NSLog(@"3.Result: %@", returnType == YES ? @"Yes" : @"No");
}


#pragma mark - WiFi
///是否開啟WiFi
+ (BOOL)isWiFiEnabled {
    NSCountedSet * cset = [NSCountedSet new];
    struct ifaddrs *interfaces;
    if(!getifaddrs(&interfaces)){
        for( struct ifaddrs *interface = interfaces; interface; interface = interface->ifa_next) {
            if ( (interface->ifa_flags & IFF_UP) == IFF_UP ) {
                [cset addObject:[NSString stringWithUTF8String:interface->ifa_name]];
            }
        }
    }
    return [cset countForObject:@"awdl0"] > 1 ? YES : NO;
}

/// 打開無線局域網(wǎng)設(shè)置FF
+ (void)openWiFiSetting {
    
    NSURL* urlCheck1 = [NSURL URLWithString: @"App-Prefs:root=WIFI"];
    NSURL* urlCheck2 = [NSURL URLWithString: @"prefs:root=WIFI"];
    NSURL* urlCheck3 = [NSURL URLWithString: UIApplicationOpenSettingsURLString];
    
    NSLog(@"Try to open WiFi Setting, waiting...");
    
    if ([[UIApplication sharedApplication] canOpenURL: urlCheck1]) {
        [[UIApplication sharedApplication] openURL:urlCheck1 options:@{} completionHandler:nil];
    } else if ([[UIApplication sharedApplication] canOpenURL: urlCheck2]) {
        [[UIApplication sharedApplication] openURL:urlCheck2 options:@{} completionHandler:nil];
    } else if ([[UIApplication sharedApplication] canOpenURL: urlCheck3]) {
        [[UIApplication sharedApplication] openURL:urlCheck3 options:@{} completionHandler:nil];
    } else {
        NSLog(@"Unable to open WiFi Setting!");
        return;
    }
    
    NSLog(@"Open WiFi Setting successful.");
}

///獲取wifi列表
+ (NSMutableArray *)getWiFiList {
    NSLog(@"1.Start");
    
    //SmartPrint -> BundleIdentifier
    NSMutableDictionary* options = [[NSMutableDictionary alloc] init];
    [options setObject:@"SmartPrint" forKey: kNEHotspotHelperOptionDisplayName];
    dispatch_queue_t queue = dispatch_queue_create("SmartPrint", NULL);
    
    NSLog(@"2.Try");
    NSMutableArray *list = [@[] mutableCopy];
    BOOL returnType = [NEHotspotHelper registerWithOptions: options queue: queue handler: ^(NEHotspotHelperCommand * cmd) {
        
        NSLog(@"4.Finish");
        NEHotspotNetwork* network;
        if (cmd.commandType == kNEHotspotHelperCommandTypeEvaluate || cmd.commandType == kNEHotspotHelperCommandTypeFilterScanList) {
            //遍歷 WiFi 列表诵竭,打印基本信息
            for (network in cmd.networkList) {
                //SSID:wifi名稱, BSSID:Mac地址, signalStrength:信號強(qiáng)度, cmd:命令類型
                NSDictionary *mDic = @{@"NEHotspotHelperCommand":cmd, @"NEHotspotNetwork":network, @"SSID":network.SSID,@"BSSID":network.BSSID, @"signalStrength": @(network.signalStrength), @"commandType":@((long)cmd.commandType)};
                [list addObject:mDic];
            }
        }
    }];
    // 注冊成功 returnType 會返回一個(gè) Yes 值环形,否則 No
    NSLog(@"3.Result: %@", returnType == YES ? @"Yes" : @"No");
    return  list;
}

///當(dāng)前連接的wifi信息
+ (NSDictionary *)getCurrentConnectionWiFiInfo
{
    NSDictionary *currentWifiInfo = nil;
    // 獲取當(dāng)前的interface 數(shù)組
    CFArrayRef currentInterfaces = CNCopySupportedInterfaces();
    if (!currentInterfaces) {
        return currentWifiInfo;
    }
    // 類型轉(zhuǎn)換总寻,將CF對象汗销,轉(zhuǎn)為NS對象犹褒,同時(shí)將該對象的引用計(jì)數(shù)交給 ARC 管理
    NSArray *interfaces = (__bridge_transfer NSArray *)currentInterfaces;
    if (interfaces.count >0) {
        for (NSString *interfaceName in interfaces) {
            // 轉(zhuǎn)換類型,不改變引用計(jì)數(shù)
            CFDictionaryRef dictRef = CNCopyCurrentNetworkInfo((__bridge CFStringRef)(interfaceName));
            if (dictRef) {
                NSDictionary *networkInfo = (__bridge_transfer NSDictionary *)dictRef;
                NSString *SSID = [networkInfo objectForKey:(__bridge_transfer NSString *)kCNNetworkInfoKeySSID];
                NSString *BSSID = [networkInfo objectForKey:(__bridge_transfer NSString *)kCNNetworkInfoKeyBSSID];
                NSData *SSIDDATA = [networkInfo objectForKey:(__bridge_transfer NSData *)kCNNetworkInfoKeySSIDData];
                currentWifiInfo = @{@"SSID":SSID,
                                    @"BSSID":BSSID,
                                    @"SSIDDATA":SSIDDATA};
                
            }
        }
    }
    NSLog(@"currentWifiInfo = %@",currentWifiInfo);
    return currentWifiInfo;
}


///連接指定WiFi
/// @param cmd 命令
/// @param network 網(wǎng)絡(luò)
/// @param password wifi密碼
+ (void)connectWiFiforCmd:(NEHotspotHelperCommand *)cmd network:(NEHotspotNetwork *)network password:(NSString *)password
{
        [network setConfidence: kNEHotspotHelperConfidenceHigh];
        [network setPassword: password];
        NEHotspotHelperResponse *response = [cmd createResponse: kNEHotspotHelperResultSuccess];
        NSLog(@"Response CMD: %@", response);
        [response setNetworkList: @[network]];
        [response setNetwork: network];
        [response deliver];
}

///斷開指定WiFi
+ (void)disconnectWiFiforCmd:(NEHotspotHelperCommand *)cmd network:(NEHotspotNetwork *)network password:(NSString *)password {
    [network setConfidence: kNEHotspotHelperConfidenceHigh];
    [network setPassword: password];
    NEHotspotHelperResponse *response = [cmd createResponse: kNEHotspotHelperResultSuccess];
    NSLog(@"Response CMD: %@", response);
    [response setNetworkList: @[network]];
    [response setNetwork: network];
    [response deliver];
}


@end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末弛针,一起剝皮案震驚了整個(gè)濱河市叠骑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌削茁,老刑警劉巖宙枷,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異茧跋,居然都是意外死亡慰丛,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進(jìn)店門瘾杭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诅病,“玉大人,你說我怎么就攤上這事粥烁∠桶剩” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵讨阻,是天一觀的道長苏潜。 經(jīng)常有香客問我,道長变勇,這世上最難降的妖魔是什么恤左? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任贴唇,我火速辦了婚禮,結(jié)果婚禮上飞袋,老公的妹妹穿的比我還像新娘戳气。我一直安慰自己,他們只是感情好巧鸭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布瓶您。 她就那樣靜靜地躺著,像睡著了一般纲仍。 火紅的嫁衣襯著肌膚如雪呀袱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天郑叠,我揣著相機(jī)與錄音夜赵,去河邊找鬼。 笑死乡革,一個(gè)胖子當(dāng)著我的面吹牛寇僧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播沸版,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼嘁傀,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了视粮?” 一聲冷哼從身側(cè)響起细办,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蕾殴,沒想到半個(gè)月后蟹腾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡区宇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年娃殖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片议谷。...
    茶點(diǎn)故事閱讀 40,001評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡炉爆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出卧晓,到底是詐尸還是另有隱情芬首,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布逼裆,位于F島的核電站郁稍,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏胜宇。R本人自食惡果不足惜耀怜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一恢着、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧财破,春花似錦掰派、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至俊性,卻和暖如春略步,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背定页。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工趟薄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拯勉。 一個(gè)月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓竟趾,卻偏偏與公主長得像憔购,于是被迫代替她去往敵國和親宫峦。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內(nèi)容