目次
Session概要
ローカルプッシュ接続性を活用し、Appサーバからネットワーク上のデバイスへ、インターネット接続の無い状況でも通知を配信できます。制約されたネットワーク環境で実行するApp向けに通知を構築する方法、期待されるインターネット接続時と同様の信頼性と体験を提供しコミュニケーションを継続するための通知を構築する方法について。
この技術を利用するためにAppでどのように実装するかも説明します。 https://developer.apple.com/videos/play/wwdc2020/10113/
ローカルプッシュについて
- デバイスがインターネットに接続していなくても利用可能
iOS 14で追加された新しいAPI
- Wi-Fiネットワークで動作する独自のPush接続サービスの作成を可能にする
Push通知の構成
- プロバイダサーバからApple Push通知サービス(APN)へプッシュ通知依頼を送ります
- APNは対象デバイスに対して対応する通知ペイロードを送信する
- 通知タイプによってペイロードを受け取るためにPushKitかUserNotificationsのいずれかのフレームワークを使用する
- ただし、オフライン環境ではPush通知が送れない
- ローカルPush接続はこの問題を解決するために設計されたソリューション
- iOS 14ではローカルPush接続APIが追加された
- NetworkExtensionの一部
- NetworkExtensionの一部

ローカルPushの接続性
- ローカルPush接続APIにより、プロバイダサーバと通信するアプリケーション拡張機能を構築することが出来る
- APNはないので、プロバイダサーバとアプリケーション拡張の間で通知を届ける
- プロトコルを独自で定義する必要がある
- 有効にするWi-Fiネットワークをアプリケーションで指定する必要があり、接続するとシステムがアプリケーション拡張機能を起動する。
- アプリケーション拡張機能はプロバイダサーバとのネットワーク接続を維持し、通知を受け取る責務を負う
- 指定されたWi-Fi環境に接続している限り、アプリケーション拡張機能はバックグラウンド実行し続ける
- 反対に指定されたWi-Fi環境の接続を失うとシステムはアプリケーション拡張機能を停止する
- ローカルPush接続のユースケース
- ネットワーク環境が限定されている
- そのネットワーク環境におけるユーザの要求によって定義される
- 新しい権限を申請する必要がある

ローカルPush Connectivity API
- NEAppPushManager
- 親アプリは NEAppPushManagerのインスタンスを使用して設定を作成し、ローカルPushが動作するWi-Fiネットワークの情報が含まれている
- 設定を読み込み、保存、削除 可能
- VoIPアプリを実装する場合は、デリゲートを設定するためにも使用する
- 親アプリは NEAppPushManagerのインスタンスを使用して設定を作成し、ローカルPushが動作するWi-Fiネットワークの情報が含まれている
- NEAppPushProvider
- 親アプリとアプリケーション拡張機能はこの権限を持っている必要がある
- アプリケーション拡張機能のライフサイクルを管理し、起動時と終了時にシステムに呼び出される
Sampleコード
NEAppPushManagerの設定import NetworkExtension
let manager = NEAppPushManager()
// 有効にしたいSSIDの範囲を指定
manager.matchSSIDs = [ "Cruise Ship Wi-Fi", "Cruise Ship Staff Wi-Fi" ]
// アプリケーション拡張機能のバンドルID
manager.providerBundleIdentifier = "com.myexample.SimplePush.Provider"
manager.providerConfiguration = [ "host": "cruiseship.example.com" ]
manager.isEnabled = true
// 実行後、システムはこの設定を使ってローカルPush接続を有効化する
manager.saveToPreferences { (error) in
if let error = error {
// Handle error
return
}
// Report success
}
// Manage App Extension life cycle and report VoIP call
class SimplePushProvider: NEAppPushProvider {
override func start(completionHandler: @escaping (Error?) -> Void) {
// Connect to your provider server
completionHandler(nil)
}
override func stop(with reason: NEProviderStopReason,
completionHandler: @escaping () -> Void) {
// Disconnect your provider server
completionHandler()
}
func handleIncomingVoIPCall(callInfo: [AnyHashable : Any]) {
reportIncomingCall(userInfo: callInfo)
}
}
class AppDelegate: UIResponder, UIApplicationDelegate, NEAppPushDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey: Any]?) -> Bool {
NEAppPushManager.loadAllFromPreferences { (managers, error) in
// Handle non-nil error
for manager in managers {
manager.delegate = self
}
}
return true
}
func appPushManager(_ manager: NEAppPushManager,
didReceiveIncomingCallWithUserInfo userInfo: [AnyHashable: Any] = [:]) {
// Report incoming call to CallKit and let it display call UI
}
}
Voice over IP
バックグラウンドモード有効にしている必要がある