Xcode Capabilities Background Modesのまとめ

# はじめに
iOSアプリのバックグラウンド動作は管理された配下で動作します。
そこで、CapabilitiesのBackground Modesの選択肢についてまとめてみます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42735/c46883d6-b865-e631-e25b-67d981df92fa.png" width=400>

# 詳細
[Configuring Background Execution Modes](https://developer.apple.com/documentation/xcode/configuring-background-execution-modes)に概要は記載されています。
各項目は下記のように記載されています。

| 項目                                   | 詳細                                                         |
| :------------------------------------- | :----------------------------------------------------------- |
| Audio, AirPlay, and Picture in Picture | アプリはバックグラウンドで可聴コンテンツを再生します。詳しくは、[Enabling Background Audio](https://developer.apple.com/documentation/watchkit/storyboard_support/playing_background_audio)をご覧ください。 |
| Location updates                       | このアプリは位置情報を提供するもので、プラットフォーム標準の位置情報サービスを利用する必要があります。詳しくは、[Using the Standard Location Service](https://developer.apple.com/documentation/corelocation/handling_location_updates_in_the_background)をご覧ください。 |
| Voice over IP                          | このアプリはVoice over IPサービスを提供し、システムの（再）起動後に自動で起動する必要があります。詳しくは、[CallKit](https://developer.apple.com/documentation/callkit)フレームワークを参照してください。 |
| External accessory communication       | アプリは、一定時間ごとにデータを配信するアクセサリーと通信します。詳しくは、[External Accessory](https://developer.apple.com/documentation/externalaccessory)フレームワークをご覧ください。 |
| Uses Bluetooth LE accessories          | アプリはバックグラウンドでBluetoothアクセサリーと通信します。詳しくは、[Core Bluetooth](https://developer.apple.com/documentation/corebluetooth)フレームワークを参照してください。|
| Acts as a Bluetooth LE accessory       | このアプリは、Bluetoothアクセサリと通信するために周辺機器モードを使用します。詳しくは、[Core Bluetooth](https://developer.apple.com/documentation/corebluetooth)フレームワークを参照してください。 |
| Background fetch                       | アプリは、一定の間隔でネットワークから新しいコンテンツを要求します。詳しくは、[Using Background Tasks to Update Your App](https://developer.apple.com/documentation/uikit/app_and_environment/scenes/preparing_your_ui_to_run_in_the_background/using_background_tasks_to_update_your_app)をご覧ください。 |
| Remote notifications                   | アプリは、新しいコンテンツがダウンロードできるようになったことを示す信号としてプッシュ通知を使用します。詳しくは、[Pushing Background Updates to Your App](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app)をご覧ください。 |
| Background processing                  | このアプリはバックグラウンドでスケジュールされたタスクを実行します。詳しくは、[BGTaskScheduler](https://developer.apple.com/documentation/backgroundtasks/bgtaskscheduler)を参照してください。 |

([Configuring Background Execution Modes](https://developer.apple.com/documentation/xcode/configuring-background-execution-modes)より抜粋、DeepLを使い日本語に翻訳)

各項目でポイントとなりそうなAppleDeveloperドキュメントおよびWWDC動画を抜粋します。

## Audio, AirPlay, and Picture in Picture
オーディオ機能に関するバックグラウンド再生時に設定する

#### [Configuring the Audio Playback of iOS and tvOS Apps](https://developer.apple.com/documentation/avfoundation/media_playback_and_selection/configuring_the_audio_playback_of_ios_and_tvos_apps)より抜粋

> バックグラウンドオーディオを有効にする
> iOSとtvOSのアプリは、いくつかのバックグラウンド操作のために、特定の機能を有効にする必要があります。再生アプリが必要とする一般的な機能は、バックグラウンドオーディオの再生です。この機能を有効にすると、ユーザーが別のアプリに切り替えたときやiOSデバイスをロックしたときにも、アプリのオーディオが継続されます。このケイパビリティは、iOSのAirPlayストリーミングやピクチャー・イン・ピクチャー再生などの高度な再生機能を有効にする場合にも必要です。
>
> これらの機能を設定する最も簡単な方法は、Xcodeを使用することです。Xcodeでアプリのターゲットを選択し、[Signing & Capabilities]タブを選択します。Capabilities タブで、Background Modes ケーパビリティを追加し、バックグラウンドモードのリストで "Audio, AirPlay, and Picture in Picture" オプションを選択します。
> 
> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42735/1b1ba250-dfec-9c13-b067-e933342dff03.png" width=300>
> 
> このモードを有効にし、オーディオセッションを設定すると、アプリでバックグラウンドオーディオを再生する準備が整います。

(DeepLを使い日本語に翻訳）

#### [Adopting Picture in Picture in a Custom Player](https://developer.apple.com/documentation/avkit/adopting_picture_in_picture_in_a_custom_player)より抜粋

> オーディオ セッションとバックグラウンド モードを設定する
> iOS と tvOS で PiP に参加するには、オーディオ セッションとバックグラウンド モードを設定して、アプリのオーディオ再生機能をカスタマイズします。詳細は、[「iOS および tvOS アプリのオーディオ再生を設定する(Configuring the Audio Playback of iOS and tvOS Apps)」](https://developer.apple.com/documentation/avfoundation/media_playback_and_selection/configuring_the_audio_playback_of_ios_and_tvos_apps) を参照してください。

(DeepLを使い日本語に翻訳）


## Location updates

CoreLocationの位置情報をバックグラウンドで取得するときに使う。
CoreLocationをバックグラウンで使うときは、CLLocationManagerの`allowsBackgroundLocationUpdates`プロパティを`true`にする必要がある。

#### [Handling Location Events in the Background](https://developer.apple.com/documentation/corelocation/getting_the_user_s_location/handling_location_events_in_the_background)より抜粋
> アプリは通常、フォアグラウンドでほとんどの位置情報サービスを使用しますが、いくつかの位置情報サービスは、バックグラウンドで実行したり、システムがアプリを起動する原因になることもあります。バックグラウンドでイベントを受信するには、以下のように Xcode でアプリの "Location updates" ケーパビリティを設定します。また、CLLocationManagerオブジェクトの`allowsBackgroundLocationUpdates`プロパティをtrueに設定する必要があります。

(DeepLを使い日本語に翻訳）


## Voice over IP

インターネット電話の着信画面([CallKit](https://developer.apple.com/documentation/callkit))を表示するために用いる。
手順については[Voice Over IP (VoIP) Best Practices](https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/OptimizeVoIP.html#//apple_ref/doc/uid/TP40015243-CH30)を参照してください。

#### WWDC19のビデオ[Advances in App Background Execution](https://developer.apple.com/wwdc19/707) 8:56より抜粋

> では次に通話を見てみましょう
> 普段はメッセージで済ませていても― 直接 話して 手早く何かを伝えたい時もあるでしょう 使うAPIはVoIPプッシュ通知です これはアプリケーションを起動して― 通話できるよう 着信を知らせる特別なプッシュです
> 使うにはPKPushRegistryで― VoIPのプッシュタイプを 設定すればいいのです
> 今年からdidReceiveIncomingPush コールバックの CallKitで 着信を報告しないと Appが 終了させられるようになりました もし繰り返し 着信の報告をしなかった場合― VoIPプッシュで Appが起動しなくなることもあります  ではコードを見ていきましょう didReceiveIncomingPushコールバック プッシュタイプはVoIPです PushPayloadの情報を CXCallUpdateオブジェクトに追加して 着信の報告はproviderを使います

## External accessory communication

詳しい解説を発見することができませんでした。ただしMFi認証を取得したデバイスを操作するため今回は省略します。

## Uses Bluetooth LE accessories

Bluetooth LEをセントラルモードでバックグラウンド動作するときに用いる。

#### [Core Bluetooth Background Processing for iOS Apps](https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/CoreBluetoothBackgroundProcessingForIOSApps/PerformingTasksWhileYourAppIsInTheBackground.html)より抜粋

> bluetooth-central バックグラウンド実行モード
> central の役割を実装するアプリが、その Info.plist ファイルに "bluetooth-central" という値を持つ UIBackgroundModes キーを含めると、Core Bluetooth フレームワークはアプリをバックグラウンドで実行し、特定の Bluetooth 関連タスクを実行できるようにします。アプリがバックグラウンドにある間も、周辺機器を発見して接続し、周辺データを探索したり操作したりすることができます。さらに、CBCentralManagerDelegate または CBPeripheralDelegate デリゲートメソッドのいずれかが呼び出されると、システムはアプリをウェイクアップし、接続が確立または解除されたとき、周辺機器が更新した特性値を送信したとき、セントラルマネージャの状態が変化したときなど、重要なセントラルロールイベントをアプリで処理できるようにします。
> 
> アプリがバックグラウンドにあるときでも多くの Bluetooth 関連タスクを実行できますが、アプリがバックグラウンドにあるときの周辺機器のスキャンは、アプリがフォアグラウンドにあるときとは異なる動作をすることに留意してください。特に、アプリがバックグラウンドでデバイスのスキャンを行う場合。
> 
> CBCentralManagerScanOptionAllowDuplicatesKeyスキャンオプションキーは無視され、アドバタイズペリフェラルの複数検出は単一の検出イベントに合体されます。
> ペリフェラルスキャンしているすべてのアプリがバックグラウンドにある場合、セントラルデバイスがアドバタイジングパケットをスキャンする間隔が長くなります。その結果、広告周辺機器を発見するのに時間がかかることがあります。
> これらの変更は、無線使用量を最小限に抑え、iOSデバイスのバッテリー寿命を向上させるのに役立ちます。

(DeepLを使い日本語に翻訳）


## Acts as a Bluetooth LE accessory

Bluetooth LEをペリフェラルモードでバックグラウンド動作するときに用いる。

#### [Core Bluetooth Background Processing for iOS Apps](https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/CoreBluetoothBackgroundProcessingForIOSApps/PerformingTasksWhileYourAppIsInTheBackground.html)より抜粋

> bluetooth-peripheral バックグラウンド実行モード
バックグラウンドで特定のペリフェラルの役割のタスクを実行するには、アプリの Info.plist ファイルに "bluetooth-peripheral" 値を持つ UIBackgroundModes キーをインクルードする必要があります。このキーと値のペアがアプリの Info.plist ファイルに含まれると、システムはアプリを起動して読み取り、書き込み、およびサブスクリプション イベントを処理します。
> 
> Core Bluetooth フレームワークでは、接続されたセントラルからの読み取り、書き込み、および購読の要求を処理するためにアプリを起動できることに加え、アプリがバックグラウンド状態にある間に広告を出すことができます。ただし、アプリがバックグラウンドにあるときの広告は、アプリがフォアグラウンドにあるときとは異なる動作をすることに注意する必要があります。特に、アプリがバックグラウンドで広告を出す場合、以下のようになります。
> 
> - CBAdvertisementDataLocalNameKeyアドバタイズキーは無視され、ペリフェラルのローカル名はアドバタイズされません。
> - CBAdvertisementDataServiceUUIDsKey アドバタイズメントキーの値に含まれるすべてのサービス UUID は、特別な「オーバーフロー」領域に配置され、それらを明示的にスキャンしている iOS デバイスによってのみ検出されるようになります。
> - アドバタイジングを行うすべてのアプリがバックグラウンドにある場合、周辺デバイスがアドバタイジングパケットを送信する頻度が減少することがあります。

(DeepLを使い日本語に翻訳）


## Background fetch

[Using Background Tasks to Update Your App](https://developer.apple.com/documentation/uikit/app_and_environment/scenes/preparing_your_ui_to_run_in_the_background/using_background_tasks_to_update_your_app)に記載があるが、短時間で処理が終わるバックグラウンド動作をするときに使う[BGAppRefreshTask](https://developer.apple.com/documentation/backgroundtasks/bgapprefreshtask)クラスを用いるときにチェックをつける。

#### WWDC19のビデオ[Advances in App Background Execution](https://developer.apple.com/wwdc19/707) 17:12より抜粋

> そこで 新しいバックグラウンドモードと フレームワークBackgroundTasksを 紹介します BackgroundTasksは 作業を後でやるよう予定を組みます iOS iPadOS tvOS そして MacのiPad Appで利用可能です 新しいモード Background Processing Tasksを紹介すると共に この機会を利用し 既存のAPIの改善にも取り組みました
> (中略)
> 次に新API Background App Refreshについて 既存のAPIとポリシーは変わりません 30秒のランタイムで 起動するたび 新しいコンテンツをフェッチします
> (中略)
> これがAppです ColorFeedという名前です 写真でなく 最新の色のトレンドが見られます スクロールして― 時間ごとに 最新の色が何だったかが示されます このAppを ユーザの手を借りず最新の状態で― 保てるようにしたいと思います Background Tasksで BackgroundAppRefreshを実装します まず最初に info.plistに必要なキーを追加して BackgroundTasksと リフレッシュのサポートを宣言します そこでプロジェクトの設定を開きます


## Remote notifications

サイレントPUSH通知を使うときにチェックします。
機能概要は、WWDCビデオを確認できます。
下記が主なハイライトです。

#### WWDC15のビデオ[What's New in Notifications](https://developer.apple.com/wwdc15/720) 1:32より抜粋
> *サイレント通知は、無音です。ユーザーにはUIが表示されません。電話のブザーも鳴らしません。ですから、ユーザーに通知するために使うのではありません。自分のアプリに通知するために使うのです。*
> *リモート通知です。つまり、インターネットから送られてくるのです。ここにあなたのサーバーとあなたのアプリがあります。サーバーはアプリに通知を送信し、コンテンツ利用可能フラグを1に送信すると、アプリはダウンロードすべき新しいコンテンツがあることを認識し、ダウンロードを開始するのです。*
> *サイレント通知は、デフォルトで有効になっています。ユーザーは、あなたの--は、あなたのアプリに使用する許可を与える必要はありませんし、あなたはユーザーに許可を求めることなく、ただ使い始めることができます。*

(DeepLを使い日本語に翻訳）

#### WWDC19のビデオ[Advances in App Background Execution](https://developer.apple.com/wwdc19/707) 12:20より抜粋

> そこでバックグラウンドプッシュです デバイスにだけ 新しいデータを知らせる仕組みです
> content-availableを１に設定した プッシュを alert sound badgeなしで送ります  いつアプリケーションを起動して ダウンロードするか システムが 電力状況などを考えて判断します 図で見ればこんな感じでしょう ユーザがスレッドをミュートします 誰かがメッセージを送ると バックグラウンドプッシュが届きます その後どこかでアプリケーションが 起動され データをフェッチします ユーザがアプリケーションを開くと― スレッドで メッセージを見ることができます ここでも注意点があります apns-priority = 5に設定しなければ アプリケーションは起動しません


## Background processing

[Using Background Tasks to Update Your App](https://developer.apple.com/documentation/uikit/app_and_environment/scenes/preparing_your_ui_to_run_in_the_background/using_background_tasks_to_update_your_app)に記載があるが、時間のかかる処理をバックグラウンドで行うときに使う[BGProcessingTask](https://developer.apple.com/documentation/backgroundtasks/bgprocessingtask)クラスを用いるときにチェックをつける。

詳しくは、Background fetchにあるWWDCビデオを参照