2025 年 3 月 27 日より、AOSP のビルドとコントリビューションには aosp-main
ではなく android-latest-release
を使用することをおすすめします。詳細については、AOSP の変更をご覧ください。
複数のアプリの再開
コレクションでコンテンツを整理
必要に応じて、コンテンツの保存と分類を行います。
Android 9 以下では、次の場合、アプリは PAUSED
状態になりました。
- アプリの上で新しい半透明のアクティビティが起動したが、アプリが引き続き表示されている(つまり停止されなかった)場合。
- アクティビティがフォーカスを失ったが表示が不鮮明にされず、ユーザーが操作できる場合。たとえば、マルチウィンドウ モードでは、同時に複数のアクティビティを表示してタッチ入力を受け取れます。
このような状況では、必要な一時停止の長さがアプリごとに異なりますが、アプリレベルでは違いを区別できません。
Android 10 では、表示されるスタック内の最上部のフォーカス可能なアクティビティは、すべて RESUMED
状態になります。これにより、onStop()
ではなく onPause()
を使用して UI の更新とユーザーとのやり取りを停止するアプリでは、マルチウィンドウ モードと MD モードの互換性が向上します。たとえば、次のようになります。
- 分割画面の両方のアクティビティが再開される。
- フリーフォーム ウィンドウ モードで最上部に表示されたすべてのアクティビティが再開される。
- 複数の画面のアクティビティを同時に再開することができる。

図 1. 折りたたみ式デバイスでの複数のアプリの再開

図 2. デスクトップ モードでの複数のアプリの再開
アクティビティは、次のようにフォーカス不可能になるか部分的に遮られるかすると、PAUSED
状態になる可能性があります。
- 最小化された分割画面(ランチャーが側面にある)で、フォーカス不可能なため最上部のアクティビティが再開されない。
- ピクチャー イン ピクチャー モードで、フォーカス不可能なためアクティビティが再開されない。
- アクティビティが同じスタック内の他の透明なアクティビティで覆われている。
このアプローチでは、RESUMED
状態でのみアクティビティに対するユーザー入力が有効なことをアプリに示します。Android 10 より前は、PAUSED
状態でもアクティビティに対する入力が可能でした(たとえば、Android 9 を搭載したデバイスで、分割画面の両方のアクティビティを同時に操作してみてください)。
以前の Android リリースの再開シグナルを保持し、アプリが排他的アクセスまたはシングルトン リソースへのアクセス権を取得する際に通信するために、Android 10 には新しいコールバックが含まれています。
Activity#onTopResumedActivityChanged(boolean onTop)
このコールバックは Activity#onResume()
と Activity#onPause()
の間に呼び出されます。このコールバックは任意であり、省略することもできるため、アクティビティはシステムの最上位に配置されることなく、RESUMED
から PAUSED
状態に移行する場合があります。たとえば、マルチウィンドウ モードがこれに該当します。このコールバックは省略可能なため、アクティビティのライフサイクルには含まれず、ほとんど使用されません。
最上位で再開されるアクティビティは、最上位で再開される次のアクティビティが onTopResumedActivity(true)
を受け取る前に onTopResumedActivity(false)
を受け取って実行を終了します。ただし、前のアクティビティがメソッド呼び出しの処理に時間がかかって、500 ミリ秒のタイムアウトに達した場合を除きます。
互換性
複数のアプリの再開を実装する際は、互換性を維持するために、次の解決策を検討してください。
1 つのアプリプロセスにおける複数のアクティビティの再開
- 問題: Android 9 以前では、一度に再開されるのはシステム内の 1 つのアクティビティのみです。アクティビティの切り替えでは、必ずアクティビティが一時停止されてから別のアクティビティが再開されます。一部のアプリとフレームワーク(Flutter、Android の LocalActivityManager など)は、この事実を利用して、再開されたアクティビティの状態をシングルトンに保存します。
- 解決策: Android 9 以前では、同じプロセスの 2 つのアクティビティが再開される場合、システムは Z オーダーが高いアクティビティのみを再開します。Android 10 をターゲットとするアプリでは、複数のアクティビティを同時に再開できます。
カメラへの同時アクセス
- 問題: 次の問題は、Android 9 以前でも発生しています。たとえば、全画面で再開されたアクティビティは、ピクチャー イン ピクチャー モードの最上部にある一時停止されたアクティビティにカメラのフォーカスを合わせられませんが、マルチウィンドウ モードとマルチディスプレイ モードを広く採用することで露出が増えます。
RESUME
状態に対して加えられた変更が原因で、再開してもアプリとカメラの接続が解除される可能性があります。この問題に対処するには、アプリがクラッシュせずにカメラの接続解除を処理する必要があります。接続が解除されると、アプリは切断コールバックを受け取り、API への呼び出しではすべて CameraAccessException
がスローされるようになります。
- カメラを使用する別のアプリを他のディスプレイで開くことができるため、
resizeableActivity=false
はカメラへの排他的アクセスを保証しません。
- 解決策: デベロッパーは、アプリとカメラの接続が解除されたときのロジックを組み込む必要があります。アプリがカメラから切断された場合は、CameraAvailable コールバックをモニタリングし、カメラへの再接続を試行して使用を続ける必要があります。Android 10 では、既存の
CameraManager#AvailabilityCallback#onCameraAvailable()
コールバックに加えて CameraManager#AvailabilityCallback#onCameraAccessPrioritiesChanged()
が追加され、再開された複数のアクティビティ間でフォーカス(およびカメラの優先度)を切り替えるケースに対応できるようになりました。アプリ デベロッパーは両方のコールバックを使用して、カメラにアクセスする最適なタイミングを判断する必要があります。
複数のアプリの再開
Android 10 では、アクティビティのライフサイクルの状態は可視性と Z オーダーによって決まります。アクティビティで可視性が更新された後の正しい状態を確認し、適用可能なライフサイクル状態を評価するには、さまざまな場所から ActivityRecord#makeActiveIfNeeded()
メソッドを呼び出します。Android 10 において「アクティブ」は RESUMED
または PAUSED
を示し、これらの 2 つのインスタンスでのみ動作します。
Android 10 では、アクティビティの再開はシステム内の 1 つの場所ではなく、各スタックで個別にトラッキングされます。これは、マルチウィンドウ モードで複数のアクティビティ遷移を同時に実行できるためです。詳細については、ActivityStack#mInResumeTopActivity
をご覧ください。
最上位で再開されたアクティビティのコールバック
最上位のアクティビティの変更(アクティビティの起動、再開、Z オーダーの変更など)につながる可能性があるアクションを行うと、ActivityStackSupervisor#updateTopResumedActivityIfNeeded()
が呼び出されます。このメソッドは、最上位で再開されたアクティビティが変更されたかどうかを確認し、必要に応じて更新します。先に最上位で再開されたアクティビティが最上位での再開状態を解除していない場合は、top-resumed-state-loss メッセージが送信され、サーバー側でタイムアウトがスケジュールされます(ActivityStackSupervisor#scheduleTopResumedStateLossTimeout()
)。前のアクティビティで状態が解除されるか、タイムアウトが発生すると、最上位での再開状態のレポートが次のアクティビティに送信されます(以下の使用例を参照)。
ActivityStackSupervisor#scheduleTopResumedActivityStateIfNeeded()
最上位での再開状態の変更をクライアントにレポートする新しい TopResumedActivityChangeItem
トランザクション項目が追加され、Android 9 の ActivityLifecycler
アーキテクチャが利用されます。
最上位での再開状態はクライアント側に保存され、アクティビティが RESUMED
または PAUSED
に遷移するたびに、onTopResumedActivityChanged()
コールバックを呼び出す必要があるかどうかが確認されます。これにより、サーバー側とクライアント側の間で行われるライフサイクル状態と最上位で再開された状態の通信で、特定の関連付け解除が可能になります。
このページのコンテンツやコードサンプルは、コンテンツ ライセンスに記載のライセンスに従います。Java および OpenJDK は Oracle および関連会社の商標または登録商標です。
最終更新日 2025-03-22 UTC。
[[["わかりやすい","easyToUnderstand","thumb-up"],["問題の解決に役立った","solvedMyProblem","thumb-up"],["その他","otherUp","thumb-up"]],[["必要な情報がない","missingTheInformationINeed","thumb-down"],["複雑すぎる / 手順が多すぎる","tooComplicatedTooManySteps","thumb-down"],["最新ではない","outOfDate","thumb-down"],["翻訳に関する問題","translationIssue","thumb-down"],["サンプル / コードに問題がある","samplesCodeIssue","thumb-down"],["その他","otherDown","thumb-down"]],["最終更新日 2025-03-22 UTC。"],[],[],null,["# Multi-resume\n\nIn Android 9 (and lower), apps were entered into the `PAUSED` state when:\n\n- A new, translucent activity launched on top of the app, while the app was still visible (and, therefore, wasn't stopped).\n- The activity lost focus, but was unobscured and could be interacted with by the user. For example, in multi-window mode, a number of activities can be visible and receive touch input simultaneously.\n\nThese situations differ in the amount of *pausing* an app must do but can't be\ndistinguished at the app level.\n\nIn Android 10, all top-focusable activities in visible stacks reside in\nthe `RESUMED` state. This improves compatibility with\n[Multi-Window](/docs/core/display/multi-window) and MD modes for apps that use\n`onPause()` instead of `onStop()` to stop refreshing the UI and interacting\nwith the user. This means:\n\n- Both activities in split-screen are resumed.\n- All top-visible activities in free-form windowing mode are resumed.\n- Activities on multiple screens can be resumed at the same time.\n\n**Figure 1.** Multi-resume on a foldable device\n\n**Figure 2.** Multi-resume in desktop mode\n\nActivities can reside in the `PAUSED` state when they cannot be focused upon or are\npartially occluded, such as:\n\n- In a minimized split-screen (with launcher on side), the top activity isn't resumed because it's not focusable.\n- In a picture-in-picture mode, the activity isn't resumed because it's not focusable.\n- When activities are covered by other transparent activities in the same stack.\n\nThis approach indicates to apps that an activity can receive input from a\nuser only in the `RESUMED` state. Before Android 10,\nactivities could also receive input in the `PAUSED` state (for example, try touching\nboth activities in split-screen simultaneously on a device running Android 9).\n\nTo preserve the *resumed* signal from previous Android releases (and\nto communicate when apps should obtain access to exclusive-access or singleton\nresources), Android 10 includes a new callback: \n\n```text\nActivity#onTopResumedActivityChanged(boolean onTop)\n```\n\nWhen invoked, this callback is called between `Activity#onResume()`\nand `Activity#onPause()`. This callback is optional and can be skipped,\nso an activity can go from a `RESUMED` to a `PAUSED` state\nwithout becoming the topmost in the system. For example, in multi-window mode.\nBecause this callback is optional, it's not part of the [Activity\nLifecycle](https://developer.android.com/guide/components/activities/activity-lifecycle) and should be rarely used.\n\nThe previous top-resumed activity receives and finishes execution of\n`onTopResumedActivity(false)` before the next top-resumed activity\nreceives `onTopResumedActivity(true)` unless the previous activity\ntakes too much time to handle the method call and hits the 500 ms timeout.\n\nCompatibility\n-------------\n\nTo maintain compatibility when implementing multi-resume, consider these\nsolutions.\n\n### Multiple resumed activities in one app process\n\n- Issue. In Android 9 and lower, only one activity in the system is resumed at a time. All transitions between activities involve pausing an activity before resuming another. Some apps and frameworks (such as Flutter, or Android's LocalActivityManager) use this fact, and store state about the resumed activity in singletons.\n- Solution. In Android 9 and lower, if two activities from the same process are both resumed, the system only resumes the activity that's higher in Z-order. Apps targeting Android 10 can support multiple activities being resumed at the same time.\n\n### Simultaneous camera access\n\n- **Issues** . These issues are also present in Android 9 and lower. For example, a fullscreen and resumed activity can lose camera focus to a paused activity on top in picture-in-picture mode but become more exposed with wider adoption of multi-window and multi-display modes.\n - Due to changes made to the `RESUME` state, apps may be disconnected from the camera *even while resumed* . To address this, apps must handle a camera disconnect without crashing. When disconnected, apps get a disconnected callback and all calls into the API start throwing `CameraAccessException`.\n - `resizeableActivity=false` isn't a guarantee of exclusive camera access, because other apps using the camera can be opened on other displays.\n- **Solutions.** Developers should include logic for when an app is disconnected from the camera. If an app is disconnected from the camera, it should watch camera availability callbacks to try to reconnect and continue camera use. In addition to the existing `CameraManager#AvailabilityCallback#onCameraAvailable()` callback, Android 10 added `CameraManager#AvailabilityCallback#onCameraAccessPrioritiesChanged()`, which covers the case when focus (and camera priority) switches between several resumed activities. App developers should use both of these callbacks to determine a good time to try to get access to the camera.\n\n### Multi-resume\n\nIn Android 10, the activity lifecycle state is determined by visibility and\nZ-order. To ensure that the correct state after visibility updates on an\nactivity and evaluate which lifecycle state is applicable, invoke the\n`ActivityRecord#makeActiveIfNeeded()` method from different\nlocations. In Android 10, active means either `RESUMED` or\n`PAUSED` and works only in these two instances.\n\nIn Android 10, resuming an activity is separately tracked in each stack\ninstead of in the single location in the system. This is because several\nactivity transitions can be performed simultaneously in multi-window modes. For\ndetails, see `ActivityStack#mInResumeTopActivity`.\n\n### Top-resumed activity callback\n\nAfter actions that can result in a top activity change (such as activity\nlaunch, resuming, or Z-order change),\n`ActivityStackSupervisor#updateTopResumedActivityIfNeeded()` is invoked. This\nmethod checks if the topmost resumed activity changed and performs the update if\nneeded. If the previous top-resumed activity hasn't release the top-resumed\nstate, then a top-resumed-state-loss message is sent to it and a timeout is\nscheduled on the server side\n(`ActivityStackSupervisor#scheduleTopResumedStateLossTimeout()`).\nA report of the top-resumed state is sent to the next activity after the previous\none released the state, or when a timeout was hit (see usages of: \n\n```text\nActivityStackSupervisor#scheduleTopResumedActivityStateIfNeeded()\n```\n\nA new `TopResumedActivityChangeItem` transaction item was added\nto report top-resumed state changes to clients and leverages the\n`ActivityLifecycler` architecture from Android 9.\n\nThe top-resumed state is stored on the client side, and each time the\nactivity transitions to `RESUMED` or `PAUSED` it also\nchecks whether the `onTopResumedActivityChanged()` callback should be\ninvoked. This enables certain decoupling in the communication of lifecycle states\nand the top-resumed state between the server and client sides."]]