iOS App无需跳转系统设置自动连接Wi-Fi

时间:2024-04-07 07:14:41

一: 介绍

近几年,智能设备越来越火,这些智能设备中,有很大一部分是通过手机来控制硬件设备,来达到预期的效果,这中间少不了要使用到蓝牙功能,通过蓝牙来通信来控制设备。
除了蓝牙控制设备之外,还可以通过Wi-Fi来控制设备,iOS11前只能跳转到系统设置界面手动连接Wi-Fi,iOS11之后苹果提供 NEHotspotConfiguration ,NEHotspotConfigurationManager 类直连周边Wi-Fi。

这篇文章主要和大家分享iOS11之后在App内自动连接Wi-Fi,Wi-Fi信息获取,Wi-Fi检测等功能。

二:权限配置

苹果提供的 NEHotspotConfiguration ,NEHotspotConfigurationManager需要在开发者账号和项目中做如下配置。

1. 打开App IDs Hotspot 权限

登陆https://developer.apple.com,如果App ID已经存在,只需增加Hotspot 权限,如果App ID不存在,新建一个并添加Hotspot 权限。

iOS App无需跳转系统设置自动连接Wi-Fi

配置的App ID需要与项目中的Bundle ID一致。

2. 添加依赖库NetworkExtension.framework

在项目中Build Phases - Link Binary With Libraries中添加 依赖库NetworkExtension.framework

iOS App无需跳转系统设置自动连接Wi-Fi

3. 打开Capabilities里的Hotspot Configuration

Xcode - Capabilities - Hostpot Configuration 开关打开

iOS App无需跳转系统设置自动连接Wi-Fi

三:NEHotspotConfiguration库分析

在NEHotspotConfiguration库中有3个属性,分别是:

  1. SSID:要连的wifi名称
  2. joinOnce:默认是NO,会保留配置过的wifi,YES即是不保存
  3. lifeTimeInDays: 配置的生命周期

源码如下:

/*!
 * @property SSID
 * @discussion SSID of the Wi-Fi Network.
 */
@property (readonly) NSString * SSID API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(macos, watchos, tvos);

/*!
 * @property joinOnce
 * @discussion if set to YES the configuration will not be persisted. Default is NO.
 */
@property BOOL joinOnce API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(macos, watchos, tvos);

/*!
 * @property lifeTimeInDays
 * @discussion The lifetime of the configuration in days. The configuration is stored for the
 *   number of days specified by this property. The minimum value is 1 day and maximum value is 365 days.
 *   A configuration does not get deleted automatically if this property is not set or set to an invalid value.
 *   This property does not apply to Enterprise and HS2.0 networks.
 */
@property (copy) NSNumber * lifeTimeInDays API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(macos, watchos, tvos);

有4个实例化方法,分别是:

  1. 无密码的开放网络
  2. 受保护的WEP或WPA / WPA2个人Wi-Fi网络创建由SSID标识的新热点配置
  3. 具有EAP设置的WPA / WPA2企业Wi-Fi网络
  4. 具有HS 2.0和EAP设置的Hotspot 2.0 Wi-Fi网络

源码如下:

/*!
 * @method initWithSSID:
 * @discussion
 *   A designated initializer to instantiate a new NEHotspotConfiguration object.
 *   This initializer is used to configure open Wi-Fi Networks.
 *
 * @param SSID The SSID of the Open Wi-Fi Network.
 *   Length of SSID must be between 1 and 32 characters.
 */
- (instancetype)initWithSSID:(NSString *)SSID API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(macos, watchos, tvos);

/*!
 * @method initWithSSID:passphrase:isWEP
 * @discussion
 *   A designated initializer to instantiate a new NEHotspotConfiguration object.
 *   This initializer is used configure either WEP or WPA/WPA2 Personal Wi-Fi Networks.
 *
 * @param SSID The SSID of the WEP or WPA/WPA2 Personal Wi-Fi Network
 * @param passphrase The passphrase credential.
 *   For WPA/WPA2 Personal networks: between 8 and 63 characters.
 *   For Static WEP(64bit)  : 10 Hex Digits
 *   For Static WEP(128bit) : 26 Hex Digits
 * @param isWEP YES specifies WEP Wi-Fi Network else WPA/WPA2 Personal Wi-Fi Network
 */
- (instancetype)initWithSSID:(NSString *)SSID
					  passphrase:(NSString *)passphrase isWEP:(BOOL)isWEP API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(macos, watchos, tvos);

/*!
 * @method initWithSSID:eapSettings
 * @discussion
 *   A designated initializer to instantiate a new NEHotspotConfiguration object.
 *   This initializer is used configure WPA/WPA2 Enterprise Wi-Fi Networks.
 *
 * @param SSID The SSID of WPA/WPA2 Enterprise Wi-Fi Network
 * @param eapSettings EAP configuration
 */
- (instancetype)initWithSSID:(NSString *)SSID
					  eapSettings:(NEHotspotEAPSettings *)eapSettings API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(macos, watchos, tvos);

/*!
 * @method initWithHS20Settings:eapSettings
 * @discussion
 *   A designated initializer to instantiate a new NEHotspotConfiguration object.
 *   This initializer is used configure HS2.0 Wi-Fi Networks.
 *
 * @param hs20Settings Hotspot 2.0 configuration
 * @param eapSettings EAP configuration
 */
- (instancetype)initWithHS20Settings:(NEHotspotHS20Settings *)hs20Settings
						eapSettings:(NEHotspotEAPSettings *)eapSettings API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(macos, watchos, tvos);

四:NEHotspotConfigurationManager库分析

在NEHotspotConfigurationManager库中提供了四个方法,分别是:

  1. 应用你的Configuration,会弹出系统框询问是否加入
  2. 通过ssid删除一个配置
  3. 删除Hotspot 2.0域名标识的Wi-Fi热点配置
  4. 获取配置过的wifi名称。如果你设置joinOnce为YES,这里就不会有了

源码如下:

/*!
 * @method applyConfiguration:
 * @discussion This function adds or updates a Wi-Fi network configuration.
 * @param configuration NEHotspotConfiguration object containing the Wi-Fi network configuration.
 * @param completionHandler A block that will be called when add/update operation is completed.
 *   This could be nil if application does not intend to receive the result.
 *   The NSError passed to this block will be nil if the configuration is successfully stored, non-nil otherwise.
 *   If the configuration is found invalid or API encounters some other error then completionHandler is called
 *   with instance of NSError containing appropriate error code. This API attempts to join the Wi-Fi network
 *   if the configuration is successfully added or updated and the network is found nearby.
 *
 */
- (void)applyConfiguration:(NEHotspotConfiguration *)configuration
						completionHandler:(void (^ __nullable)(NSError * __nullable error))completionHandler API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(macos, watchos, tvos);

/*!
 * @method removeConfigurationForSSID:
 * @discussion This function removes Wi-Fi configuration.
 *   If the joinOnce property was set to YES, invoking this method will disassociate from the Wi-Fi network
 *   after the configuration is removed.
 * @param SSID Wi-Fi SSID for which the configuration is to be deleted.
 */
- (void)removeConfigurationForSSID:(NSString *)SSID API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(macos, watchos, tvos);

/*!
 * @method removeConfigurationForNetworkName:
 * @discussion This function removes Wi-Fi configuration.
 * @param domainName HS2.0 domainName for which the configuration is to be deleted.
 */
- (void)removeConfigurationForHS20DomainName:(NSString *)domainName API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(macos, watchos, tvos);


/*!
 * @method getConfiguredSSIDsWithCompletionHandler:
 * @discussion This function returns array of SSIDs and HS2.0 Domain Names that the calling application has configured.
 *   It returns nil if there are no networks configurred by the calling application.
 */
- (void)getConfiguredSSIDsWithCompletionHandler:(void (^)(NSArray<NSString *> *))completionHandler API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(macos, watchos, tvos);

到这里配置及源码分析的前期工作已经做完。

五:加入Wi-Fi实现解析

首先引入 NetworkExtension 库

#import <NetworkExtension/NetworkExtension.h>

然后需要调用NEHotspotConfiguration库方法,根据不同的情况,选择使用不同的方法,这里使用受保护的WEP或WPA举例

NEHotspotConfiguration *hotspotConfig = [[NEHotspotConfiguration alloc]initWithSSID:_wifiName.text passphrase:_wifiPassword.text isWEP:NO];

然后开始连接 ,调用applyConfiguration此方法后系统会自动弹窗确认,根据返回的error.code来判断Wi-Fi是否加入成功,error code = 7 为用户点击了弹框取消按钮,error code = 13 为已连接

[[NEHotspotConfigurationManager sharedManager] applyConfiguration:hotspotConfig completionHandler:^(NSError * _Nullable error) {
            if (error && error.code != 13 && error.code != 7) {
                NSLog(@"加入失败");
            }else if(error.code ==7){
                NSLog(@"已取消");
            }else{
                NSLog(@"已连接");
            }
        }];

五:Wi-Fi列表实现解析

在Android中设备周围的Wi-Fi信息是可以扫面获取到的,iOS设备至今也没有完全开放相关接口,如果真有该需求
,需要填写申请表申请,通过后方可使用,咱们这里分享的Wi-Fi列表,是NEHotspotConfigurationManager库中的getConfiguredSSIDsWithCompletionHandler方法,可以获取到已经保存过的Wi-Fi信息,实现源码如下:

[[NEHotspotConfigurationManager sharedManager] getConfiguredSSIDsWithCompletionHandler:^(NSArray<NSString *> * array) {
        for (NSString * str in array) {
            self.WiFiListTextView.text = [NSString stringWithFormat:@"%@\n%@",self.WiFiListTextView.text,str];
            NSLog(@"加入过的WiFi:%@",str);
        }
    }];

六:Wi-Fi测速实现解析

通过Wi-Fi测速可以获取到Wi-Fi强度、上行速度、下行速度,我在demo中封装了SpeedController类来实现该功能,通过下面两个方法来实现:

//获取信号强度(0到1)
+(void)getSignalStrength:(void(^)(float signalStrength))resultBlock;
//获取下行速度,上行速度(单位是 MB/S)
-(void)getDownstreamSpeedAndUpstreamSpeed:(void(^)(float downstreamSpeed,float upstreamSpeed))resultBlock;

源码Demo获取方法

关注 【网罗开发】微信公众号,回复【93】便可领取。
网罗天下方法,方便你我开发,更多iOS技术干货等待领取,所有文档会持续更新,欢迎关注一起成长!