BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース AppleがExposure Notification ベータ版とベストプラクティスのサンプルアプリを備えたiOS 13.5をリリース

AppleがExposure Notification ベータ版とベストプラクティスのサンプルアプリを備えたiOS 13.5をリリース

原文(投稿日:2020/05/25)へのリンク

iOSの最新リリースであるiOS 13.5は、Exposure Notification APIのベータサポートを含んでいる。これは接触追跡アプリを有効にするためにAppleがGoogleと共同で定義したものである。Appleは、また、接触追跡アプリのベストプラクティスを紹介するサンプルアプリも公開した。

実際のフレームワーク実装を提供するだけでなく、iOS 13.5には、ユーザが接触ログにオプトインまたはオプトアウトできる基本的なユーザ向け認証メカニズムが含まれている。Exposure Notification APIを使用するアプリはまだ利用できないため、Exposureのログ設定は無効になる。一部の保健当局によって開発されたサードパーティのアプリをインストールすると、ユーザはオプトインまたはオプトアウトするオプションが与えられる。

接触追跡アプリを作成したいサードパーティが作成を容易にするために、Appleはリファレンスデザインを提供するサンプルアプリを公開した。このサンプルには、フレームワークを使用する際のベストプラクティスを示すだけでなく、中央サーバの応答をシミュレートして診断キーの共有と暴露基準の管理を実装するためのコードも含んでいる。

Appleサンプルアプリは、起動時にユーザがExposureログを有効にしているかどうかを確認し、有効になっていない場合は有効にするように求める。iOSによって管理される他の特権で通常発生することとは異なり、Exposure Notification APIは、アプリがENManagerシングルトンを介して承認メカニズムを明示的にトリガするメカニズムを提供する。

static func enableExposureNotifications(from viewController: UIViewController) {
    ExposureManager.shared.manager.setExposureNotificationEnabled(true) { error in
        NotificationCenter.default.post(name: ExposureManager.authorizationStatusChangeNotification, object: nil)
        if let error = error as? ENError, error.code == .notAuthorized {
            viewController.show(RecommendExposureNotificationsSettingsViewController.make(), sender: nil)
        } else if let error = error {
//...
        }
    }
}

Appleのサンプルは、ユーザが最初のリクエストで許可を拒否した場合に、サービスを2回有効にするようにユーザに求めるところまで行っている。これは明らかに要件ではないが、これが受け入れられた慣行であるとAppleが考えていることを示唆している。つまり、ユーザの許可を収集するこのような積極的な戦略は、最終的なApp Storeレビュープロセスで拒否される原因とは見なされない。

アプリは、ユーザがオンボーディングしたかどうかを示すフラグ、行った検査に関するデータ、サーバと共有したかどうかなど、ローカルに記録するすべてのデータを保存する。すべてのユーザデータを中央サーバに保存する必要はない。ローカルに保存するとユーザのプライバシが維持されるため、これはExposure Notificationプロトコルの重要な機能である。

ユーザがCOVID-19と確実に診断された場合にのみ、中央サーバと共有することを決定できる。これには、アプリが診断キーのリストを取得する必要がある。これにより、ユーザは毎回明示的な認証を提供し、それをサーバに送信する必要がある:

func getAndPostDiagnosisKeys(testResult: TestResult, completion: @escaping (Error?) -> Void) {
    manager.getDiagnosisKeys { temporaryExposureKeys, error in
        if let error = error {
            completion(error)
        } else {
            // In this sample app, transmissionRiskLevel isn't set for any of the diagnosis keys. However, it is at this point that an app could
            // use information accumulated in testResult to determine a transmissionRiskLevel for each diagnosis key.
            Server.shared.postDiagnosisKeys(temporaryExposureKeys!) { error in
                completion(error)
            }
        }
    }
}

サンプルアプリはまた、バックグラウンドタスクを使用して、COVID-19診断を受けていないユーザの曝露を定期的にチェックする。バックグラウンドタスク識別子は .exposure-notification で終わる必要がある。これにより、操作を完了するためにより多くのバックグラウンド時間が自動的に受信される。さらに、タスクを所有するアプリは、実行されていないときに、より頻繁に起動される。バックグラウンドタスクは、アプリの detectExposures メソッドを呼び出して、ユーザが公開されたかどうかを確認し、自分自身を再スケジュールする。

BGTaskScheduler.shared.register(forTaskWithIdentifier: AppDelegate.backgroundTaskIdentifier, using: .main) { task in
    
    // Notify the user if bluetooth is off
    ExposureManager.shared.showBluetoothOffUserNotificationIfNeeded()
    
    // Perform the exposure detection
    let progress = ExposureManager.shared.detectExposures { success in
        task.setTaskCompleted(success: success)
    }
    
    // Handle running out of time
    task.expirationHandler = {
        progress.cancel()
        LocalStore.shared.exposureDetectionErrorLocalizedDescription = NSLocalizedString("BACKGROUND_TIMEOUT", comment: "Error")
    }
    
    // Schedule the next background task
    self.scheduleBackgroundTaskIfNeeded()
}

最後に、Exposure Notificationフレームワークは、接触が検出されるたびにリスクを推定する方法を提供する。これは、相互作用がいつ発生したか、および検出されたデバイスの近接性に基づいてそれがどのくらい続いたかを考慮に入れている。アプリは、通常サーバから送信される ENExposureConfiguration オブジェクトを提供することでリスクの推定方法を変更し、最終的に finish を呼び出してローカルストアを更新し、検索を完了することができる。ENExposureConfiguration オブジェクトは、最小リスク、感染リスク、接触期間、最後の曝露からの日数などのパラメータをサポートする。

ENExposureConfiguration オブジェクトは、シングルトン ENManagerdetectExposures(configuration:diagnosisKeyURLs:completionHandler:) メソッドに渡される。検出された暴露ごとに、アプリは getExposureInfo(summary:userExplanation:completionHandler:) を使用して追加情報を取得できる:

Server.shared.getExposureConfiguration { result in
    switch result {
    case let .success(configuration):
        ExposureManager.shared.manager.detectExposures(configuration: configuration, diagnosisKeyURLs: localURLs) { summary, error in
            if let error = error {
                finish(.failure(error))
                return
            }
            let userExplanation = NSLocalizedString("USER_NOTIFICATION_EXPLANATION", comment: "User notification")
            ExposureManager.shared.manager.getExposureInfo(summary: summary!, userExplanation: userExplanation) { exposures, error in
                    if let error = error {
                        finish(.failure(error))
                        return
                    }
                    let newExposures = exposures!.map { exposure in
                        Exposure(date: exposure.date,
                                 duration: exposure.duration,
                                 totalRiskScore: exposure.totalRiskScore,
                                 transmissionRiskLevel: exposure.transmissionRiskLevel)
                    }
                    finish(.success((newExposures, nextDiagnosisKeyFileIndex + localURLs.count)))
            }
        }
        
    case let .failure(error):
        finish(.failure(error))
    }
}

Exposure Notification APIは、iOS 13.5とXcode 11.5が必要である。

この記事に星をつける

おすすめ度
スタイル

BT