マルチ ウィンドウ モードでは、複数のアプリで同じ画面を同時に使用できます。アプリを左右または上下に並べて表示したり(分割画面モード)、1 つのアプリを小さなウィンドウに表示して他のアプリに重ねたり(ピクチャー イン ピクチャー モード)、それぞれのアプリを位置もサイズも変更可能な個別のウィンドウに表示したり(デスクトップ ウィンドウ モード)できます。
スマートフォンで分割画面モードにアクセスする方法については、Google Pixel で 2 つのアプリを同時に表示するを参照してください。
バージョン固有のマルチウィンドウ機能
マルチウィンドウのユーザー エクスペリエンスは、Android のバージョンとデバイスの種類によって異なります。
Android 7.0(API レベル 24)では、小画面デバイスでの分割画面モードと、一部のデバイスでのピクチャー イン ピクチャー モードが導入されました。
分割画面モードでは、2 つのアプリが左右または上下に並べて表示されます。ユーザーは、2 つのアプリの間の分割線をドラッグすることで、一方を拡大(他方を縮小)できます。
ピクチャー イン ピクチャー モードでは、動画を再生しながら他のアプリを操作できます(ピクチャー イン ピクチャーのサポートをご覧ください)。
大画面デバイスのメーカーは、ユーザーが各アクティビティのサイズを自由に変更できるデスクトップ ウィンドウ化モードを有効にできます。
マルチ ウィンドウ モードをアプリがどう処理するかを設定するには、アクティビティの最小許容ディメンションを指定します。また、
resizeableActivity="false"
に設定してアプリが常に全画面表示されるようにすることで、そのアプリのマルチ ウィンドウ モードを無効にすることもできます。
Android 8.0(API レベル 26)では、小画面デバイスでもピクチャー イン ピクチャー モードを使用できます。
Android 12(API レベル 31)では、マルチウィンドウ モードが標準の動作です。
大画面(中程度または拡大のウィンドウ サイズクラス)では、アプリの設定にかかわらず、すべてのアプリでマルチウィンドウ モードがサポートされます。
resizeableActivity="false"
の場合、ディスプレイの寸法に合わせるために必要なとき、アプリは画面互換性モードになります。小画面(コンパクト ウィンドウ サイズ クラス)では、システムはアクティビティの
minWidth
とminHeight
をチェックし、アクティビティをマルチウィンドウ モードで実行できるかどうかを判断します。resizeableActivity="false"
の場合、幅と高さの最小値にかかわらず、アプリはマルチウィンドウ モードで実行されません。
分割画面モード
ユーザーは次の操作を行うことで、分割画面モードを有効にできます。
- 最近の画面を開きます。
- スワイプしてアプリをビューに表示します。
- アプリのタイトルバーにあるアプリアイコンをタップします。
- [分割画面] メニュー オプションを選択します。
- [最近の画面] から別のアプリを選択するか、[最近の画面] を閉じて別のアプリを実行します。
ユーザーは、ウィンドウ分割線を画面の上下左右いずれかの端までドラッグすることで、分割画面モードを終了できます。
隣接して起動する
アプリがインテント経由でコンテンツにアクセスする必要がある場合は、FLAG_ACTIVITY_LAUNCH_ADJACENT
を使用して、隣接する分割画面ウィンドウでコンテンツを開くことができます。
FLAG_ACTIVITY_LAUNCH_ADJACENT
は、分割画面モードで実行されているアプリが隣接するウィンドウでアクティビティを起動できるようにするために、Android 7.0(API レベル 24)で導入されました。
Android 12L(API レベル 32)以降では、全画面で実行されているアプリが分割画面モードを有効にして、隣接するウィンドウでアクティビティを起動できるように、フラグの定義が拡張されました。
隣接するアクティビティを起動するには、FLAG_ACTIVITY_LAUNCH_ADJACENT
と FLAG_ACTIVITY_NEW_TASK
を併用します。次に例を示します。
fun openUrlInAdjacentWindow(url: String) {
Intent(Intent.ACTION_VIEW).apply { data = Uri.parse(url)
addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT or Intent.FLAG_ACTIVITY_NEW_TASK)
}.also { intent -> startActivity(intent) }
}
マルチ ウィンドウ モードでのアクティビティのライフサイクル
マルチ ウィンドウ モードは、アクティビティのライフサイクルを変更しません。ただし、複数ウィンドウ内でのアプリの再開状態は、Android のバージョンによって異なります。
複数のアプリの再開
Android 10(API レベル 29)以降のバージョンでは、複数のアプリの再開がサポートされています。デバイスがマルチ ウィンドウ モードのときは、すべてのアクティビティが RESUMED
状態のままになります。アクティビティは、別の透明なアクティビティが上にある場合や、フォーカス可能でない場合(アクティビティがピクチャー イン ピクチャー モードの場合など)には、一時停止されることもあります。また、通知ドロワーが開いている場合などには、フォーカスされているアクティビティがないということもありえます。onStop()
メソッドは通常どおりに動作し、アクティビティが画面から外れるたびに呼び出されます。
複数のアプリの再開は、Android 9(API レベル 28)を搭載する一部のデバイスでも使用できます。Android 9 デバイスで複数のアプリの再開を有効にするには、次のマニフェスト メタデータを追加します。
<meta-data android:name="android.allow_multiple_resumed_activities" android:value="true" />
デバイスがこのマニフェスト メタデータをサポートしているかどうかを確認するには、デバイスの仕様をご覧ください。
Android 9
Android 9(API レベル 28)以前のマルチウィンドウ モードでは、ある時点でアクティブなのは、ユーザーが最後に操作したアクティビティのみです。このアクティビティはトップレベルと見なされ、RESUMED
状態の唯一のアクティビティとなります。表示されているその他すべてのアクティビティは STARTED
状態にあり、RESUMED
状態にはありません。ただし、このように再開状態にはないものの表示されているアクティビティには、表示されていないアクティビティよりも高い優先度が与えられます。表示されているアクティビティのいずれかをユーザーが操作すると、そのアクティビティが再開され、その前に最上位だったアクティビティが STARTED
状態になります。
1 つのアクティブ アプリ プロセス内に複数のアクティビティがある場合、Z オーダーが最も高いアクティビティが再開され、他のアクティビティは一時停止されます。
構成の変更
構成の変更を処理するで説明されているように、ユーザーがアプリをマルチウィンドウ モードに切り替えると、構成の変更がアクティビティに通知されます。構成の変更は、ユーザーがアプリのサイズを変更したときや、アプリを全画面モードに戻したときにも通知されます。
基本的に、こうした構成の変更は、デバイスが縦表示から横表示に切り替えられた場合(ただし、アプリのディメンションが単にスワップされるのでなく変更された場合を除く)にアプリに通知されるのと同じ影響をアクティビティ ライフサイクルに及ぼします。アクティビティでは、設定変更自体に対応することも、システムにアクティビティの破棄と新しいディメンションでの再作成を許可することもできます。
ユーザーがウィンドウのサイズを変更して、高さまたは幅を拡大した場合、システムはユーザー操作に合わせてアクティビティのサイズを変更し、必要に応じて構成の変更を実行します。新たにエクスポーズされる領域をアプリが描画するのに時間がかかる場合、その領域は、windowBackground
属性またはデフォルトの windowBackgroundFallback
スタイル属性で指定された色で一時的に塗りつぶされます。
リソースへの排他的アクセス
複数のアプリの再開機能をサポートするには、onTopResumedActivityChanged()
ライフサイクル コールバックを使用します。
コールバックは、アクティビティが最上位の再開状態を獲得または喪失したときに呼び出されます。これは、アクティビティがマイクやカメラなどの共有シングルトン リソースを使用する場合に重要です。
override fun onTopResumedActivityChanged(topResumed: Boolean) {
if (topResumed) {
// Top resumed activity.
// Can be a signal to re-acquire exclusive resources.
} else {
// No longer the top resumed activity.
}
}
アプリはその他の理由(共有ハードウェアの取り外しなど)でリソースを失うこともあります。
いずれにしても、アプリは使用可能なリソースに影響するイベントと状態変化にスムーズに対処する必要があります。
カメラを使用するアプリの場合、CameraManager.AvailabilityCallback#onCameraAccessPrioritiesChanged()
を使用することで、カメラにアクセスするタイミングの手がかりが得られます。このメソッドは、Android 10(API レベル 29)以降で使用できます。
resizeableActivity=false
はカメラへの排他的アクセスを保証するものではないことにご注意ください。カメラを使用する他のアプリが他のディスプレイで開かれている可能性もあります。

アプリがフォーカスを失ったときに、必ずしもカメラを解放する必要はありません。たとえば、新たにフォーカスを得た最上位の再開状態にあるアプリをユーザーが操作している間、カメラのプレビューを継続することもできます。最上位の再開状態にあるアプリでなくても、カメラの実行を続けることに問題はありませんが、切断のケースを適切に処理する必要があります。最上位の再開状態にあるアプリは必要なときにカメラを開くことができます。このとき、それまでカメラを実行していたアプリはアクセスを失います。アプリにフォーカスが戻ると、カメラを再度開くことができます。
アプリが CameraDevice.StateCallback#onDisconnected()
コールバックを受け取った後にカメラデバイスを要求すると、CameraAccessException
がスローされます。
マルチディスプレイ
Android 10(API レベル 29)は、セカンダリ ディスプレイ上のアクティビティをサポートしています。アクティビティが複数のディスプレイを持つデバイスで実行されている場合、ユーザーはディスプレイ間でアクティビティを移動できます。複数のアプリの再開はマルチスクリーンのシナリオにも適用されます。複数のアクティビティがユーザー入力を同時に受け取ることができます。
アプリは、起動時や別のアクティビティの作成時に、どのディスプレイで実行するかを指定できます。この動作は、マニフェスト ファイルで定義したアクティビティの起動モード、またはアクティビティを起動するエンティティが設定したインテント フラグやオプションによって異なります。詳細については、ActivityOptions
クラスをご覧ください。
アクティビティをセカンダリ ディスプレイに移動すると、コンテキストの更新、ウィンドウのサイズ変更、構成とリソースの変更が行われることがあります。アクティビティが構成の変更を処理する場合、アクティビティには onConfigurationChanged()
で通知されます。それ以外の場合、アクティビティは再起動されます。
構成の変更を処理する場合、アクティビティは onCreate()
と onConfigurationChanged()
で現在のディスプレイを確認する必要があります。ディスプレイが変更されたときは、リソースとレイアウトを必ず更新するようにします。
アクティビティに対して選択した起動モードで複数のインスタンスが許容されている場合、セカンダリ画面で起動すると、アクティビティの新しいインスタンスが作成されることがあります。両方のアクティビティが同時に再開されます。

Android 8.0 で導入されたマルチディスプレイ API についてもご確認ください。
アクティビティとアプリのコンテキスト
マルチディスプレイでは適切なコンテキストを使用することが非常に重要です。リソースにアクセスするときのアクティビティ コンテキスト(表示される)は、アプリ コンテキスト(表示されない)とは異なります。
アクティビティ コンテキストはディスプレイに関する情報を含んでおり、アクティビティの表示領域に合わせて常に調整されます。これにより、アプリのディスプレイ密度やウィンドウ指標に関する正しい情報を取得できます。現在のウィンドウまたはディスプレイに関する情報を取得するには、必ずアクティビティ コンテキスト(または別の UI ベースのコンテキスト)を使用する必要があります。アクティビティ コンテキストは、その情報を使用するシステム API にも影響を及ぼします(例については、トーストの概要をご覧ください)。
リソースとコンテキストは、アクティビティのウィンドウ構成と親ディスプレイによって定義されます。現在のディスプレイは次のように取得します。
val activityDisplay = activity.getDisplay()
現在のアクティビティのウィンドウ指標は次のように取得します。
val windowMetrics = activity.getWindowManager().getCurrentWindowMetrics()
現在のシステム構成の最大ウィンドウ指標は次のように取得します。
val maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics()
最大ウィンドウ指標は、計算、レイアウトの選択、事前に取得するリソースのサイズの決定に役立ちます。これを onCreate()
で利用できるようにすると、最初のレイアウトパスの前にこれらの決定を行うことができます。この指標は、特定のビュー要素のレイアウトには使用しないでください。代わりに、Configuration
オブジェクトからの情報を使用してください。
ディスプレイ カットアウト
折りたたみ式デバイスでは、折りたたんだときや広げたときにカットアウト ジオメトリが変更されることがあります。カットアウトに関する問題を回避するには、ディスプレイ カットアウトをサポートするをご覧ください。
セカンダリ ディスプレイ
使用可能なディスプレイは、DisplayManager
システム サービスから次のようにして取得できます。
val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
val displays = displayManager.getDisplays()
Display
クラスを使用して、ディスプレイのサイズやディスプレイが安全かどうかを示すフラグなど、特定のディスプレイに関する情報を取得します。ただし、ディスプレイのサイズがアプリに割り当てられる表示領域と同じサイズになるとは限りません。マルチウィンドウ モードでは、アプリはディスプレイの一部に配置されることを忘れないでください。
アクティビティをディスプレイ上で起動できるかどうかは、次のようにして判断します。
val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val activityAllowed = activityManager.isActivityStartAllowedOnDisplay(context, displayId, intent)
その後、次のようにしてディスプレイ上でアクティビティを起動します。
val options = ActivityOptions.makeBasic()
options.setLaunchDisplayId(targetDisplay.displayId)
startActivity(intent, options.toBundle())
マルチディスプレイのサポート
Android は、ソフトウェア キーボード、壁紙、ランチャーをマルチディスプレイでサポートしています。
ソフトウェア キーボード
ディスプレイがシステム デコレーションをサポートするように設定されている場合は、キーボードをセカンダリ画面上に表示できます。そのディスプレイでテキスト フィールドへの入力をリクエストすると、インプット メソッド エディタが自動的に表示されます。

壁紙
Android 10(API レベル 29)では、セカンダリ画面に壁紙を設定できます。ディスプレイごとに WallpaperService.Engine
の個別のインスタンスが作成されます。各エンジンのサーフェスが別々に描画されていることをご確認ください。デベロッパーは、WallpaperService.Engine#getDisplayContext()
のディスプレイ コンテキストを使用してアセットを読み込むことができます。また、WallpaperInfo.xml
ファイルで android:supportsMultipleDisplays="true"
が設定されることをご確認ください。

ランチャー
新しいインテント フィルタ カテゴリ SECONDARY_HOME
は、セカンダリ画面専用のアクティビティを提供します。このアクティビティのインスタンスは、システム デコレーションをサポートするすべてのディスプレイで使用されます(ディスプレイごとに 1 つ)。
<activity>
...
<intent-filter>
<category android:name="android.intent.category.SECONDARY_HOME" />
...
</intent-filter>
</activity>
アクティビティには、複数のインスタンスの作成を妨げず、さまざまな画面サイズに適応可能な起動モードを設定する必要があります。起動モードを singleInstance
または singleTask
に設定することはできません。
たとえば、Launcher3
の AOSP 実装は SECONDARY_HOME
アクティビティをサポートしています。


ウィンドウ指標
Android 11(API レベル 30)には、マルチウィンドウ モードで実行されるアプリの境界を提供するために、次の WindowManager
メソッドが導入されました。
getCurrentWindowMetrics()
: システムの現在のウィンドウ表示状態を表すWindowMetrics
オブジェクトを返します。getMaximumWindowMetrics()
: システムで可能な最大のウィンドウ表示状態を表すWindowMetrics
を返します。
Jetpack WindowManager ライブラリ メソッドの computeCurrentWindowMetrics()
と computeMaximumWindowMetrics()
はそれぞれ同様の機能を持ちますが、API レベル 14 との下位互換性があります。
現在のディスプレイ以外のディスプレイ指標を取得するには、次の手順を行います(コード スニペットに示すように)。
- ディスプレイ コンテキストを作成する
- ディスプレイのウィンドウ コンテキストを作成する
- ウィンドウ コンテキストの
WindowManager
を取得する - アプリで使用できる最大ディスプレイ領域の
WindowMetrics
を取得する
val windowMetrics = context.createDisplayContext(display)
.createWindowContext(WindowManager.LayoutParams.TYPE_APPLICATION, null)
.getSystemService(WindowManager::class.java)
.maximumWindowMetrics
サポート終了のメソッド
Display
メソッドの getSize()
と getMetrics()
は、API レベル 30 でサポートが終了し、新しい WindowManager
メソッドに置き換えられました。
Display
メソッドの getRealSize()
と getRealMetrics()
は、Android 12(API レベル 31)でサポートが終了し、その動作が getMaximumWindowMetrics()
とより厳密に一致するよう更新されています。
マルチウィンドウ モードの設定
アプリが Android 7.0(API レベル 24)以降をターゲットにしている場合は、アプリのアクティビティがマルチ ウィンドウ モードをサポートするかどうかと、どのようにサポートするかを設定できます。サイズとレイアウトの両方を制御する属性をマニフェストに設定できます。ルート アクティビティの属性の設定は、タスクスタック内のすべてのアクティビティに適用されます。たとえば、ルート アクティビティに android:resizeableActivity="true"
が設定されていると、タスクスタック内のすべてのアクティビティはサイズ変更可能になります。Chromebook などの一部の大型デバイスでは、android:resizeableActivity="false"
を指定しても、アプリがサイズ変更可能なウィンドウで実行される場合があります。これによりアプリの動作が阻害される場合は、Google Play のフィルタを使用して、そのようなデバイスでのアプリの利用を制限できます。
Android 12(API レベル 31)では、マルチウィンドウ モードがデフォルトです。大画面(中程度または拡大のウィンドウ サイズクラス)では、アプリの設定にかかわらず、すべてのアプリがマルチウィンドウ モードで実行されます。画面が小さい場合は、システムがアクティビティの minWidth
、minHeight
、resizeableActivity
の設定を確認して、そのアクティビティをマルチウィンドウ モードで実行できるかどうかを判断します。
resizeableActivity
API レベル 30 以下でマルチ ウィンドウ モードを有効または無効にするには、マニフェストの <activity>
要素または <application>
要素でこの属性を次のように設定します。
<application
android:name=".MyActivity"
android:resizeableActivity=["true" | "false"] />;
この属性を true
に設定すると、アクティビティは分割画面モードとデスクトップ ウィンドウ モードで起動できます。この属性を false
に設定した場合、アクティビティはマルチウィンドウ モードをサポートしません。この値が false の場合、ユーザーがマルチウィンドウ モードでアクティビティを起動しようとすると、アクティビティは全画面モードで表示されます。
API レベル 24 以降をターゲットとしているアプリで、この属性に値を指定しなかった場合、属性の値はデフォルトで true になります。
API レベル 31 以降をターゲットとしているアプリの場合、この属性による動作は小画面と大画面で異なります。
- 大画面(中程度または拡大のウィンドウ サイズクラス): すべてのアプリでマルチウィンドウ モードがサポートされます。この属性は、アクティビティのサイズが変更可能かどうかを示します。
resizeableActivity="false"
の場合、ディスプレイの寸法に合わせるために必要なとき、アプリは画面互換性モードになります。 - 小画面(コンパクト ウィンドウ サイズクラス):
resizeableActivity="true"
で、アクティビティの幅と高さの最小値がマルチウィンドウの要件内にある場合、アクティビティはマルチウィンドウ モードをサポートします。resizeableActivity="false"
の場合、アクティビティは幅と高さの最小値にかかわらず、マルチウィンドウ モードをサポートしません。
supportsPictureInPicture
マニフェストの <activity>
ノードでこの属性を設定すると、アクティビティがピクチャー イン ピクチャー モードをサポートするかどうかを指定できます。
<activity
android:name=".MyActivity"
android:supportsPictureInPicture=["true" | "false"] />
configChanges
マルチウィンドウの構成の変更(ユーザーがウィンドウ サイズを変更した場合など)を自分で処理するには、android:configChanges
属性をアプリ マニフェストの <activity>
ノードに追加して少なくとも次の値を設定します。
<activity
android:name=".MyActivity"
android:configChanges="screenSize | smallestScreenSize
| screenLayout | orientation" />
android:configChanges
を追加すると、アクティビティとフラグメントは破棄されて再作成される代わりに、onConfigurationChanged()
へのコールバックを受け取ります。その後、手動でビューを更新したり、リソースを再読み込みしたり、必要に応じて他のオペレーションを実行したりできます。
<layout>
Android 7.0(API レベル 24)以降では、<layout>
マニフェスト要素が、マルチウィンドウ モードでのアクティビティの動作に影響するいくつかの属性をサポートするようになりました。
android:defaultHeight
、android:defaultWidth
: デスクトップ ウィンドウ モードで起動されたときのアクティビティのデフォルトの高さと幅。android:gravity
: デスクトップ ウィンドウ モードで起動されたときのアクティビティの初期配置。適切な値については、Gravity
クラスをご覧ください。android:minHeight
、android:minWidth
: 分割画面モードとデスクトップ ウィンドウ モードの両方におけるアクティビティの高さと幅の最小値。ユーザーが分割画面モードの分割線を動かして、アクティビティを指定された最小サイズより小さくすると、アクティビティはユーザーが要求するサイズに合わせて切り取られます。
次のコードは、アクティビティがデスクトップ ウィンドウ モードで表示されるときに、アクティビティのデフォルトのサイズと位置、および最小サイズを指定する方法を示しています。
<activity android:name=".MyActivity">
<layout android:defaultHeight="500dp"
android:defaultWidth="600dp"
android:gravity="top|end|..."
android:minHeight="450dp"
android:minWidth="300dp" />
</activity>
ランタイムのマルチウィンドウ モード
Android 7.0 以降では、マルチウィンドウ モードで実行できるアプリをサポートする機能がシステムによって提供されるようになりました。
マルチウィンドウ モードで無効になる機能
マルチウィンドウ モードでは、Android は、他のアクティビティまたはアプリとデバイスの画面を共有しているアクティビティに適用されない機能を無効にするか、無視することがあります。
また、システム UI の一部のカスタマイズ オプションは無効になります。たとえば、アプリがマルチウィンドウ モードで実行されている場合、ステータスバーを非表示にすることはできません(システム UI の表示設定を制御するをご覧ください)。
android:screenOrientation
属性に対する変更は無視されます。
マルチウィンドウ モードのクエリとコールバック
Activity
クラスには、マルチ ウィンドウ モードをサポートする次のメソッドが用意されています。
isInMultiWindowMode()
: アクティビティがマルチウィンドウ モードかどうかを示します。isInPictureInPictureMode()
: アクティビティがピクチャー イン ピクチャー モードかどうかを示します。onMultiWindowModeChanged()
: アクティビティがマルチウィンドウ モードに入るかマルチウィンドウ モードから抜けると、システムは常にこのメソッドを呼び出します。アクティビティがマルチウィンドウ モードに入ったときはこのメソッドに true 値が渡され、アクティビティがマルチウィンドウ モードから抜けたときはこのメソッドに false 値が渡されます。onPictureInPictureModeChanged()
: アクティビティがピクチャー イン ピクチャー モードに入るかピクチャー イン ピクチャー モードから抜けると、システムは常にこのメソッドを呼び出します。アクティビティがピクチャー イン ピクチャー モードに入ったときはこのメソッドに true 値が渡され、アクティビティがピクチャー イン ピクチャー モードから抜けたときはこのメソッドに false 値が渡されます。
上記のメソッドの多くには、Fragment
クラスのバージョン(たとえば Fragment.onMultiWindowModeChanged()
)も用意されています。
ピクチャー イン ピクチャー モード
アクティビティをピクチャー イン ピクチャー モードに切り替えるには、enterPictureInPictureMode()
を呼び出します。デバイスがピクチャー イン ピクチャー モードをサポートしていない場合、このメソッドは何の効果も生じさせません。詳しくは、ピクチャー イン ピクチャー(PIP)を使って動画を追加するをご覧ください。
マルチウィンドウ モードの新しいアクティビティ
新しいアクティビティを起動するとき、新しいアクティビティを現在のアクティビティの隣に(表示できる場合は)表示する必要があるかどうかを指定できます。インテント フラグ FLAG_ACTIVITY_LAUNCH_ADJACENT
を使用して、隣接するウィンドウに新しいアクティビティを作成するようシステムに指示し、2 つのアクティビティが画面を共有するようにします。システムはそうするように努めますが、実現できるとは限りません。
デバイスがデスクトップ ウィンドウ モードになっているときに新しいアクティビティを起動する場合は、ActivityOptions.setLaunchBounds()
を呼び出すことにより、新しいアクティビティのディメンションと画面上の位置を指定できます。デバイスがマルチウィンドウ モードになっていない場合、このメソッドは何の効果も生じさせません。
API レベル 30 以前では、タスクスタック内でアクティビティを起動すると、画面上のアクティビティが起動したアクティビティに置き換えられ、すべてのマルチウィンドウ プロパティが継承されます。マルチウィンドウ モードで新しいアクティビティを別のウィンドウとして起動する場合は、そのアクティビティを新しいタスクスタックで起動する必要があります。
Android 12(API レベル 31)では、アプリはタスク ウィンドウを複数のアクティビティに分配できます。アプリによるアクティビティの表示方法(全画面表示、横に並べて表示、縦に並べて表示)を決定するには、XML 構成ファイルを作成するか、Jetpack WindowManager API 呼び出しを行います。
ドラッグ&ドロップ
2 つのアクティビティが画面を共有しているとき、ユーザーは一方のアクティビティからもう一方のアクティビティにデータをドラッグ&ドロップできます(Android 7.0 より前のバージョンでは、同じアクティビティ内でしかデータをドラッグ&ドロップできませんでした)。ドロップされたコンテンツの受け入れに対するサポートを迅速に追加するには、DropHelper
API をご覧ください。ドラッグ&ドロップの包括的なガイダンスについては、ドラッグ&ドロップを有効にするをご覧ください。
マルチインスタンス
各ルート アクティビティは独自のタスクを持ち、独自のウィンドウに表示されます。アプリの新しいインスタンスを別のウィンドウで起動するには、FLAG_ACTIVITY_NEW_TASK
フラグを指定して新しいアクティビティを開始します。この設定とマルチウィンドウ属性を組み合わせて、新しいウィンドウの場所を指定できます。たとえば、ショッピング アプリであれば、商品比較のために複数のウィンドウを表示できます。
Android 12(API レベル 31)以降では、アクティビティの埋め込みで、1 つのアクティビティの 2 つのインスタンスを同じタスク ウィンドウ内に並べて起動できます。
ユーザーがアプリ ランチャーまたはタスクバーからアプリの別のインスタンスを起動できるようにするには、ランチャー アクティビティのマニフェストで android:resizeableActivity="true"
を設定し、複数のインスタンスを防止する起動モードを使用しないでください。たとえば、FLAG_ACTIVITY_MULTIPLE_TASK
または FLAG_ACTIVITY_NEW_DOCUMENT
が設定されている場合、singleInstancePerTask
アクティビティは異なるタスクで複数回インスタンス化できます。
Android 15(API レベル 35)以降では、PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI
を使用してマルチインスタンスのサポートを宣言できます。このプロパティは、システム UI がユーザーにコントロールを公開してアプリの複数のインスタンスを作成するための明示的なシグナルです。このプロパティは起動モードとは独立していますが、アクティビティまたはアプリの起動モードがプロパティと互換性がある場合にのみ使用する必要があります(起動モードが singleInstance
でない場合など)。
折りたたみ式デバイスでアプリの複数のインスタンスが個別のウィンドウで実行されている場合、デバイスの形状が変更されると、1 つ以上のインスタンスがバックグラウンドに移動する可能性があります。たとえば、デバイスが折りたたまれていない状態で、2 つのアプリ インスタンスが折り目の両側にある別々のウィンドウで実行されているとします。デバイスが折りたたまれると、小さくなった画面に合うよう両方のインスタンスが調整される代わりに、片方のインスタンスが終了する可能性があります。
マルチウィンドウ モードの確認
アプリが API レベル 24 以降をターゲットにしているかどうかにかかわらず、ユーザーが Android 7.0 以降を搭載したデバイスをマルチウィンドウ モードにしてアプリを起動しようとする場合に備えて、アプリがマルチウィンドウ モードでどのように動作するかを確認する必要があります。
デバイスをテストする
Android 7.0(API レベル 24)以降を搭載したデバイスは、マルチ ウィンドウ モードをサポートしています。
API レベル 23 以下
アプリが固定された画面の向きを宣言していない限り、ユーザーがマルチ ウィンドウ モードでアプリを使用しようとすると、システムはアプリのサイズを強制的に変更します。
アプリが固定された画面の向きを宣言していない場合は、Android 7.0 以降を搭載したデバイスでアプリを起動し、アプリを分割画面モードにしてみる必要があります。アプリのサイズが強制的に変更されたら、ユーザー エクスペリエンスが許容範囲内かどうかを確認します。
アプリが固定された画面の向きを宣言している場合は、アプリをマルチウィンドウ モードにしてみる必要があります。マルチ ウィンドウ モードにしても、全画面モードのままであることを確認します。
API レベル 24~30
アプリが API レベル 24 ~ 30 をターゲットにしており、マルチウィンドウのサポートを無効にしていない場合は、分割画面モードとデスクトップ ウィンドウ モードの両方で次の動作を確認します。
アプリを全画面表示で起動した後、最近ボタンを長押ししてマルチウィンドウ モードに切り替えます。アプリのモードが適切に切り替わることを確認します。
マルチウィンドウ モードで直接アプリを起動し、アプリが適切に起動されることを確認します。最近ボタンを押した後、アプリのタイトルバーを長押しして、画面上のハイライト表示された領域のいずれかにアプリをドラッグすると、マルチウィンドウ モードでアプリを起動できます。
分割画面モードで分割線をドラッグして、アプリのサイズを変更します。アプリがクラッシュせず、アプリのサイズが変更され、必要な UI 要素が表示されることを確認します。
アプリの最小ディメンションを指定している場合は、アプリのサイズを変更して、ウィンドウ サイズがそれらのディメンションより小さくなるようにします。指定した最小ディメンションより小さいサイズに変更できないことを確認します。
すべてのテストを通して、アプリのパフォーマンスが許容範囲内かどうかを確認します。たとえば、アプリのサイズを変更したとき、UI の更新に時間がかかりすぎないかを確認します。
API レベル 31 以降
アプリが API レベル 31 以降をターゲットにしており、メイン アクティビティの最小幅と最小高がそれぞれ使用可能な表示領域の幅と高さ以下の場合は、API レベル 24 ~ 30 の場合で挙げた動作をすべて確認してください。
テスト チェックリスト
マルチウィンドウ モードでアプリのパフォーマンスを確認するには、以下の操作を試します。特に記載のない限り、分割画面モードとデスクトップ ウィンドウ モードの両方で試す必要があります。
マルチウィンドウ モードに入り、マルチウィンドウ モードから抜けます。
一方のアプリからもう一方のアプリに切り替え、最初のアプリが適切に動作する(表示されたままだが、アクティブでなくなる)ことを確認します。たとえば、アプリが動画を再生している場合、ユーザーが別のアプリを操作しているときも動画を再生し続けることを確認します。
分割画面モードで分割線を動かして、アプリの拡大と縮小を試します。アプリを左右に並べて表示しているときと上下に並べて表示しているときの両方で、これらの操作をテストします。アプリがクラッシュせず、基本的な機能が表示され、サイズ変更が速やかに行われることを確認します。
いくつかのサイズ変更操作を続けてすばやく行います。アプリがクラッシュせず、メモリリークが発生しないことを確認します。アプリのメモリ使用状況に関する情報は、Android Studio の Memory Profiler で入手できます(Memory Profiler を使用してアプリのメモリ使用量を調べるをご覧ください)。
さまざまなウィンドウ構成でアプリを通常どおりに使用し、アプリが適切に動作することを確認します。テキストが判読可能で、UI 要素が操作できないほど小さくならないことを確認します。
マルチウィンドウのサポートを無効にする場合
API レベル 24 ~ 30 で android:resizeableActivity="false"
を設定してマルチウィンドウ サポートを無効にした場合は、Android 7.0 ~ 11 を搭載したデバイスでアプリを起動し、アプリを分割画面モードとデスクトップ ウィンドウ モードにしてみる必要があります。マルチ ウィンドウ モードにしても、全画面モードのままであることを確認します。
参考情報
Android におけるマルチウィンドウ サポートの詳細については、以下をご覧ください。
- Android MultiWindowPlayground サンプル