iOS App無需跳轉系統設置自動鏈接Wi-Fi

一: 介紹

近幾年,智能設備愈來愈火,這些智能設備中,有很大一部分是經過手機來控制硬件設備,來達到預期的效果,這中間少不了要使用到藍牙功能,經過藍牙來通訊來控制設備。 除了藍牙控制設備以外,還能夠經過Wi-Fi來控制設備,iOS11前只能跳轉到系統設置界面手動鏈接Wi-Fi,iOS11以後蘋果提供 NEHotspotConfiguration ,NEHotspotConfigurationManager 類直連周邊Wi-Fi。ios

這篇文章主要和你們分享iOS11以後在App內自動鏈接Wi-Fi,Wi-Fi信息獲取,Wi-Fi檢測等功能。git

二:權限配置

蘋果提供的 NEHotspotConfiguration ,NEHotspotConfigurationManager須要在開發者帳號和項目中作以下配置。macos

1. 打開App IDs Hotspot 權限

登錄https://developer.apple.com,若是App ID已經存在,只需增長Hotspot 權限,若是App ID不存在,新建一個並添加Hotspot 權限。sass

1.png

配置的App ID須要與項目中的Bundle ID一致。bash

2. 添加依賴庫NetworkExtension.framework

在項目中Build Phases - Link Binary With Libraries中添加 依賴庫NetworkExtension.framework微信

2.png

3. 打開Capabilities裏的Hotspot Configuration

Xcode - Capabilities - Hostpot Configuration 開關打開網絡

3.png

三:NEHotspotConfiguration庫分析

在NEHotspotConfiguration庫中有3個屬性,分別是:app

  1. SSID:要連的wifi名稱
  2. joinOnce:默認是NO,會保留配置過的wifi,YES便是不保存
  3. lifeTimeInDays: 配置的生命週期

源碼以下:dom

/*!
 * @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技術乾貨等待領取,全部文檔會持續更新,歡迎關注一塊兒成長!


歡迎關注個人公衆號:網羅開發

相關文章
相關標籤/搜索