現代の世界では、公共機関における公共Wi-Fiの存在は当たり前のことと考えられています。 カフェ、ショッピングセンター、ホテル、空港、レジャーパーク、その他多くの場所を訪れると、すぐにパスワードなしで切望されている信号を探します。 そして、これは簡単ではありません。なぜなら、リストにはいくつかのポイントがあり、次に、無料のWi-Fiをパスワードで保護できるため、正しいネットワークを指してパスワードを指定できる従業員を捕まえることが唯一の方法です。 しかし、その後でも、何も機能しないことが起こります。 ユーザーは、ネットワークへのフルアクセスが許可される前に、ブラウザを開く必要があると推測し(別の質問、どのページをダウンロードする必要があるか)、追加のアクション(ログイン、広告の表示、ユーザー同意の確認)を行う必要があります。
ただし、現在では多くの人気のある機関が無料ポイントへの接続を容易にするアプリケーションを提供しています。 私たちはそれぞれそのような例を簡単に思い出すことができると確信しているので、名前や広告なしで行うことができます。 さらに、この問題の別の解決策について以下で説明します-独自のネットワークヘルパーを作成します! このアプローチを使用すると、接続するグリッドを推測する必要がなくなります。 ネットワークにアクセスするための追加のアクションでさえ、便利なネイティブUIで実行でき、ブラウザよりもはるかに高速です。
すべてがシンプルです。 iOS 9のリリース以降、開発者が利用できるようになったNEHotspotHelperテクノロジーを使用するだけで十分です。このツールの主なタスクは、Wi-Fiネットワークの分類とユーザー認証です。 NEHotspotHelperはNetworkExtensionフレームワークの一部です。 以下に、iOS 11のリリース時に含まれていたツールの図を示します。

主なドキュメントはこちらです:
Hotspot Network Subsystem Programming Guide 。 さらに、ネットワーク上で情報が見つからなかったため、この記事を書いています。 私の資料がドキュメントのギャップを埋めて、独自のホットスポットヘルパーを実装する方法を説明するのに役立つことを願っています。 このテクノロジーの使用例は、
GitHubにあります 。
動作原理
ホットスポットヘルパーは、ヘルパーシステムによって送信されるWi-Fi接続状態マシンとコマンドに基づいており、その処理によりマシンが1つの状態から別の状態に転送されます。 以下は、Apple自身がドキュメントで引用しているおおよその状態図です。

最初は、このような複雑な図は怖いですが、心配しないでください-実際には、すべてが非常に単純です。
以下を理解するだけで十分です。
- デバイスを再起動した後に初めてネットワークに接続するとき、それを提供するためにヘルパーが選択されます( Evaluate )。
- 選択が行われると、選択したホットスポットヘルパー( 認証 )を使用して、ネットワーク上の認証が開始されます。
- 承認プロセス中にUIを表示する必要がある場合、Hotspot Helperは明示的に要求します( PresentingUI )。 そのような必要性がない場合、バックグラウンドのヘルパーは、ネットワーク上のユーザーを認証するために必要な手順を実行します( 認証済み )。
- 必要に応じて、システムはセッションをサポートするために、選択したホットスポットヘルパーを定期的に起動します( メンテナンス )。
- セッションのサポート中、ヘルパーは何もしなかったり、再認証を要求したり、ネットワークへの再接続を引き起こしたりします。
唯一の非自明なポイント:ネットワークへの最初の接続後、システムは選択されたホットスポットヘルパーをキャッシュします。したがって、次の接続で、マシンはすぐに保守状態に切り替わり、以前のすべてをバイパスします。
Hotspot Helperは、ネットワークのリストの表示から選択されたネットワークへの接続まで、Wi-Fiネットワークのユーザー認証に関与し、認証とセルフログアウトをサポートします。 同時に、接続を確立するために、Hotspot Helperは必要なすべてのコマンドを処理するため、システムはあらゆる状況で起動します(ユーザーがアプリケーションを強制的にシャットダウンした場合でも(
サイレントプッシュ通知を無視することになります)、デバイス全体の動作はこれに依存するためです)。プロセス全体がユーザーに対して透過的であるため、最も一般的なシナリオは、アプリケーションをバックグラウンドで起動することです。
そのため、Wi-Fi接続を確立するには、ホットスポットヘルパーが必要なコマンドをすべて処理する必要があります。
つまり、StateMachineがAuthenticated状態になるまで、デバイスは自身がネットワークに接続されているとは見なしません 。 そして、これは、Hotspot Helperが
Evaluateコマンド
を受信すると接続の表示を開始するという事実にもかかわらずです。 この瞬間は、以下で説明するReachabilityツールによって完全に追跡されます。
NEHotspotHelperは、他の拡張機能でよくあるように、個別のターゲットではなく、メインアプリケーションがHotspot Helperとして登録されていると言わなければなりません。 つまり、彼がコマンドを処理する必要があるとすぐに、メインアプリケーションが起動され、その後のすべての結果がもたらされます。 つまり、アプリケーションは任意のコードを実行できますが、バックグラウンドで起動されると、まるでユーザー自身によって開始されたかのように本格的なアクションをデプロイできます。 ただし、このようなアクティビティはリソースを無駄にすることを意味するだけなので
、バックグラウンドで何が起こっているかは注目に値します
事前準備
アプリケーションをホットスポットヘルパーとして登録するには、Appleの許可が必要です。 これを行うには、チームエージェントが
リンクをたどってアンケートに記入する必要があります。
執筆時点では、次のようになっています。
すべてがうまく
いけば 、
https://developer.apple.comでプロビジョニングプロファイルを作成するときに、すべてのグッズを使用する権利を与えるキー
com.apple.developer.networking.HotspotHelperで
資格を選択することができます。

さらに、プロジェクトで
バックグラウンドモード機能を有効にし、
UIBackgroundModesセクションの
Info.plistに行
ネットワーク認証を記述する必要があります。 その後、最も興味深いコーディングに進むことができます。
登録
アプリケーションをホットスポットヘルパーにするには、システムに登録する必要があります。 これを行うには、次のメソッドを呼び出します。
class NEHotspotHelper class func register(options: [String : NSObject]? = nil, queue: DispatchQueue, handler: @escaping NetworkExtension.NEHotspotHelperHandler) -> Bool
このメソッドは3つのパラメーターを取ります。
ヘルパーを各開始時に1回だけ登録します。 同じ実行での呼び出しは何も与えず、
falseを返し
ます 。 再登録が完了するまで、アプリケーションはシステムによって起動されたコマンドを受信しないことに注意することが重要です。
いかなる方法でも登録をキャンセルすることはできません。 ブロックの登録を停止するだけで、アプリケーションは接続を処理しませんが、それでも起動します-
詳細はこちら 。
さらに、システムの他の多くの機能(フォトギャラリー、カレンダー、通知など)とは異なり、Hotspot Helperを使用したWi-Fi接続の処理はユーザーからの許可を必要とせず、ユーザーに対して透過的です(彼は単にそのような概念に遭遇しません) 。
コマンド処理
コマンドはNEHotspotHelperCommandクラスのオブジェクトであり、各コマンドに固有のタイプとデータセット(コマンドが示す場合はネットワークまたはネットワークのリスト)が含まれます。
各コマンドを処理した後、実行の結果と特定のコマンドにも依存するデータセットを使用してNEHotspotHelperResponseを作成します。
NEHotspotHelperResponseオブジェクトは、受信したコマンドでこのメソッドを呼び出すことにより作成されます。
func createResponse(_ result: NEHotspotHelperResult) -> NEHotspotHelperResponse
さらに、コマンドオブジェクトを使用すると、適切なメソッドを呼び出して、コマンドが属するネットワークに基づいて
TCPまたは
UDP接続を確立できます。
func createTCPConnection(_ endpoint: NWEndpoint) -> NWTCPConnection func createUDPSession(_ endpoint: NWEndpoint) -> NWUDPSession
サーバーとの高レベルの通信のために、NSURLRequestを作成できます。 Hotspot Helperにコマンドを添付すると、デバイスにWi-Fi接続が表示されない状況でサーバーと対話する機会が得られます。 この方法で確立された接続は、「独自の方法で」承認に使用できます。 IYKWIM
func bind(to command: NEHotspotHelperCommand)
以下では、Hotspot Helperがネットワークに接続する基本的なシナリオに対応する順序で受信できる各コマンドを検討します。 ほとんどのコマンドは、それらが呼び出されるステートマシンの状態と同様に名前が付けられます。
公式には、各コマンドの実行に割り当てられるの
は45秒以下です(ただし、バックグラウンドで利用可能な時間を見ると、60秒という数字を見ることができます)。 その後、チームは未処理と見なされ、Hotspot Helperの作業は中断されます。 この制限は、コマンドが処理されるまでステータスバーに切望されたWi-Fiアイコンが表示されないため、ネットワークに接続する際の不必要な遅延をなくすために必要です。 システム内に同じネットワークを処理する複数のホットスポットヘルパーが存在する場合、最速のものが選択されることを理解しておく必要があります(詳細については後述)。
NEHotspotHelperCommandType。 filterScanList
これは特別なコマンドであり、他のコマンドとは異なり、StateMachineのどの状態にも関連付けられておらず、いつでも呼び出すことができます。 このコマンドは、システムに認識されているすべてのホットスポットヘルパーで
5秒ごとに呼び出されます。 これは、ユーザーがシステムのSettings.appのWi-Fiネットワークのリストにいる間、常に発生します。
チームは、Hotspot Helperが処理しているネットワークをユーザーに示すという唯一の目的を果たします。 これを行うには、コマンドの対応するフィールドに使用可能なネットワークのリストが含まれます。
var networkList: [NEHotspotNetwork]? { get }
これは、ユーザーに表示されるリストと同じです。 さらに、ネットワークのリストは、チームへの新しい呼び出しごとに変わる場合があります。
Hotspot Helperはネットワークのリストを分析し、コマンドへの応答として提供する準備ができているものを返す必要があると想定されています。 回答の空の配列は、このヘルパーによるサービスに利用できるネットワークがないことを意味します。
リストからのネットワークユーザーの非表示は機能しません。Hotspot Helperがこのコマンドに応答して返したリスト内のネットワークには署名があります。 オプションkNEHotspotHelperOptionDisplayNameとしてHotspot Helperの最後の登録時に転送された値に対応します。 署名値は1つのみです。 登録中に設定され、次の登録まで変更することはできません(これはアプリケーションの再起動後に発生します)。したがって、悲しいかな、さまざまな方法でネットワークに署名することはできません。
応答としてネットワーク自体を送信することに加えて、ネットワーク
によって保護されている場合はパスワードを設定する必要があることに注意することが重要です。 これがないと、署名は表示されません。 パスワードが設定されている場合、署名に加えて、ユーザーは自分でパスワードを入力する必要はありません。 ネットワークのパスワードを設定できるのはこれだけです。 今すぐ確認しない場合は、ユーザーが実行する必要があります。
その結果、コマンドは次のように処理される必要があります。
let network = <A network from command.networkList> network.setPassword("PASSWORD") let response = command.createResponse(.success) response.setNetworkList([network]) response.deliver()
その結果、ユーザーには次のようなものが表示されます。
filterScanListコマンドは、ユーザーにネットワークのリストを示すために使用され、ネットワーク接続の残りの処理には影響しないことを理解してください。 Hotspot Helperコマンドに応答してネットワークが返されない場合、以下に説明するコマンドを使用して、それらのいずれかへの接続を処理するように提案されます。
興味深い事実:アプリケーションをアンインストールすると、ネットワークのリスト内の署名は、デバイスが再起動されるまで残ります。
NEHotspotHelperCommandType。 評価する
このコマンドは、システムが認識しているすべてのホットスポットヘルパー上のネットワークへの最初の接続時に呼び出されます。
注:後続の接続では、evaluateは呼び出されず、すぐに評価プロセスで選択されたHotspot Helperが維持されます。
このチームの目的は、最初に、選択したネットワークへの接続を処理するのに最適なホットスポットヘルパーネットワークを特定することです。 これを行うには、Hotspot Helperチームとともに、接続しているネットワーク経由でデータを受信します。
var network: NEHotspotNetwork? { get }
ネットワークには多くのプロパティが含まれていますが、評価コマンドの処理プロセスでは、次の値のみに値があります。
// var ssid: String { get } var bssid: String { get } // 0.0 1.0 (, , ) var signalStrength: Double { get } // var isSecure: Bool { get } // , , // var didAutoJoin: Bool { get }
この情報を受け取ったHotspot Helperは、(ローカルテーブルからサーバーへのリクエストで終わる)何らかの方法でネットワークを分析し、ネットワークを適切な
信頼レベルに設定する必要があります。
// Helper , . case none // Helper , , *. case low // Helper , . case high
*この場合、ユーザーにユーザーを承認する機会を提供できますが、ヘルパープロセスでこのネットワークと互換性がないことを理解した場合、彼はそれを使用することを拒否でき、StateMachineは再び評価状態に入り、ヘルパーは除外リストに追加されますこのネットワーク。注意することが重要です: Appleは、システム全体のUXに直接影響するため、信頼レベルは慎重に選択する必要があり、すべてのネットワークを高(さらには低)に設定する必要がある
ことを明確に明確にします。
その結果、コマンドは次のように処理される必要があります。
let network = command.network // confidence... network.setConfidence(<Appropriate level of confidence>) let response = command.createResponse(.success) response.setNetwork(network) response.deliver()
コマンドの処理には
45秒かかりますが、できるだけ早く実行するのが理にかなっています。 システムが最初の応答を高い信頼度で受信するとすぐに、コマンドの処理が終了するためです。 次に、ネットワーク接続をさらに処理するために応答するホットスポットヘルパーが選択され、他のすべては作業を停止して一時停止状態になります。
NEHotspotHelperCommandType。 認証する
authenticateコマンドは、evaluateコマンドの結果に基づいて最も適切なホットスポットヘルパーで呼び出されます。
このコマンドの目的は、選択したWi-Fiネットワークへの完全なユーザーアクセスを提供するために必要なすべての手順を実行することです。 これを行うには、Hotspot Helperチームとともに、接続しているネットワーク経由でデータを受信します。
var network: NEHotspotNetwork? { get }
Hotspot Helperの中核はこのチームの中核です。 この段階では、Hotspot Helperのみがユーザーとネットワークアクセスの間の障壁であり、ユーザーアクセスを許可するかどうかを開発者が想像できる方法で決定する必要があります。
コマンドの処理に
45秒が与えられた後、次の結果のいずれかで応答を返す必要があります。
.success-認証は正常に完了しました。 ネットワークアクセスは完全にオープンです。 StateMachineは認証済み状態に入ります。
.unsupportedNetwork-このネットワークはヘルパーによってサポートされていません:ネットワークは評価段階で誤って分析されました。 StateMachineは評価フェーズに戻り、このネットワークの例外にヘルパーが追加されます。 これは、たとえば、ヘルパーが評価段階でこのネットワークに対して低い信頼度を返し、現在では対応できないことを確認した場合に発生する可能性があります。
.uiRequired-ユーザーの操作が必要です。 この結果は、認証に追加のデータが必要な場合に返されます。 ただし、すべてがそれほど単純な
わけではありません 。
この結果が返されたとき 、
UI自体は表示されません 。
これは次のように機能します。ホットスポットヘルパーはUILocalNotificationによって生成され、これを介してユーザーに追加の対話の必要性を通知します。 ユーザーがそれを無視した場合、他には何も起こりません。 処理結果を受信すると、StateMachineはpresentingUI状態に入り、ネットワークからの承認または切断が完了するまでその状態のままになります。
.temporaryFailureは
修正可能なエラーです。 たとえば、認証中にネットワークエラーが発生しました。 StateMachineが障害状態になり、デバイスが選択したネットワークから切断されます。
.failure (またはその他の結果、およびその不在)は致命的なエラーです。 何かが完全にうまくいかず、接続を処理できません。たとえば、サーバー側の認証プロトコルが変更され、クライアントはこれに対応できていません。 StateMachineが障害状態になり、デバイスが選択したネットワークから切断されます。 また、temporaryFailureとは異なり、
このようなネットワークでは自動参加機能が無効になっています 。
その結果、コマンドは次のように処理される必要があります。
let network = command.network // // UILocalNotification (.uiRequired) command.createResponse(<Command result>).deliver()
NEHotspotHelperCommandType。 presentUI
このコマンドは、認証コマンドの処理中にuiRequired結果を返した場合、選択したホットスポットヘルパーで呼び出されます。
これは、バックグラウンドでアプリケーションを起動せず、実行時間が無制限の唯一のコマンドです。 これは、ユーザーがアプリケーションを起動した後にのみ届きます。たとえば、認証コマンドの処理プロセスでの追加の対話の必要性についてUILocalNotificationを受信した場合です。
この段階で、ネットワークが企業の場合はドメインローンを入力するようにユーザーに要求するか、ネットワークが商用の場合は広告を表示する必要があります。 要するに、オプションは開発者の想像力と常識によってのみ制限されます。
最後に、次の結果のいずれかで応答を返す必要があります。
.success-認証は正常に完了しました。 ネットワークアクセスは完全にオープンです。 StateMachineは認証済み状態に入ります。
.unsupportedNetwork-このネットワークはヘルパーによってサポートされていません:ネットワークは評価段階で誤って分析されました。 StateMachineは評価フェーズに戻り、このネットワークの例外にヘルパーが追加されます。 これは、たとえば、ヘルパーが評価段階でこのネットワークに対して低い信頼度を返し、現在では対応できないことを確認した場合に発生する可能性があります。
.temporaryFailureは
修正可能なエラーです。 認証中にネットワークエラーが発生したとします。 StateMachineが障害状態になり、デバイスが選択したネットワークから切断されます。
.failure (またはその他の結果、およびその不在)は致命的なエラーです。 何らかの問題が発生し、接続を処理できません。たとえば、サーバー側の認証プロトコルが変更され、クライアントはこれに対応できていません。 StateMachineが障害状態になり、デバイスが選択したネットワークから切断されます。 また、temporaryFailureとは異なり、
このようなネットワークでは自動参加機能が無効になっています 。
その結果、コマンドは次のように処理される必要があります。
let network = command.network // // command.createResponse(<Command result>).deliver()
NEHotspotHelperCommandType。 維持する
名前から推測できるように、maintainコマンドは、現在のネットワークでユーザー認証セッションを維持するように設計されています。 次の2つの場合、評価プロセスでネットワーク用に選択されたホットスポットヘルパーで呼び出されます。
- デバイスがWi-Fiネットワークに接続されている間、300秒(5分)ごと。
- 現在のホットスポットヘルパーが以前に選択された処理のために、evaluateコマンドの代わりにネットワーク接続を確立するとき。
どちらの場合でも、Hotspot Helperは認証セッションの現在の状態を分析し、次のいずれかのアクションを実行すると想定されています。
- ネットワークへのユーザーアクセスを即座に提供し(提供し続け)、結果.successで応答します。
- 結果.authenticationRequiredで応答を呼び出すことにより、再認証が必要になります(この場合、StateMachineはAuthenticating状態に入り、hotspot Helperにauthenticateコマンドを送信します)。
- エラーコード( .temporaryFailure / .failureまたは上記以外のもの)を使用してコマンドを完了することにより、セッションを継続できないことを報告します。 この場合、StateMachineは評価状態に入り、接続を処理できるホットスポットヘルパーを選択します。
Maintainコマンドが、コマンドで送信されたネットワーク上のデータ配列の2番目から呼び出される最初のケースを区別するために、特別なフラグ
-didJustJoinが
提供されます。
その結果、コマンドは次のように処理される必要があります。
let network = command.network if network.didJustJoin { // , Helper } else { // , ( 300 .) } // // command.createResponse(<Command result>).deliver()
再認証中は、デバイスが認証済み状態に戻るまで接続を利用できないことに注意してください。
NEHotspotHelperCommandType。 ログオフ
ご想像のとおり、logoffコマンド
はネットワークから切断されても送信されません 。
Hotspot Helperを使用してネットワークからの切断を追跡することはできません。このコマンドは、選択したホットスポットヘルパーの内部認証セッションを終了することを目的としており、静的メソッドNEHotspotHelperへの呼び出しに応答して送信されます。
class func logoff(_ network: NEHotspotNetwork) -> Bool
このメソッドは、現在のネットワークをパラメーターとして、それを許可したHotspot Helperを使用して、アプリケーションがアクティブな場合にのみ正常に呼び出すことができます。 そうでない場合、メソッドはfalseを返し、コマンドは呼び出されません。
その結果、StateMachineはLoggingOff状態に入り、ホットスポットヘルパーは切望されたコマンドとそれを実行するための
45秒を受け取ります。
次のようにして、メソッドに渡すネットワークを取得できます。
let network = NEHotspotHelper.supportedNetworkInterfaces().first
主な使用例:presentUIコマンドを使用した承認スクリプトに関連する、アプリケーションUIからのログイン。
Hotspot Helperがコマンドを完了すると(またはタイムアウトになると)、StateMachineは非アクティブ状態になり、デバイスはWi-Fiネットワークから切断されます。
その結果、コマンドは次のように処理される必要があります。
let network = command.network
このコマンドを受信する前に、アプリケーションはネットワークから切断するアクションを実行しないでください。これはシステム全体のUXに悪影響を与えるためです(実際、ユーザーには接続が表示されますが、データは送信されません)。
他に知っておくと良いこと
Hotspot Helperの動作原理と実装の詳細は上記で説明されています。 ただし、開発を開始する際に注意すべき機能がいくつかあります。
- Hotspot Helperはシミュレーターに登録できません-開発とデバッグには実際のデバイスが必要です。
- Hotspot Helperとして登録されたアプリケーションは、システム全体の動作がそれに依存するため、どのような状況でもバックグラウンドでシステムによって起動されます。 ユーザーがアプリケーションをアンロードした場合、バックグラウンドフェッチをオフにした場合、低電力モードをオンにした場合など。
- Hotspot Helperは、ネットワークの停止を監視する機能を提供していません(logoffコマンドが誤解を招くようにしてください。これは、ヘルパー自身による許可セッションの終了の処理です)。 シャットダウンを監視する必要がある場合は、到達可能性からの通知を使用する必要があります(それ自体で、アプリケーションがアクティブになります-バックグラウンドでは、システムはユーザーを呼び出しません)。
- デバイスが現在接続されているネットワークは、次のように見つけることができます。
let network = NEHotspotHelper.supportedNetworkInterfaces().first
このメソッドの迅速な署名(結果としてオプションではない配列を示す)と期待される動作(ネットワークがない場合は空の配列に見える)にもかかわらず、接続がない場合、SSIDとして空の文字列を持つネットワークオブジェクトを取得できます。 BSSIDおよび信号強度0.0。 , , nil ( crash). , .
Note: C iOS 11 .
- , StateMachine Authenticated. reachbility, , Hotspot Helper .
, , reachability Wi-Fi, Hotspot Helper . , :

, . , , .
- Helper .
Hotspot Helper, . , , .
evaluate: Hotspot Helper, high-confidence . Helper. Helper , . , Hotspot Helper .
, - Helper. : , . Apple UI ( SSID).
, - Hotspot Helper . , , — , Hotspot Helper . :
let network = NEHotspotHelper.supportedNetworkInterfaces().first if !network.isChosenHelper {
, false , Helper (, evaluate). , , . .
- , . :
func createTCPConnection(_ endpoint: NWEndpoint) -> NWTCPConnection func createUDPSession(_ endpoint: NWEndpoint) -> NWUDPSession
NSMutableURLRequest:
func bind(to command: NEHotspotHelperCommand)
- iOS10.3, , . - , . : . , - — .
, , .
- iOS 11 NEHotspotHelper NEHotspotConfigurationManager , Wi-Fi . . :
- , (, - .);
- , Wi-Fi- (, ). .
おわりに
数年前に登場したNEHotspotHelperテクノロジーは、今日までその関連性を失っていません。このツールを使用すると、ネットワークサービスを使用するプロセスを大幅に改善および促進できます。ここでは、作業の基本原則、適用方法、およびそれを効果的に使用するために実行する必要があるすべての手順を調べました。さらに、彼は、Helperのいくつかの機能について話しましたが、その機能についてはドキュメントは巧妙に静かです。プロジェクトでこのことを使用する理由と方法を完全に理解していただければ幸いです。しかし、質問があれば、書いてください、私はそれらに答える準備ができています。便利なリンク
- GitHubの実装例
- ホットスポットネットワークサブシステムプログラミングガイド
- ネットワーク拡張
- NEhotspotHelperリファレンス
- WWDC'15 What's New in Network Extension and VPN
- WWDC'17 Advances in Networking, Part 1
- Forum: How to cancel register an app as a Hotspot Helper (NEHotspotHelper)?
- Forum: entitlements
- Forum: U I
- HotspotHelper