iOSのExposureNotificationのAPIをサンプルアプリとドキュメントから見てみる


ExposureNotification概要

ExposureNotificationはCOVID-19への潜在的な曝露を人々に通知します。
ExposureNotificationの機能を実現するにはExposure Notification Serverの実装が必須です。

おことわり

リリースするには Exposure Notification Entitlement Requestで申請する必要があり、ハードルが高いので、
あくまで、公式ドキュメントとサンプルアプリのシミュレータでの確認になっています。
大いに間違っている可能性があるので公式ドキュメントを正としてください。

実機ビルドするだけであれば、Code Signing Entitlements の項目を外すことでビルドは可能ですが、機能を使える保証はないです。

公式ドキュメント

サンプルアプリ

https://developer.apple.com/documentation/exposurenotification/building_an_app_to_notify_users_of_covid-19_exposure

ENManager

activate

func activate(completionHandler: @escaping ENErrorHandler)

ENManagerを使う前に最初に呼び出す。
これを行い、完了ハンドラが戻ってきたところでENManagerの機能が使えるようになる。

setExposureNotificationEnabled

func setExposureNotificationEnabled(_ enabled: Bool,completionHandler: @escaping ENErrorHandler)

曝露通知を有効/無効にするクラス。
自動的に通知許可をもらうダイアログも表示する。
許可が断られた場合、completionHandlerはENError.notAuthorizedを返す?
enabledをfalseにした場合、 Bluetoothのスキャンとアドバタイズを停止するが、取得していた診断データはそのまま残る。
残念ながらシミュレータで動作させてもDomain=NSOSStatusErrorDomain Code=-71148 のErrorになります。

detectExposures

func detectExposures(configuration: ENExposureConfiguration, 
    diagnosisKeyURLs: [URL], 
   completionHandler: @escaping ENDetectExposuresHandler) -> Progress

曝露を検出する。
diagnosisKeyURLsは、Exposure Notification ServerからダウンロードしたキーのローカルURLとする。
configurationに関しても、Exposure Notification Serverから取得するデータから生成することをサンプルアプリでは想定している。

このAPIはBluetooth経由で得ているデータをワンショット返すようで、サンプルアプリではBackgroundTasksフレームワークを用いて定期的に検出を行っている。

completionHandlerで返ってくる ENDetectExposuresHandler には ENExposureDetectionSummary が含まれていて、後述の getExposureInfo で使用する。

getExposureInfo

func getExposureInfo(summary: ENExposureDetectionSummary, 
     userExplanation: String, 
   completionHandler: @escaping ENGetExposureInfoHandler) -> Progress

前述の detectExposures から得た ENExposureDetectionSummary をパラメータにして曝露情報を取得する。
userExplanation はUIの一部としてユーザーに表示するために使われる。
コールバックとして ENExposureInfo が受け取れる。
サンプルアプリではこの情報を独自の構造にマッピングしてローカルに保存している。

getDiagnosisKeys

func getDiagnosisKeys(completionHandler: @escaping ENGetDiagnosisKeysHandler)

ENTemporaryExposureKey を取得する。
このメソッドを呼び出すたびに、ユーザーは承認を行う必要がある。
このキーはそのままExposure Notification Serverに送信する必要があり、サンプルアプリでは一旦JSONにデコードして送信する想定となっている。

getTestDiagnosisKeys

func getTestDiagnosisKeys(completionHandler: @escaping ENGetDiagnosisKeysHandler)

getDiagnosisKeys のテスト用API。
シミュレータで動作させてもDomain=NSOSStatusErrorDomain Code=-71148 のErrorになります。

invalidate

func invalidate()

ENManagerを無効にする。

ENStatus

曝露通知システムの有効状態を示すenum。
特筆したいのがbluetoothOffという種別であり、ENStatusにしかBluetooth使用を示すものがないので、ExposureNotificationのフレームワーク内で完全にBluetoothの処理は閉じていてBluetoothに対するコントロールは出来なさそう。

tvOS14(おまけ)

tvOS14にもExposureNotification.frameworkが有効なんですが、

  • ENAuthorizationStatus
  • ENStatus
  • ENError

と、限定的なAPIしか使えず、メインのENManagerが使えない模様。