マルチウィンドウのサポート

Android 7.0 では、複数のアプリを同時に表示するためのサポートが追加されました。ハンドヘルド デバイスでは、分割画面モードで 2 つのアプリを左右または上下に並べて表示できます。TV デバイスでは、アプリがピクチャー イン ピクチャー モードで動画を再生している間、ユーザーは別のアプリを操作できます。

Android 7.0(API レベル 24)以降をターゲットにしているアプリでは、アプリがマルチウィンドウ ディスプレイを処理する方法を構成できます。たとえば、アクティビティの最小許容ディメンションを指定できます。また、アプリに対してマルチウィンドウ ディスプレイを無効にし、アプリを全画面モードのみで表示するようシステムに指示することもできます。

概要

Android では、複数のアプリが画面を同時に共有できます。たとえば、ユーザーは画面を分割して、ウェブページを左側の画面に表示したまま、右側の画面でメールを作成できます。ユーザー エクスペリエンスは、Android OS のバージョンとデバイスの種類によって異なります。

  • Android 7.0 を搭載したハンドヘルド デバイスは、分割画面モードに対応しています。このモードでは、2 つのアプリを左右または上下に並べて画面に表示できます。ユーザーは、2 つのアプリ画面の分割線をドラッグして、一方のアプリを拡大し、もう一方のアプリを縮小できます。
  • Android 8.0 以降では、アプリをピクチャー イン ピクチャー モードにすると、そのアプリにコンテンツを表示したまま、他のアプリをブラウジングまたは操作できます。
  • 大型画面デバイスのメーカーは、ユーザーが各アクティビティのサイズを自由に変更できるフリーフォーム モードを有効にすることもできます。メーカーがこの機能を有効にした場合、デバイスでは、分割画面モードに加えて、フリーフォーム モードを利用できます。

図 1. 分割画面モードで左右に並べて実行されている 2 つのアプリ

ユーザーは、次の方法でマルチウィンドウ モードに切り替えることができます。

  • オーバービュー画面を開き、アクティビティ タイトルを長押しすると、そのアクティビティを画面のハイライト表示された領域にドラッグして、アクティビティをマルチウィンドウ モードに切り替えることができます。
  • オーバービュー ボタンを長押しすると、現在のアクティビティがマルチウィンドウ モードになり、オーバービュー画面が開いて、画面を共有する別のアクティビティの選択が可能になります。

複数のアクティビティが画面を共有しているとき、ユーザーは一方のアクティビティからもう一方のアクティビティにデータをドラッグ&ドロップできます。

マルチウィンドウのライフサイクル

マルチウィンドウ モードは、アクティビティのライフサイクルを変更しません。

マルチウィンドウ モードでは、ユーザーが直前に操作したアクティビティのみがその時点でアクティブになります。このアクティビティはトップレベルにあると見なされます。RESUMED 状態にあるのは、このアクティビティだけです。 表示されているその他すべてのアクティビティは STARTED 状態にあり、RESUMED 状態にはありません。 しかし、表示されているが再開されていないこれらのアクティビティには、表示されていないアクティビティよりも高い優先度が与えられます。表示されているアクティビティのいずれかをユーザーが操作すると、そのアクティビティが再開され、その前にトップレベルだったアクティビティが STARTED 状態になります。

注: マルチウィンドウ モードでは、アプリはユーザーに表示されていても RESUMED 状態でないことがあります。場合によっては、アプリはトップレベルでないときもオペレーションを続行する必要があります。たとえば、この状態の動画再生アプリは、動画を表示し続けなければなりません。そのため、動画を再生するアクティビティが ON_PAUSE ライフサイクル イベントに応じて動画を一時停止しないようにすることをおすすめします。代わりに、アクティビティが ON_START に応じて再生を開始し、ON_STOP に応じて再生を一時停止するようにします。Lifecycle パッケージを使用せずに直接ライフサイクル イベントを処理する場合は、onStop() ハンドラで動画の再生を一時停止し、onStart() で再生を再開します。

構成の変更を処理するで説明されているように、ユーザーがアプリをマルチウィンドウ モードに切り替えると、構成の変更がアクティビティに通知されます。構成の変更は、ユーザーがアプリのサイズを変更したときや、アプリを全画面モードに戻したときにも通知されます。 基本的に、こうした構成の変更は、デバイスが縦表示から横表示に切り替えられた場合(ただし、デバイスのディメンションが単にスワップされるのでなく変更された場合を除く)にアプリに通知されるのと同じ影響をアクティビティ ライフサイクルに及ぼします。構成の変更を処理するで説明されているように、アクティビティは自身で構成の変更を処理できます。また、アクティビティを破棄して新しいディメンションでアクティビティを再作成するようにシステムに指示することもできます。

ユーザーがウィンドウのサイズを変更して、高さまたは幅を拡大した場合、システムはユーザー操作に合わせてアクティビティのサイズを変更し、必要に応じて構成の変更を実行します。新たにエクスポーズされる領域をアプリが描画するのに時間がかかる場合、その領域は、windowBackground 属性またはデフォルトの windowBackgroundFallback スタイル属性で指定された色で一時的に塗りつぶされます。

アプリがマルチウィンドウ モードで実行されている場合、再開状態はデバイスの Android バージョンによって異なります。

  • Android 9(API レベル 28)以前の場合、フォーカスされているアクティビティのみが RESUMED 状態になり、他はすべて PAUSED になります。単一のアプリプロセス内に複数のアクティビティがある場合、Z オーダーが最も高いアクティビティが RESUMED になり、他は PAUSED になります。
  • Android 10(API レベル 29)以降の場合、表示されている最上部のフォーカス可能なアクティビティはすべて RESUMED になります。

詳しくは、複数のアプリの再開のドキュメントをご覧ください。

マルチウィンドウ

複数のウィンドウを実行できることは、大画面のメリットの 1 つです。過去には、2 つのアプリを並べて表示するデバイスもありました。現在の進歩したテクノロジーでは、画面上で同時に実行する 3 つ以上のアプリでコンテンツを共有することも可能になっています。

アプリでマルチウィンドウを適切にサポートしていない場合は resizeableActivity=false を設定します。詳しくは、マルチウィンドウ ガイドをご覧ください。

マルチウィンドウは一般的になりつつあるため、アプリでドラッグ&ドロップをサポートすることを検討してください。

複数のアプリの再開

Android 9.0 以前では、フォーカスされているアプリのみが再開状態になります。表示されている他のアクティビティはすべて一時停止されます。そのため、アクティビティが一時停止されたときに、アプリがリソースを閉じたり、コンテンツの再生を停止したりすると問題が発生することがあります。

Android 10 ではこの動作が変更されました。デバイスがマルチウィンドウ モードのとき、すべてのアクティビティが再開状態にとどまります。これを「複数のアプリの再開」といいます。上位で透明なアクティビティが行われている場合や、アクティビティをフォーカスできない場合(ピクチャー イン ピクチャー モードの場合など)は、アクティビティが一時停止されることがあります。また、ある時点(通知ドロワーが開いている場合など)でどのアクティビティもフォーカスされていないこともありえます。OnStop は通常どおり動作します。アクティビティが画面から外れると、いつでも呼び出されます。

複数のアプリの再開は、Android 9.0 が搭載されている一部のデバイスでも使用できます。これらのデバイスで複数のアプリの再開を有効にするには、以下のマニフェスト メタデータを追加します。

<meta-data
    android:name="android.allow_multiple_resumed_activities" android:value="true" />

デバイスがこのマニフェスト メタデータをサポートしているかどうかを確認するには、デバイスの仕様をご覧ください。

リソースへの排他的アクセス

複数のアプリの再開機能をサポートするために、新しいライフサイクル コールバック Activity#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 がスローされます。

マルチディスプレイ

今後、複数の画面またはディスプレイを同時にサポートする折りたたみ式スマートフォンが登場するかもしれません。このような構成への対処は、Chrome OS における現在の投影画面の操作方法に似ています。

Android 10(API レベル 29)以降では、セカンダリ ディスプレイのアクティビティがサポートされています。アクティビティが複数のディスプレイを持つデバイスで実行されている場合、ユーザーはディスプレイ間でアクティビティを移動できます。複数のアプリの再開はマルチスクリーンのシナリオにも適用されます。複数のアクティビティがユーザー入力を同時に受け取ることができます。

アプリは、起動時や別のアクティビティの作成時に、どのディスプレイで動作するかを指定できます。この動作は、マニフェスト ファイルで定義したアクティビティの起動モード、またはアクティビティを起動するエンティティが設定したインテント フラグやオプションによって異なります。詳細については ActivityOptions をご覧ください。

折りたたみによる画面遷移と同様に、アクティビティがセカンダリ ディスプレイに移動すると、コンテキストの更新、ウィンドウのサイズ変更、構成とリソースの変更が行われることがあります。アクティビティで構成の変更に対処する場合、onConfigurationChanged() で通知されます。対処しない場合、アクティビティは再起動されます。

対処する場合、アクティビティは onCreateonConfigurationChanged で現在のディスプレイを確認する必要があります。ディスプレイが変更されたときは、リソースとレイアウトを必ず更新するようにします。

アクティビティに対して選択した起動モードで複数のインスタンスが許容されている場合、セカンダリ画面で起動すると、アクティビティの新しいインスタンスが作成されることがあります。この場合、両方のアクティビティが同時に再開されます。

アクティビティの複数のインスタンスが複数のディスプレイに表示される

Android 8.0 で導入された既存のマルチディスプレイ API についてもご確認ください。

ディスプレイ カットアウト

折りたたみ式デバイスでは、折りたたんだときや広げたときにカットアウト ジオメトリが変更されることがあります。カットアウトに関する問題を回避するために、ディスプレイ カットアウトに関するおすすめの方法をご確認ください。

アクティビティ コンテキストとアプリのコンテキスト

マルチディスプレイでは適切なコンテキストを使用することが非常に重要です。リソースにアクセスするときのアクティビティ コンテキスト(表示される)は、アプリ コンテキスト(表示されない)とは異なります。

アクティビティ コンテキストにはディスプレイに関する情報が含まれており、その表示領域に合わせて常に調整されます。これにより、アプリの現在の密度またはウィンドウの指標に関する正しい情報を取得できます。現在のウィンドウまたはディスプレイに関する情報を取得するには、必ずアクティビティ コンテキスト(または別の UI ベースのコンテキスト)を使用する必要があります。アクティビティ コンテキストは、その情報を使用するシステム API(トーストなど)にも影響を及ぼします。

リソースとコンテキストは、アクティビティのウィンドウ構成と親ディスプレイによって定義されます。現在のディスプレイを取得するには、次のコードを使用します。

val activityDisplay = activity.display

現在のアクティビティのウィンドウに関する指標を取得するには、次のコードを使用します。

val windowMetrics = activity.windowManager.getCurrentWindowMetrics()

現在のシステム構成の最大ウィンドウ指標を取得するには、次のコードを使用します。

val maximumWindowMetrics = activity.windowManager.getMaximumWindowMetrics()

最大ウィンドウ指標は、計算、レイアウトの選択、または事前に取得するリソースのサイズの決定に役立ちます。これを onCreate() で利用できるようにすると、最初のレイアウトパスの前にこれらの決定を行うことができます。これらは特定のレイアウト要素のレイアウトに使用することはできません。代わりに、Configuration オブジェクトからの情報を使用する必要があります。

セカンダリ画面の使用

使用可能なディスプレイは DisplayManager システム サービスから取得できます。

val dm = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
val displays = dm.displays

Display クラスを使用して、フラグの確認など、特定のディスプレイに関する情報を取得して、ディスプレイが安全であるかどうかを確認します。

ただし、ディスプレイのサイズがアプリを配置する定数サイズになると仮定しないでください。マルチウィンドウ モードでは、アプリがディスプレイのサブセットに表示されます。

アクティビティをディスプレイ上で起動できるかどうかを確認するには、次のコードを使用します。

activityManager.isActivityStartAllowedOnDisplay(context, displayId, intent)

アクティビティをディスプレイ上で起動するには、次のコードを使用します。

val options = ActivityOptions.makeBasic()
options.launchDisplayId = 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 アクティビティをサポートしています。

スマートフォンに表示されたマテリアル デザイン ランチャー

セカンダリ ディスプレイに表示されたマテリアル デザイン ランチャー

マルチウィンドウ モード向けにアプリを構成する

アプリが API レベル 24 以降をターゲットにしている場合は、アプリのアクティビティがマルチウィンドウ ディスプレイをサポートする方法と、サポートするかどうかを構成できます。サイズとレイアウトの両方を制御する属性をマニフェストに設定できます。 ルート アクティビティの属性の設定は、タスクスタック内のすべてのアクティビティに適用されます。たとえば、ルート アクティビティで android:resizeableActivity を true に設定すると、タスクスタック内のすべてのアクティビティはサイズ変更可能になります。

注: API レベル 23 以前をターゲットにして複数の画面の向きを持つアプリを作成した場合、ユーザーがそのアプリをマルチウィンドウ モードで使用すると、システムはアプリのサイズを強制的に変更します。さらに、アプリが予期しない動作をする可能性があることをユーザーに警告するダイアログ ボックスを表示します。システムは、画面の向きが固定されたアプリのサイズを変更しません。画面の向きが固定されたアプリをユーザーがマルチウィンドウ モードで開こうとすると、アプリは全画面モードで表示されます。

Chromebook などの一部の大型デバイスでは、android:resizeableActivity=”false” を指定しても、アプリがサイズ変更可能なウィンドウで実行される場合があります。これによりアプリの動作が阻害される場合は、フィルタを使用することで、そのようなデバイスでのアプリの利用を制限できます。

android:resizeableActivity

マルチウィンドウ ディスプレイを有効または無効にするには、マニフェストの <activity> 要素または <application> 要素でこの属性を設定します。

android:resizeableActivity=["true" | "false"]

この属性を true に設定した場合、アクティビティは分割画面モードまたはフリーフォーム モードで起動できます。この属性を false に設定した場合、アクティビティはマルチウィンドウ モードをサポートしません。この値が false の場合、ユーザーがマルチウィンドウ モードでアクティビティを起動しようとすると、アクティビティは全画面モードで表示されます。

API レベル 24 をターゲットとするアプリでこの属性の値を指定しなかった場合、属性の値はデフォルトで true に設定されます。

android:supportsPictureInPicture

マニフェストの <activity> ノードでこの属性を設定すると、アクティビティがピクチャー イン ピクチャー ディスプレイをサポートするかどうかを指定できます。android:resizeableActivity が false の場合、この属性は無視されます。

android:supportsPictureInPicture=["true" | "false"]

レイアウト属性

Android 7.0 では、<layout> マニフェスト要素が、マルチウィンドウ モードでのアクティビティの動作に影響するいくつかの属性をサポートするようになりました。

android:defaultWidth
フリーフォーム モードで起動されたときのアクティビティのデフォルトの幅。
android:defaultHeight
フリーフォーム モードで起動されたときのアクティビティのデフォルトの高さ。
android:gravity
フリーフォーム モードで起動されたときのアクティビティの初期配置。適切な値については、Gravity リファレンスをご覧ください。
android:minHeightandroid:minWidth
分割画面モードとフリーフォーム モードの両方におけるアクティビティの高さと幅の最小値。ユーザーが分割画面モードの分割線を動かして、アクティビティを指定された最小サイズより小さくすると、システムはユーザーが要求するサイズに合わせてアクティビティを切り取ります。

たとえば、次のコードは、アクティビティがフリーフォーム モードで表示されているときに、アクティビティのデフォルトのサイズと位置、および最小サイズを指定する方法を示しています。

<activity android:name=".MyActivity">
    <layout android:defaultHeight="500dp"
          android:defaultWidth="600dp"
          android:gravity="top|end"
          android:minHeight="450dp"
          android:minWidth="300dp" />
</activity>

構成の変更を適切に処理する

デベロッパーがマルチウィンドウ構成(ユーザーがウィンドウのサイズを変更したときの動作など)を変更する場合は、android:configChanges 属性をマニフェストに追加して、少なくとも次の値を指定します。

<activity
  android:name=".MyActivity"
  android:configChanges="screenSize|smallestScreenSize
      |screenLayout|orientation"
/>

android:configChanges を追加すると、アクティビティとフラグメントは破棄されて再作成される代わりに、onConfigurationChanged() へのコールバックを受け取ります。その後、手動でビューを更新したり、リソースを再読み込みしたり、必要に応じて他のオペレーションを実行したりできます。

マルチウィンドウ モードでアプリを実行する

Android 7.0 以降では、マルチウィンドウ モードで実行できるアプリをサポートする機能がシステムによって提供されるようになりました。

マルチウィンドウ モードで無効になる機能

デバイスがマルチウィンドウ モードになっているとき、一部の機能は無効にされるか無視されます。それらの機能は、他のアクティビティまたはアプリとデバイスの画面を共有する可能性があるアクティビティでは意味をなさないためです。そうした機能には次のようなものがあります。

  • システム UI の一部のカスタマイズ オプションは無効になります。たとえば、アプリが全画面モードで実行されていない場合、アプリはステータスバーを非表示にできません。
  • android:screenOrientation 属性に対する変更はシステムにより無視されます。

マルチウィンドウの変更通知とクエリ

Activity は、マルチウィンドウ ディスプレイをサポートする次のメソッドを提供します。

isInMultiWindowMode()
アクティビティがマルチウィンドウ モードで実行されているかどうかを判別する際に呼び出します。
isInPictureInPictureMode()
アクティビティがピクチャー イン ピクチャー モードで実行されているかどうかを判別する際に呼び出します。

注: ピクチャー イン ピクチャー モードは、マルチウィンドウ モードの特殊なケースです。myActivity.isInPictureInPictureMode() が true を返す場合は、myActivity.isInMultiWindowMode() も true を返します。

onMultiWindowModeChanged()
アクティビティがマルチウィンドウ モードに入るかマルチウィンドウ モードから抜けると、システムは常にこのメソッドを呼び出します。アクティビティがマルチウィンドウ モードに入ったときはこのメソッドに true 値が渡され、アクティビティがマルチウィンドウ モードから抜けたときはこのメソッドに false 値が渡されます。
onPictureInPictureModeChanged()
アクティビティがピクチャー イン ピクチャー モードに入るかピクチャー イン ピクチャー モードから抜けると、システムは常にこのメソッドを呼び出します。アクティビティがピクチャー イン ピクチャー モードに入ったときはこのメソッドに true 値が渡され、アクティビティがピクチャー イン ピクチャー モードから抜けたときはこのメソッドに false 値が渡されます。

Fragment クラスは、上記のメソッドの多くについて異なるバージョン(たとえば Fragment.onMultiWindowModeChanged())をエクスポーズします。

ピクチャー イン ピクチャー モードに切り替える

アクティビティをピクチャー イン ピクチャー モードに切り替えるには、Activity.enterPictureInPictureMode() を呼び出します。デバイスがピクチャー イン ピクチャー モードをサポートしていない場合、このメソッドは効果を生じさせません。詳しくは、ピクチャー イン ピクチャーのドキュメントをご覧ください。

マルチウィンドウ モードで新しいアクティビティを起動する

新しいアクティビティを起動するとき、新しいアクティビティを現在のアクティビティの隣に(表示できる場合は)表示する必要があるかどうかを指定できます。これを行うには、インテント フラグ FLAG_ACTIVITY_LAUNCH_ADJACENT を使用します。 このフラグは、起動されたアクティビティの隣に新しいアクティビティを作成するようシステムに指示して、2 つのアクティビティが画面を共有するようにします。システムはそうするように努めますが、実現できるとは限りません。

デバイスがフリーフォーム モードになっているときに新しいアクティビティを起動する場合は、ActivityOptions.setLaunchBounds() を呼び出すことにより、新しいアクティビティのディメンションと画面上の位置を指定できます。デバイスがマルチウィンドウ モードになっていない場合、このメソッドは効果を生じさせません。

注: タスクスタック内でアクティビティを起動すると、画面上のアクティビティが、起動されたアクティビティに置き換えられ、すべてのマルチウィンドウ プロパティが継承されます。マルチウィンドウ モードで新しいアクティビティを別のウィンドウとして起動する場合は、そのアクティビティを新しいタスクスタックで起動する必要があります。

ドラッグ&ドロップをサポートする

2 つのアクティビティが画面を共有しているとき、ユーザーは一方のアクティビティからもう一方のアクティビティにデータをドラッグ&ドロップできます(Android 7.0 より前のバージョンでは、同じアクティビティ内でしかデータをドラッグ&ドロップできませんでした)。編集可能な TextView ウィジェットでドロップされたコンテンツの受け入れに対するサポートを迅速に追加するには、Jetpack の OnReceiveContentListener をご覧ください。ドラッグ&ドロップの包括的なサポート(アプリからのコンテンツのドラッグを有効にするなど)については、ドラッグ&ドロップのトピックをご覧ください。

DragAndDropPermissions
ドロップ先のアプリに付与される権限を指定するトークン オブジェクト。
View.startDragAndDrop()
View.startDrag() のエイリアス。アクティビティ間のドラッグ&ドロップを有効にするには、DRAG_FLAG_GLOBAL フラグを渡します。ドロップ先のアクティビティに URI 権限を付与する必要がある場合は、権限に応じて DRAG_FLAG_GLOBAL_URI_READ フラグまたは DRAG_FLAG_GLOBAL_URI_WRITE フラグを渡します。
View.cancelDragAndDrop()
現在進行中のドラッグ オペレーションをキャンセルします。ドラッグ オペレーションを開始した側のアプリだけが呼び出せます。
View.updateDragShadow()
現在進行中のドラッグ オペレーションのドラッグ シャドウを置き換えます。ドラッグ オペレーションを開始した側のアプリだけが呼び出せます。
Activity.requestDragAndDropPermissions()
DragEvent に含まれる ClipData で渡されるコンテンツ URI の権限をリクエストします。
DragAndDropPermissions.release()
ClipData で指定されたコンテンツ URI のデータにアクセスするために必要な権限を解放します。このメソッドを呼び出さなかった場合は、権限を含むアクティビティが破棄されたときに、自動的に権限が解放されます。

マルチインスタンス

各ルート アクティビティは独自のタスクを持ち、独立したプロセスで実行され、独自のウィンドウに表示されます。アプリの新しいインスタンスを別のウィンドウで起動するには、FLAG_ACTIVITY_NEW_TASK フラグを指定して新しいアクティビティを開始します。これとマルチウィンドウ属性のいくつかを組み合わせることで、新しいウィンドウの場所を指定できます。たとえば、ショッピング アプリであれば、商品比較のために複数のウィンドウを表示できます。

マルチインスタンスとマルチパネル レイアウト(SlidingPaneLayout を使用するリストやディテール レイアウトなど)を混同しないでください。マルチパネル レイアウトは 1 つのウィンドウ内で実行されます。

なお、折りたたみ式デバイスで複数のインスタンスが個別のウィンドウで実行されている場合、ポーズが変更されると、1 つ以上のインスタンスがバックグラウンドに移動する可能性があります。たとえば、デバイスが折りたたまれていない状態で、2 つのアプリ インスタンスが折り目の両側にある 2 つのウィンドウで実行されているとします。デバイスが折りたたまれると、小さくなった画面に合うよう両方のインスタンスが調整される代わりに、片方のインスタンスが終了する可能性があります。

アプリのマルチウィンドウ サポートをテストする

アプリが API レベル 24 以降をターゲットにしているかどうかにかかわらず、ユーザーが Android 7.0 以降を搭載したデバイスをマルチウィンドウ モードにしてアプリを起動しようとする場合に備えて、アプリがマルチウィンドウ モードでどのように動作するかを確認する必要があります。

テストデバイスの設定

Android 7.0 以降を搭載したデバイスでは、分割画面モードが自動的にサポートされます。

アプリが API レベル 23 以前をターゲットにしている場合

アプリが API レベル 23 以前をターゲットにしている場合、アプリが固定された画面の向きを宣言していない限り、ユーザーがマルチウィンドウ モードでアプリを使用しようとすると、システムはアプリのサイズを強制的に変更します。

アプリが固定された画面の向きを宣言していない場合は、Android 7.0 以降を搭載したデバイスでアプリを起動し、アプリを分割画面モードにしてみる必要があります。アプリのサイズが強制的に変更されたら、ユーザー エクスペリエンスが許容範囲内かどうかを確認します。

アプリが固定された画面の向きを宣言している場合は、アプリをマルチウィンドウ モードにしてみる必要があります。そうしようとしても、全画面モードのままであることを確認します。

マルチウィンドウ モードをサポートしている場合

アプリが API レベル 24 以降をターゲットにしており、マルチウィンドウのサポートを無効にしていない場合は、分割画面モードとフリーフォーム モードの両方で次の動作を確認します。

  • アプリを全画面モードで起動した後、オーバービュー ボタンを長押しして、マルチウィンドウ モードに切り替えます。アプリのモードが適切に切り替わることを確認します。
  • マルチウィンドウ モードで直接アプリを起動し、アプリが適切に起動されることを確認します。オーバービュー ボタンを押した後、アプリのタイトルバーを長押しして、画面上のハイライト表示された領域のいずれかにアプリをドラッグすると、マルチウィンドウ モードでアプリを起動できます。
  • 分割画面モードで分割線をドラッグして、アプリのサイズを変更します。 アプリがクラッシュせず、アプリのサイズが変更され、必要な UI 要素が表示されることを確認します。
  • アプリの最小ディメンションを指定している場合は、アプリをそれらのディメンション以下にしてみます。指定した最小ディメンションより小さいサイズに変更できないことを確認します。
  • すべてのテストを通して、アプリのパフォーマンスが許容範囲内かどうかを確認します。たとえば、アプリのサイズを変更したとき、UI の更新に時間がかかりすぎないかを確認します。

テスト チェックリスト

マルチウィンドウ モードでアプリのパフォーマンスを確認するには、以下の操作を試します。特に記載のない限り、分割画面モードとマルチウィンドウ モードの両方でこれらの操作を試す必要があります。

  • マルチウィンドウ モードに入り、マルチウィンドウ モードから抜けます。
  • 一方のアプリからもう一方のアプリに切り替え、最初のアプリが適切に動作する(表示されたままだが、アクティブでなくなる)ことを確認します。たとえば、アプリが動画を再生している場合、ユーザーが別のアプリを操作しているときも動画を再生し続けることを確認します。
  • 分割画面モードで分割線を動かして、アプリの拡大と縮小を試します。アプリを左右に並べて表示しているときと上下に並べて表示しているときの両方で、これらの操作をテストします。アプリがクラッシュせず、基本的な機能が表示され、サイズ変更が速やかに行われることを確認します。
  • いくつかのサイズ変更操作を続けてすばやく行います。アプリがクラッシュせず、メモリリークが発生しないことを確認します。アプリのメモリ使用状況を確認するには、Android Studio の Memory Profiler を使用します。
  • さまざまなウィンドウ構成でアプリを通常どおりに使用し、アプリが適切に動作することを確認します。テキストが判読可能で、UI 要素が操作できないほど小さくならないことを確認します。

マルチウィンドウ サポートを無効にした場合

android:resizeableActivity="false" を設定してマルチウィンドウ サポートを無効にした場合は、Android 7.0 以降を搭載したデバイスでアプリを起動し、アプリをフリーフォーム モードと分割画面モードにしてみる必要があります。そうしようとしても、全画面モードのままであることを確認します。

Android におけるマルチウィンドウ サポートの詳細については、Android N でマルチウィンドウを準備するための 5 つのヒントマルチウィンドウ プレイグラウンド サンプルアプリを参照してください。