LASSIC Media らしくメディア
アプリのフォアグラウンド常駐処理の実装
LASSIC IT事業部|元請(プライムベンダー)としてシステム保守・運用を受託
この記事のポイント
- 画面に無い間も継続実行する常駐処理は、AndroidのForeground Service(永続通知が必須)とiOSのBackground Modes(用途限定)という別々の仕組みで実装します。
- アプリが前面にない間の遅延実行(BGTaskScheduler・WorkManager)とは別論点であり、ユーザーに可視の継続実行に絞って検討する必要があります。
- Android 14ではforegroundServiceTypeの宣言が必須になり、型ごとに異なる権限とマニフェスト宣言を満たす設計が求められます。
目次
フォアグラウンド常駐処理とは
フォアグラウンド常駐処理とは、位置情報の継続取得・音楽再生・通話・データ同期など、ユーザーがアプリの画面を開いていない間も処理を止めずに動かし続ける実装を指します。走行ログを記録するフィットネスアプリや、地図アプリの経路案内、音楽再生アプリのバックグラウンド再生などが代表例です。この種の処理は、アプリが画面から離れた瞬間にOSが実行を止めてしまうと機能そのものが成立しないため、通常のアプリ実行とは別の仕組みでOSに継続実行を申告する必要があります。
ここで扱う常駐処理は「ユーザーに可視の継続実行」に限定します。AndroidのWorkManagerやiOSのBGTaskSchedulerが担う「アプリが前面にない間、OSが都合の良いタイミングでまとめて実行する遅延実行」(バックグラウンド同期やバッチ処理など)とは目的も実装方式も異なる別論点であり、本稿では扱いません。遅延実行の設計については別稿で解説しているため、常駐処理との混同を避け、要件に応じて仕組みを使い分けることが重要です。
常駐処理を実現する仕組みはOSごとに大きく異なります。Androidでは永続通知を伴うForeground Serviceという明示的なサービス形態を使い、iOSではBackground Modesという用途限定の宣言によってアプリ全体に特定の継続実行権を与える設計です。両OSとも、常駐処理はバッテリー消費とユーザーのプライバシーに直結するため、OS側が起動条件や宣言方法を年々厳格化してきた経緯があります。発注前にこの前提を理解しておくことが、要件定義の精度を左右します。
AndroidのForeground Service — 永続通知と起動制限
Androidでフォアグラウンド常駐処理を実装する仕組みがForeground Service(前面サービス)です。公式ドキュメントでは、フォアグラウンドサービスはユーザーに知覚可能な処理を行うサービスと定義されており、通知の表示を義務付けています*1。この通知は、サービスが停止するかフォアグラウンドから外れるまで、ユーザー側から消すことができない仕様です*1。走行ログを記録するフィットネスアプリが、移動距離を通知に表示し続ける例が公式に挙げられています*2。
Android 12以降はバックグラウンドからの起動が原則不可
Android 12(APIレベル31)以降をターゲットとするアプリは、アプリ自体がバックグラウンドで動作している間はフォアグラウンドサービスを起動できないという制限が導入されました*3。例外条件に該当しない状態で起動を試みると、システムはForegroundServiceStartNotAllowedExceptionをスローします*3。例外として認められる主なケースには、ユーザーが操作したアクティビティからの遷移、通知やウィジェットなどUI要素とのユーザー操作、Firebase Cloud Messagingの高優先度メッセージ受信、正確なアラームの発火、端末の再起動直後などが挙げられています*3。
位置情報など「while-in-use」権限は例外の中でもさらに制限される
位置情報・カメラ・マイクなど「while-in-use(使用中のみ)」権限を要するフォアグラウンドサービスは、上記の起動制限の例外に該当する状況であっても、アプリがバックグラウンドにある間は原則として作成できません*3。ただし、サービスがforegroundServiceType「location」を宣言しており、かつアプリがACCESS_BACKGROUND_LOCATION権限を保有している場合に限り、バックグラウンドで動作していても位置情報へ常時アクセスできる例外が用意されています*3。この権限は審査上の扱いが厳しく、常時の位置取得が本当に必要な機能であるかを事前に精査しておくことが重要です。
この起動制限の存在は、外注する側にとっても実務上の意味を持ちます。「アプリを閉じても位置情報を取り続けたい」という要件が、実装時にどのタイミング・どの導線から常駐処理を起動するかによって実現可否が変わるためです。企画段階でこの制約を理解していないと、要件定義後に「その起動方法では動かない」という手戻りが発生しかねません。
Android 14のforegroundServiceType宣言と型ごとの権限
Android 14(APIレベル34)からは、フォアグラウンドサービスごとに適切な型(foregroundServiceType)を宣言することが必須になりました*4。マニフェストに型を宣言していないサービスでstartForegroundを呼び出すと、システムはMissingForegroundServiceTypeExceptionをスローします*5。この変更により、サービスが「何のために」前面で動き続けているのかをOS側が型として把握し、型ごとに異なる権限チェックを適用できる構造になっています。
位置情報型(location)はwhile-in-use制限の対象
位置情報の継続取得を行うサービスには、マニフェストでandroid:foregroundServiceType="location"を宣言し、FOREGROUND_SERVICE_LOCATION権限を宣言する必要があります*4。この型はACCESS_COARSE_LOCATIONまたはACCESS_FINE_LOCATIONのランタイム権限を前提とし、while-in-use制限の対象となるため、ACCESS_BACKGROUND_LOCATION権限を付与されていない限り、アプリがバックグラウンドにある間に位置情報型のサービスを新規作成することはできません*4。
データ同期型(dataSync)は用途が異なりランタイム権限は不要
データのアップロード・ダウンロード、バックアップ・復元、インポート・エクスポートといったデータ転送処理にはdataSync型を宣言します*4。この型はランタイム権限を前提としませんが*4、Android 15以降をターゲットとするアプリでは、端末起動完了(BOOT_COMPLETED)のブロードキャストレシーバーからこの型のサービスを起動することが禁止されている点に注意が必要です*4。
宣言していない型を使うと例外がスローされる
特定の条件を満たす場合にのみ使用できるsystemExempted型のように、要件を満たさずに宣言するとForegroundServiceTypeNotAllowedExceptionがスローされる型も存在します*4。Android 14以上をターゲットとするアプリは、Google Play Consoleのアプリコンテンツページでもフォアグラウンドサービスの型を申告する必要があり*4、開発時の実装とストア申請の両方で型の整合性を保つ必要があります。
| 観点 | Android(Foreground Service) | iOS(Background Modes) |
|---|---|---|
| 宣言方法 | マニフェストにforegroundServiceTypeを宣言(Android 14以降必須) | Info.plistのUIBackgroundModesキーに用途を追加 |
| 通知・可視化 | 永続通知の表示が必須。ユーザーが消せない | 位置情報の常時利用時はBackground Location Indicatorが表示され得る |
| 起動制限 | Android 12以降、バックグラウンドからの起動が原則不可 | 用途ごとに宣言した処理以外はシステムが実行を許可しない |
| 位置情報の常時取得 | location型宣言+ACCESS_BACKGROUND_LOCATION権限が必要 | Always権限+allowsBackgroundLocationUpdatesの設定が必要 |
| 審査・申請 | Google Play Consoleでサービス型の申告が必要 | App Store審査で宣言した用途に実機能が伴うか確認される |
iOSのBackground Modes — 位置情報・音声などの用途限定
iOSでフォアグラウンド常駐処理に相当する継続実行を行う仕組みがBackground Modes(バックグラウンド実行モード)です。アプリがバックグラウンドで実行を継続するために必要な用途を、Info.plistのUIBackgroundModesキーに配列として宣言する方式で、用途ごとに宣言できるモードが決められています*6。代表的なモードには、音声・AirPlay・ピクチャインピクチャを継続するためのモードと、バックグラウンドでも位置情報の更新を継続するためのモードがあります*6。
位置情報の継続取得にはAlways権限と専用プロパティの設定が必要
位置情報をバックグラウンドで継続取得するには、Info.plistのUIBackgroundModesにlocationを追加したうえで*7、位置情報マネージャーのallowsBackgroundLocationUpdatesプロパティをtrueに設定する実装が必要です*8。バックグラウンドでの更新は「使用中のみ許可」と「常に許可」のどちらの権限でも動作しますが、アプリが実行されていない状態からシステムがアプリを起動して位置情報を渡すのは、常に許可の権限を持ち、かつ significant location change(大幅な位置変化)やvisits、リージョン監視といった特定のサービスを使っている場合に限られます*8。
常時利用時はインジケーター表示が対になる
常に許可の権限でバックグラウンド位置情報を利用する場合、ユーザーに利用中であることを知らせるためshowsBackgroundLocationIndicatorプロパティをtrueに設定できます*8。Androidの永続通知が「消せない常時表示」であるのに対し、iOSはOS側のインジケーターやAlways権限の許諾プロセスを通じてユーザーへの可視化を担保する設計思想の違いがあります。
用途を宣言したら実際にその機能が伴っている必要がある
Background Modesは「宣言すれば何でも動く」仕組みではなく、宣言した用途に対応する実際の機能をアプリが備えていることが前提です。位置情報の用途を宣言する場合はアプリに位置情報を継続的に必要とする機能が、音声の用途を宣言する場合はバックグラウンドで音声コンテンツを再生できる機能が求められます。宣言と実装が一致しない場合、審査段階で指摘される可能性がある点は発注時に確認しておくべき論点です。
バッテリー影響・審査・ユーザー体験の設計
フォアグラウンド常駐処理は、機能を実現する代わりにバッテリー消費とユーザー体験への配慮という代償を伴います。OS側もこの点を強く意識しており、不要な常駐に対しては制約や審査基準を年々強化してきた経緯があります。
Androidは「アプリを非アイドル扱いにするためだけ」の常駐を禁じる方針
Android公式のDoze・App Standbyに関する解説では、システムがアプリをアイドル状態と判定させない目的だけでフォアグラウンドサービスを起動しないよう明記されています*9。バックグラウンドタスクには複数のAPIが用意されており、常駐処理が本当に必要な用途かどうかを見極め、遅延実行で足りる処理まで前面サービス化しないという判断が、システムリソースを浪費しない「行儀の良いアプリ」であるための前提です*9。
iOSは宣言した用途と実装の一致を審査の起点に置く
iOSでは、Background Modesで宣言した用途に見合う機能を実際に備えているかが審査上の観点になります。不要な用途まで宣言してバックグラウンド実行時間を確保しようとする設計は、審査で問題になり得るため、位置情報や音声など、事業上必須の用途だけに絞り込んで宣言する姿勢が求められます。
ユーザー体験は「常駐している理由の説明」で決まる
Androidの永続通知もiOSのAlways権限ダイアログや位置情報インジケーターも、ユーザーから見れば「このアプリはなぜ動き続けているのか」を判断する材料です。通知文言や権限リクエストの説明文が曖昧だと、ユーザーが不安を感じてアプリの利用自体を避ける結果につながりかねません。常駐処理を企画する段階で、通知文言や権限説明文をどう設計するかまで含めて要件に落とし込む必要があります。
外注時に確認すべき実装範囲と引き継ぎの論点
フォアグラウンド常駐処理の実装をアプリ開発会社に外注する場合、OSごとの制約が絡み合う領域だけに、発注前の確認が不足すると後工程で機能不全や審査差し戻しにつながりやすくなります。
内製に必要なもの
フォアグラウンド常駐処理を内製で実装するには、Android・iOSそれぞれのOSバージョンごとの制約(Android 12の起動制限、Android 14の型宣言、iOSのBackground Modesと権限体系)を把握したうえで、通知文言や権限説明文といったユーザー体験の設計まで担える体制が必要です。OSのメジャーアップデートのたびに制約が変わる領域のため、実装後も継続的に仕様変更を追随する運用体制を社内に持てるかどうかが、内製化の可否を左右します。
発注先への確認
提案書に「バックグラウンドで位置情報を取得します」とだけ記載されている場合、Android側でどのforegroundServiceTypeを宣言し、ACCESS_BACKGROUND_LOCATION権限をどう申請・審査対応するのか、iOS側でAlways権限の説明文とshowsBackgroundLocationIndicatorの扱いをどう設計するのかを、具体的に質問して回答の解像度を確認する必要があります。あわせて、常駐処理ではなく遅延実行(WorkManager・BGTaskScheduler)で要件を満たせる可能性がないかを検討したかどうかも、設計の妥当性を見極める材料になります。
契約明記
常駐処理に関わるマニフェスト宣言・Info.plist設定・権限申請の履歴は、OSのアップデートで審査基準が変わった際に見直しが必要になる資料です。開発会社との契約終了後に引き継ぐ可能性がある場合は、宣言済みの型・用途の一覧、権限申請時に提出した説明文、通知文言の設計意図をドキュメントとして納品物に含めるよう契約段階で明記しておく必要があります。これらが欠けたまま引き継ぐと、後任担当者がOSアップデート対応のたびに実装意図を推測する状態に陥りかねません。
常駐処理は一度実装して終わりではなく、OSのメジャーアップデートごとに制約への適合を確認し続ける運用が前提です。発注時にはこの運用フェーズを含めた保守体制まで確認しておくことが、長期的な機能維持につながります。
まとめ:フォアグラウンド常駐処理を機能させる3つの判断軸
本稿では、位置情報の継続取得や音楽再生・通話・データ同期といった、画面に無い間も継続実行が必要な処理について、AndroidのForeground ServiceとiOSのBackground Modesという2つの仕組みを整理しました。要点を3つに集約すると次の通りです。第一に、常駐処理はアプリが前面にない間の遅延実行(WorkManager・BGTaskScheduler)とは別の要件であり、要件定義の段階でどちらが必要かを明確に切り分ける必要があります。第二に、Androidは永続通知とAndroid 14以降の型宣言、iOSはBackground Modesの用途限定とAlways権限という、OSごとに異なる可視化・権限の設計思想を理解したうえで実装方針を決める必要があります。第三に、常駐処理はバッテリー消費とユーザー体験への影響が大きいため、不要な常駐を避け、通知文言や権限説明文まで含めた設計を外注先と具体的にすり合わせる姿勢が、長期的な審査対応と機能維持を左右します。
よくある質問
フォアグラウンド常駐処理とバックグラウンドの遅延実行はどう違いますか。
フォアグラウンド常駐処理は、位置情報の継続取得や音楽再生のように、ユーザーに可視の形で処理を止めずに動かし続ける仕組みです。一方、WorkManagerやBGTaskSchedulerが担う遅延実行は、アプリが前面にない間にOSが都合の良いタイミングでまとめて実行する処理で、ユーザーへの常時の可視化は前提としません。要件が「今すぐ・止めずに」なのか「いずれ・まとめて」なのかで、採用する仕組みが変わります*1*6。
Android 14でforegroundServiceTypeの宣言が必須になったのはなぜですか。
サービスが前面で動き続ける目的を型として明示させることで、システム側が型ごとに異なる権限チェックや起動制約を適用できるようにするためです。マニフェストに適切な型を宣言していないサービスでstartForegroundを呼び出すと、MissingForegroundServiceTypeExceptionがスローされます。位置情報型であればFOREGROUND_SERVICE_LOCATION権限、データ同期型であればFOREGROUND_SERVICE_DATA_SYNC権限というように、型ごとに必要な宣言が異なります*4*5。
iOSでバックグラウンド中も位置情報を取得し続けるには何が必要ですか。
Info.plistのUIBackgroundModesキーにlocationを追加したうえで、位置情報マネージャーのallowsBackgroundLocationUpdatesプロパティをtrueに設定する実装が必要です。アプリが実行されていない状態からシステムが位置情報を渡してアプリを起動するのは、常に許可の権限を持ち、大幅な位置変化やリージョン監視などの特定サービスを使っている場合に限られます*7*8。
常駐処理を実装するとバッテリー消費はどの程度増えますか。
具体的な消費量は端末や実装内容によって異なるため一律には言えませんが、Android公式はシステムをアイドル扱いさせない目的だけでフォアグラウンドサービスを起動しないよう明記しており、常駐処理がバッテリーに与える影響をOS側が強く意識していることがうかがえます。常駐処理が本当に必要な用途かどうかを見極め、遅延実行で代替できる処理まで前面サービス化しない設計が重要です*9。
外注先を選ぶ際、常駐処理についてどこまで確認すべきですか。
Android側ではどのforegroundServiceTypeを宣言し、位置情報など常時アクセスが必要な権限をどう申請・審査対応するのか、iOS側ではBackground Modesの用途宣言とAlways権限の説明文をどう設計するのかを具体的に質問することが有効です。あわせて、常駐処理ではなく遅延実行で要件を満たせないかを検討したかどうかも、提案の妥当性を見極める材料になります*3*4*6。
著者:テレリモ総研編集部 鈴木 亮佑
ご不明な点はお問い合わせフォームからもご連絡いただけます。
- *1 出典:Android Developers「Foreground services」https://developer.android.com/develop/background-work/services/foreground-services
- *2 出典:Android Developers「Services overview」https://developer.android.com/develop/background-work/services
- *3 出典:Android Developers「Restrictions on starting a foreground service from the background」https://developer.android.com/develop/background-work/services/fgs/restrictions-bg-start
- *4 出典:Android Developers「Foreground service types are required」https://developer.android.com/develop/background-work/services/fgs/service-types
- *5 出典:Android Developers「Declare foreground service types」https://developer.android.com/develop/background-work/services/fgs/declare
- *6 出典:Apple Developer Documentation「Configuring background execution modes」https://developer.apple.com/documentation/xcode/configuring-background-execution-modes
- *7 出典:Apple Developer Documentation「UIBackgroundModes」https://developer.apple.com/documentation/bundleresources/information-property-list/uibackgroundmodes
- *8 出典:Apple Developer Documentation「allowsBackgroundLocationUpdates」https://developer.apple.com/documentation/corelocation/cllocationmanager/allowsbackgroundlocationupdates
- *9 出典:Android Developers「Optimize for Doze and App Standby」https://developer.android.com/training/monitoring-device-state/doze-standby