iOS App無需跳轉系統設定自動連線Wi-Fi

FBY展菲發表於2019-03-11

一: 介紹

近幾年,智慧裝置越來越火,這些智慧裝置中,有很大一部分是通過手機來控制硬體裝置,來達到預期的效果,這中間少不了要使用到藍芽功能,通過藍芽來通訊來控制裝置。 除了藍芽控制裝置之外,還可以通過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 許可權。

1.png

配置的App ID需要與專案中的Bundle ID一致。

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個屬性,分別是:

  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技術乾貨等待領取,所有文件會持續更新,歡迎關注一起成長!


歡迎關注我的公眾號:網羅開發

iOS App無需跳轉系統設定自動連線Wi-Fi

相關文章