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网络框架
#import <NetworkExtension/NetworkExtension.h>

NS_ASSUME_NONNULL_BEGIN

///WiFi
@interface WiFiManager : NSObject

///wifi是否开启
+ (BOOL)isWiFiEnabled;
/// 打开wifi设置界面
+ (void)openWiFiSetting;
///获取当前连接的wifi信息
+ (NSDictionary *)getCurrentConnectionWiFiInfo;
///获取wifi列表
+ (NSMutableArray *)getWiFiList;

///连接指定WiFi
/// @param cmd 命令
/// @param network 网络
/// @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 {
//            //系统错误:没有以字符串数组的形式返回
//            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 {
//                //系统错误:\(接口)没有信息
//                print("System error: \(interface) has no information")
//                return false
//            }
//            guard let SSIDDict = (unwrappedCFDictionaryForInterface as NSDictionary) as? [String: AnyObject] else {
//                //系统错误:接口信息不是字符串键控字典
//                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, *)) {
        //用户明确拒绝,可以弹窗提示用户到设置中手动打开权限
        if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
            NSLog(@"User has explicitly denied authorization for this application, or location services are disabled in Settings.");
            //使用下面接口可以打开当前应用的设置页面
            //[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
            return nil;
        }
        CLLocationManager* cllocation = [[CLLocationManager alloc] init];
        if(![CLLocationManager locationServicesEnabled] || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined){
            //弹框提示用户是否开启位置权限
            [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为网络接口物理地址,一般指电脑网卡的物理地址
///获取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;
    
}



///当前设备的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信号强度: %f\nCommandType:%ld\n---------------------------\n\n", network.SSID, network.BSSID, network.signalStrength, (long)cmd.commandType];
                NSLog(@"%@", wifiInfoString);
                
                // 检测到指定 WiFi 可设定密码直接连接
                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 会返回一个 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;
}

/// 打开无线局域网设置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:信号强度, cmd:命令类型
                NSDictionary *mDic = @{@"NEHotspotHelperCommand":cmd, @"NEHotspotNetwork":network, @"SSID":network.SSID,@"BSSID":network.BSSID, @"signalStrength": @(network.signalStrength), @"commandType":@((long)cmd.commandType)};
                [list addObject:mDic];
            }
        }
    }];
    // 注册成功 returnType 会返回一个 Yes 值,否则 No
    NSLog(@"3.Result: %@", returnType == YES ? @"Yes" : @"No");
    return  list;
}

///当前连接的wifi信息
+ (NSDictionary *)getCurrentConnectionWiFiInfo
{
    NSDictionary *currentWifiInfo = nil;
    // 获取当前的interface 数组
    CFArrayRef currentInterfaces = CNCopySupportedInterfaces();
    if (!currentInterfaces) {
        return currentWifiInfo;
    }
    // 类型转换,将CF对象,转为NS对象,同时将该对象的引用计数交给 ARC 管理
    NSArray *interfaces = (__bridge_transfer NSArray *)currentInterfaces;
    if (interfaces.count >0) {
        for (NSString *interfaceName in interfaces) {
            // 转换类型,不改变引用计数
            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 网络
/// @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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容