メディア プロジェクション

android.media.projection Android 5(API レベル 21)で導入された API を使用すると、コンテンツをキャプチャできます。 再生、録画、キャストが可能なメディア ストリームとして、 テレビなどの他のデバイスに接続できます。

Android 14(API レベル 34)では、アプリの画面共有が導入され、ユーザーが デバイス画面全体ではなく 1 つのアプリ ウィンドウを共有 使用します。アプリの画面共有には、ステータスバー、ナビゲーション バー、 通知、その他のシステム UI 要素を、共有ディスプレイから アプリの画面共有を使用して全画面表示でアプリを撮影する場合。選択したアプリのコンテンツのみが共有されます。

アプリの画面共有により、ユーザーのプライバシーを確保し、ユーザーの生産性を向上させます。 マルチタスク機能を強化するために、ユーザーが複数のアプリを 1 つのアプリでのみコンテンツを共有できます。

3 つのディスプレイ表現

メディア プロジェクションは、デバイスのディスプレイやアプリ ウィンドウのコンテンツをキャプチャします。 キャプチャした画像を仮想ディスプレイに投影し、ディスプレイに画像を Surface

仮想ディスプレイに実際のデバイス ディスプレイを投影する。仮想ディスプレイのコンテンツをアプリが提供する「サーフェス」に書き込む。
図 1. 実際のデバイス画面またはアプリ ウィンドウを投影 表示されます。アプリケーション提供に書き込まれた仮想ディスプレイ Surface

アプリは、次の方法で Surface を提供します。 MediaRecorder SurfaceTexture、または ImageReader: キャプチャしたディスプレイのコンテンツを表示し、レンダリングされた画像を管理できます。 Surfaceにリアルタイムで見てもらうことができます。録画またはキャストとして画像を保存できます キャストできます。

実際のディスプレイ

メディア プロジェクション セッションを開始するには、アプリに デバイスのディスプレイやアプリ ウィンドウのコンテンツをキャプチャする機能。トークン トレーニング データの MediaProjection クラスです。

次の getMediaProjection() メソッドを使用します。 MediaProjection インスタンスを作成する MediaProjectionManager システム サービス 更新します。アプリケーションのインテントでアクティビティを開始する 画面を指定する createScreenCaptureIntent() メソッド キャプチャ操作:

Kotlin

val mediaProjectionManager = getSystemService(MediaProjectionManager::class.java)
var mediaProjection : MediaProjection

val startMediaProjection = registerForActivityResult(
    StartActivityForResult()
) { result ->
    if (result.resultCode == RESULT_OK) {
        mediaProjection = mediaProjectionManager
            .getMediaProjection(result.resultCode, result.data!!)
    }
}

startMediaProjection.launch(mediaProjectionManager.createScreenCaptureIntent())

Java

final MediaProjectionManager mediaProjectionManager =
    getSystemService(MediaProjectionManager.class);
final MediaProjection[] mediaProjection = new MediaProjection[1];

ActivityResultLauncher<Intent> startMediaProjection = registerForActivityResult(
    new StartActivityForResult(),
    result -> {
        if (result.getResultCode() == Activity.RESULT_OK) {
            mediaProjection[0] = mediaProjectionManager
                .getMediaProjection(result.getResultCode(), result.getData());
        }
    }
);

startMediaProjection.launch(mediaProjectionManager.createScreenCaptureIntent());

仮想ディスプレイ

メディア プロジェクションの中心となるのは仮想ディスプレイです。仮想ディスプレイは、MediaProjection インスタンスで createVirtualDisplay() を呼び出して作成します。

Kotlin

virtualDisplay = mediaProjection.createVirtualDisplay(
                     "ScreenCapture",
                     width,
                     height,
                     screenDensity,
                     DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                     surface,
                     null, null)

Java

virtualDisplay = mediaProjection.createVirtualDisplay(
                     "ScreenCapture",
                     width,
                     height,
                     screenDensity,
                     DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                     surface,
                     null, null);

width パラメータと height パラメータは、仮想デバイスのディメンションを指定します。 表示されます。幅と高さの値を取得するには、 WindowMetrics API の導入 。(詳しくは、 メディア プロジェクション サイズのセクションを参照)。

Surface

メディア プロジェクション サーフェスのサイズを調整して、適切な出力が生成されるようにします。 解決します。テレビに画面をキャストする場合や、ディスプレイを低解像度にキャストする パソコンのモニターと、デバイスのディスプレイ録画用の小型(高解像度)

Android 12L(API レベル 32)以降では、キャプチャしたコンテンツを システムでは、アスペクト比を維持しながらコンテンツが均一にスケーリングされます。 コンテンツの寸法(幅と高さ)を同じサイズ以下にする 表します。キャプチャされたコンテンツは 表面の中央に配置されます。

Android 12L のスケーリング アプローチにより、テレビへの画面キャストが改善され、 サーフェス画像のサイズを最大化するとともに 適切なアスペクト比を選択します。

フォアグラウンド サービスの権限

Android 14 以降をターゲットとするアプリの場合、アプリ マニフェストに に対する権限の宣言 mediaProjection フォアグラウンド サービスのタイプ:

<manifest ...>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
    <application ...>
        <service
            android:name=".MyMediaProjectionService"
            android:foregroundServiceType="mediaProjection"
            android:exported="false">
        </service>
    </application>
</manifest>

startForeground() を呼び出してメディア プロジェクション サービスを開始します。

呼び出しでフォアグラウンド サービスのタイプを指定しない場合、 マニフェストで定義されているフォアグラウンド サービス タイプのビット単位の整数に設定します。条件 マニフェストでサービスタイプが指定されていない場合、システムによって MissingForegroundServiceTypeException.

アプリは、各メディア プロジェクション セッションの前にユーザーの同意をリクエストする必要があります。 createVirtualDisplay() の 1 回の呼び出しです。MediaProjection トークン 呼び出しを行うために 1 回だけ使用するようにしてください。

Android 14 以降では、createVirtualDisplay() メソッドは SecurityException に アプリは次のいずれかを実行します。

  • createScreenCaptureIntent() から getMediaProjection() に返された Intent インスタンスを複数回渡します。
  • 同じ MediaProjectioncreateVirtualDisplay() を複数回呼び出します インスタンス

メディア プロジェクション サイズ

メディア プロジェクションでは、デバイスのディスプレイ全体またはアプリ ウィンドウをキャプチャできます。 常に同じです

初期サイズ

全画面のメディア プロジェクションでは、アプリで クリックします。アプリの画面共有では、アプリは ユーザーがキャプチャ領域を選択するまでキャプチャされたディスプレイのサイズ。 そのため、メディア プロジェクションの初期サイズはデバイスの画面サイズとなります。

WindowManager プラットフォームを使用する getMaximumWindowMetrics() メソッドで 次のクラスの WindowMetrics オブジェクト: メディア プロジェクション ホストアプリがマルチウィンドウにある場合でも、デバイスの画面 ディスプレイの一部だけに表示されます。

API レベル 14 までに対応するには、WindowMetricsCalculator computeMaximumWindowMetrics() を使用します。 メソッドを使用します。WindowManager

WindowMetricsgetBounds() メソッドを呼び出して、デバイス ディスプレイの幅と高さを取得します。

サイズの変更

デバイスを回転させると、メディア プロジェクションのサイズが変わることがある またはユーザーがアプリ画面共有のキャプチャ領域としてアプリ ウィンドウを選択したとき。 キャプチャされたコンテンツが 最大ウィンドウ指標とは異なるサイズにするため、 表示されます。

キャプチャした画像のサイズとメディア プロジェクションを デバイスの回転をまたいで取得する場合は、 キャプチャのサイズを変更するための onCapturedContentResize() コールバック。(詳しくは、 後述のカスタマイズをご覧ください)。

カスタマイズ

アプリでは、以下を使用してメディア プロジェクションのユーザー エクスペリエンスをカスタマイズできます。 MediaProjection.Callback API:

  • onCapturedContentVisibilityChanged(): ホストアプリ(メディア プロジェクションを開始したアプリ)による表示または 非表示にできます。

    このコールバックを使用して、キャプチャされたかどうかに基づいてアプリの UI をカスタマイズします。 ユーザーに表示されます。たとえば、アプリが一般公開される アプリの UI 内にキャプチャしたコンテンツが表示されている ユーザーに表示されます( ユーザーが同じコンテンツを 2 回表示します。コールバックを使用して更新する 使用して、キャプチャしたコンテンツを非表示にして、 他のコンテンツもチェックできます

  • onCapturedContentResize(): ホストアプリが仮想デバイスのメディア プロジェクションのサイズを変更できるようにします。 キャプチャしたサイズに応じて、ディスプレイとメディア プロジェクションの Surface 表示されます。

    キャプチャしたコンテンツ(1 つのアプリ ウィンドウまたは全画面)が表示されるたびにトリガーされます デバイスのディスプレイ - サイズの変更(デバイスの回転またはキャプチャされた 別のウィンドウ モードに切り替わる場合など)。この API を使用して、 キャプチャしたアスペクト比とアスペクト比が一致するように、仮想ディスプレイとサーフェス キャプチャがレターボックス表示されていません。

リソースの復旧

アプリは MediaProjection を登録する必要があります。 onStop() メディア プロジェクション セッションが停止して 無効です。セッションが停止したら、アプリはセッションを終了したリソースを 仮想ディスプレイや投影面など、ディスプレイが保持するA は メディア プロジェクション セッションで新しい仮想ディスプレイを作成できなくなった アプリでそのメディア プロジェクションの仮想ディスプレイがまだ作成されていない。

メディア プロジェクションの終了時にコールバックが呼び出されます。これは、 ユーザーが手動でセッションを停止した場合、またはシステムがユーザーのセッションを 理由があります。

アプリがコールバックを登録しない場合、createVirtualDisplay() の呼び出しは スロー IllegalStateException.

無効にする

Android 14 以降では、アプリの画面共有がデフォルトで有効になっています。メディアごとの プロジェクション セッションを使用すると、アプリ ウィンドウや 表示できます。

アプリは、 createScreenCaptureIntent(MediaProjectionConfig) メソッド の呼び出しから返された MediaProjectionConfig 引数で createConfigForDefaultDisplay()

createScreenCaptureIntent(MediaProjectionConfig) への呼び出し 呼び出しから返された MediaProjectionConfig 引数。 createConfigForUserChoice() は同じです デフォルトの動作、つまり createScreenCaptureIntent()

サイズ変更可能なアプリ

常にメディア プロジェクション アプリのサイズを変更できるようにしてください(resizeableActivity="true")。サイズ変更可能 アプリは、デバイス設定の変更とマルチ ウィンドウ モードをサポートします( マルチウィンドウのサポート)。

サイズ変更できないアプリの場合、ウィンドウからディスプレイ境界をクエリする必要があります getMaximumWindowMetrics() を使用してその WindowMetrics を取得します。 アプリが使用できる最大表示領域 :

Kotlin

val windowContext = context.createWindowContext(context.display!!,
      WindowManager.LayoutParams.TYPE_APPLICATION, null)
val projectionMetrics = windowContext.getSystemService(WindowManager::class.java)
      .maximumWindowMetrics

Java

Context windowContext = context.createWindowContext(context.getDisplay(),
      WindowManager.LayoutParams.TYPE_APPLICATION, null);
WindowMetrics projectionMetrics = windowContext.getSystemService(WindowManager.class)
      .getMaximumWindowMetrics();

参考情報

メディア プロジェクションの詳細については、動画と音声の再生のキャプチャをご覧ください。