接続されたディスプレイは、デスクトップ ウィンドウ エクスペリエンスを標準のスマートフォンに拡張し、ユーザーがモバイル デバイスから大画面にアクセスできるようにします。この機能により、アプリの操作性とユーザーの生産性が向上します。
デスクトップ ウィンドウのすべての固有機能は、接続されたディスプレイに適用されます。スマートフォンをディスプレイに接続すると、スマートフォンの状態は変わらず、接続されたディスプレイで空白のデスクトップ セッションが開始されます。デバイスとディスプレイは、それぞれ独自のアプリを持つ 2 つの個別のシステムとして機能します。
タブレットなどのデスクトップ ウィンドウ機能対応デバイスを外部モニターに接続すると、デスクトップ セッションが両方のディスプレイに拡張されます。2 つのディスプレイは、1 つの連続したシステムとして機能します。この設定により、ウィンドウ、コンテンツ、カーソルを 2 つのディスプレイ間で自由に移動できます。
接続されたディスプレイを効果的にサポートするには、アプリの設計と実装のいくつかの側面に注意する必要があります。次のベスト プラクティスに沿って、スムーズで生産性の高いユーザー エクスペリエンスを実現しましょう。
動的ディスプレイの変更を処理する
多くのアプリは、Display オブジェクトとその特性がアプリのライフサイクル中に変化しないことを前提に構築されています。ただし、ユーザーが外部モニターを接続または切断した場合や、アプリのウィンドウをディスプレイ間で移動した場合、アプリのコンテキストまたはウィンドウに関連付けられている基盤となる Display オブジェクトが変更される可能性があります。ディスプレイのサイズ、解像度、リフレッシュ レート、HDR サポート、密度などのプロパティはすべて異なる可能性があります。スマートフォンの画面に基づいて値をハードコードすると、外部ディスプレイでレイアウトが崩れる可能性があります。
外部ディスプレイのピクセル密度も大きく異なる場合があります。アプリが密度変化に正しく対応していることを確認する必要があります。これには、レイアウトに密度非依存ピクセル(dp)を使用すること、密度固有のリソースを提供すること、UI が適切にスケーリングされるようにすることなどが含まれます。
ディスプレイが切断されたときにアクティビティが外部ディスプレイで実行されている場合、システムはアクティビティをメイン ディスプレイに移動します。移動により、画面サイズや密度などの構成変更がトリガーされ、アクティビティが再作成されることがあります。アプリは、UI の状態を保存して復元することで、構成変更に対応し、データ損失やユーザー エクスペリエンスの混乱を防ぐ必要があります。
適切なコンテキストを使用する
マルチディスプレイ環境では適切なコンテキストを使用することが非常に重要です。リソースにアクセスするときのアクティビティ コンテキスト(表示される)は、アプリ コンテキスト(表示されない)とは異なります。
アクティビティ コンテキストはディスプレイに関する情報を含んでおり、アクティビティの表示領域に合わせて常に調整されます。これにより、アプリの表示密度やウィンドウ指標に関する正しい情報を取得できます。現在のウィンドウまたはディスプレイに関する情報を取得するには、必ずアクティビティ コンテキスト(または別の UI ベースのコンテキスト)を使用してください。アクティビティ コンテキストは、その情報を使用するシステム API にも影響を及ぼします。
Jetpack Compose では、LocalConfiguration.current や LocalDensity.current などの CompositionLocal オブジェクトを使用して、ディスプレイ固有の情報にアクセスできます。アクティビティまたはウィンドウがディスプレイ間を移動すると、デバイスの構成が変更され、新しいディスプレイ指標で再コンポーズがトリガーされます。CompositionLocal オブジェクトを使用すると、UI をシームレスに適応させることができます。
ディスプレイ情報を取得する
Display クラスを使用して、ディスプレイのサイズ、密度、フラグなどの情報を取得できます。DisplayManager システム サービスを使用して、使用可能なディスプレイを取得します。外部ディスプレイを識別するには、通常はスマートフォンやタブレットの内蔵画面である Display.DEFAULT_DISPLAY を除外します。
val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
val displays = displayManager.getDisplays()
// The default display is 0. External displays have other IDs.
val externalDisplays = displays.filter { it.displayId != Display.DEFAULT_DISPLAY }
アクティビティの起動と構成を管理する
接続されたディスプレイでは、アプリは起動時や別のアクティビティの作成時に、どのディスプレイで動作するかを指定できます。この動作は、マニフェスト ファイルで定義したアクティビティの起動モード、またはアクティビティを起動するエンティティが設定したインテント フラグやオプションによって異なります。
アクティビティをセカンダリ ディスプレイに移動すると、アプリでコンテキストの更新、ウィンドウのサイズ変更、構成とリソースの変更が行われることがあります。アクティビティで構成の変更に対処する場合、onConfigurationChanged() で通知されます。それ以外の場合、アクティビティは再起動されます。
アクティビティに対して選択した起動モードで複数のインスタンスが許容されている場合、セカンダリ画面で起動すると、アクティビティの新しいインスタンスが作成されることがあります。両方のアクティビティが同時に再開されるため、特定のマルチタスク シナリオでメリットがあります。
ActivityOptions を使用して、特定ディスプレイでアクティビティを起動できます。なお、launchDisplayId には Android 8(API レベル 26)以上が必要です。
// Get DisplayManager and find the first external display.
val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
val externalDisplayId = displayManager.displays
.firstOrNull { it.displayId != Display.DEFAULT_DISPLAY }
?.displayId
// If an external display is found, launch the activity on it.
if (externalDisplayId != null) {
val intent = Intent(this, MySecondaryActivity::class.java)
val options = ActivityOptions.makeBasic()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
options.launchDisplayId = externalDisplayId
}
startActivity(intent, options.toBundle())
} else {
// Optionally, handle the case where no external display is connected.
}
デバイスの許可リストを避ける
アプリは、許可リストを使用するか、BUILD.MODEL と組み込みのディスプレイ サイズを確認することで、大画面の UI と機能を特定のデバイスに制限することがあります。このアプローチは、接続されたディスプレイには有効ではありません。ほぼすべてのデバイスを大画面に接続でき、外部ディスプレイが接続されてもデバイスモデルは変更されないためです。
許可リストを使用したり、BUILD.MODEL や組み込みのディスプレイ サイズを確認したりする代わりに、ランタイムにウィンドウの指標やデバイスの機能を確認して UI を決定します。Jetpack WindowManager API またはウィンドウ サイズクラスを使用して、さまざまな画面サイズと密度に対応するレスポンシブ レイアウトとアダプティブ レイアウトを構築します。
外部周辺機器をサポート
ユーザーが外部ディスプレイに接続すると、多くの場合、デスクトップのような環境が作成されます。多くの場合、外付けキーボード、マウス、トラックパッド、ウェブカメラ、マイク、スピーカーを使用します。アプリがこれらの周辺機器とシームレスに連携できるようにする必要があります。これには、キーボード ショートカットの処理、マウス ポインタの操作の管理、外部カメラやマイクの正しいサポート、音声出力ルーティングの尊重が含まれます。詳しくは、大画面での入力の互換性をご覧ください。
ユーザーの生産性を高める
接続されたディスプレイは、ユーザーの生産性を向上させる大きな機会を提供します。これで、デスクトップ アプリケーションに匹敵するエクスペリエンスを提供できるモバイルアプリを構築するためのツールが揃いました。ユーザーの生産性を高めるために、次の機能の実装を検討してください。
- 同じアプリの複数のインスタンスを開くことができます。ドキュメントの比較、複数の会話の管理、複数のファイルの同時表示などのタスクに役立ちます。
- ドラッグ&ドロップを使用して、アプリ内外でリッチデータを共有できるようにします。
- 堅牢な状態管理システムを実装して、構成の変更後もユーザーがワークフローを維持できるようにします。
これらのガイドラインに沿って、提供されているコード例を活用することで、接続されたディスプレイにシームレスに適応するアプリを作成し、ユーザーにリッチで生産性の高いエクスペリエンスを提供できます。