미디어 프로젝션

android.media.projection Android 5 (API 수준 21)에 도입된 API를 사용하면 재생, 녹화 또는 전송할 수 있는 미디어 스트림으로 표시되는 기기 디스플레이의 기타 기기(예: TV)

Android 14 (API 수준 34)에는 사용자가 다른 기기와 상관없이 전체 기기 화면이 아닌 단일 앱 창 공유 윈도잉 모드. 앱 화면 공유 시 상태 표시줄, 탐색 메뉴, 알림 및 기타 시스템 UI 요소를 공유 디스플레이에서 사용할 수 있습니다. 앱 화면 공유를 사용하여 앱을 전체 화면으로 캡처할 때 선택한 앱의 콘텐츠만 공유됩니다.

앱 화면 공유는 사용자 개인 정보 보호를 보장하고 사용자 생산성을 개선하며 사용자가 여러 앱을 실행할 수 있도록 지원하여 멀티태스킹을 향상하지만 공유할 수 있습니다.

세 가지 디스플레이 표현

미디어 프로젝션은 기기 디스플레이 또는 앱 창의 콘텐츠를 캡처하고 캡처한 이미지를 가상 디스플레이에 투사하여 Surface

가상 디스플레이에 프로젝션된 실제 기기 디스플레이 애플리케이션에서 제공하는 `Surface`에 기록된 가상 디스플레이의 콘텐츠
그림 1. 화면에 프로젝션된 실제 기기 화면 또는 앱 창 가상 디스플레이입니다. 애플리케이션 제공에 작성된 가상 디스플레이 Surface

애플리케이션은 다음을 통해 Surface를 제공합니다. MediaRecorder님, SurfaceTexture 또는 ImageReader는 캡처된 디스플레이의 콘텐츠를 관리하고 렌더링된 이미지 관리 실시간으로 Surface을(를) 볼 수 있습니다. 이미지를 녹화 또는 전송으로 저장할 수 있습니다. TV나 다른 기기에 전송할 수 있습니다.

실제 디스플레이

앱에 기기 디스플레이 또는 앱 창의 콘텐츠를 캡처하는 기능 토큰 는 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())

자바

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)

자바

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

widthheight 매개변수는 가상 머신의 크기를 지정합니다. 디스플레이. 너비와 높이 값을 얻으려면 WindowMetrics API 도입 (Android 11(API 수준 30)) 자세한 내용은 미디어 프로젝션 크기 섹션).

Surface

미디어 프로젝션 표면 크기를 조정하여 적절한 형식으로 출력을 생성합니다. 있습니다. TV로 화면을 전송하기 위해 화면 크기를 크게 (저해상도) 컴퓨터 모니터 및 기기 디스플레이 녹화용 소형 (고해상도)입니다.

Android 12L (API 수준 32)부터 표면의 경우 시스템에서 콘텐츠의 크기를 균일하게 조정하고 가로세로 비율을 유지하며 콘텐츠의 크기 (너비와 높이)가 같거나 이보다 작아야 합니다. 더 큽니다. 그러면 캡처된 콘텐츠가 지면의 중앙에 오도록 합니다.

Android 12L 확장 접근 방식은 텔레비전과 TV로의 화면 전송을 개선합니다. 표면 이미지의 크기를 최대화하여 다른 대형 디스플레이의 크기를 조절합니다. 가로세로 비율을 조정해야 합니다.

포그라운드 서비스 권한

앱이 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()의 단일 호출입니다. MediaProjection 토큰 한 번만 사용해야 합니다.

Android 14 이상에서 createVirtualDisplay() 메서드는 다음을 발생시킵니다. 다음과 같은 경우 SecurityException 앱이 다음 중 하나를 실행합니다.

  • createScreenCaptureIntent()에서 getMediaProjection()로 반환된 Intent 인스턴스를 두 번 이상 전달합니다.
  • 동일한 MediaProjection에서 createVirtualDisplay()을 두 번 이상 호출합니다. 인스턴스

미디어 프로젝션 크기

미디어 프로젝션은 전체 기기 디스플레이 또는 앱 창을 캡처할 수 있습니다. 윈도잉 모드와는 상관없습니다.

초기 크기

전체 화면 미디어 프로젝션에서는 앱이 기본 동영상의 크기를 기기 화면에 표시됩니다. 앱 화면 공유에서는 앱이 사용자가 캡처 영역을 선택할 때까지 캡처된 디스플레이의 크기를 유지합니다. 따라서 모든 미디어 프로젝션의 초기 크기는 기기 화면의 크기입니다.

WindowManager 플랫폼 이용 getMaximumWindowMetrics() 메서드를 사용하여 다음에 대한 WindowMetrics 객체 미디어 프로젝션 호스트 앱이 멀티 윈도우에 있어도 기기 화면 디스플레이의 일부만 차지합니다.

API 수준 14까지의 호환성을 위해 WindowMetricsCalculator computeMaximumWindowMetrics()를 사용합니다. 메서드를 호출합니다.WindowManager

WindowMetrics getBounds() 메서드를 호출하여 기기 디스플레이의 너비와 높이를 가져옵니다.

크기 변경

미디어 프로젝션의 크기는 기기가 회전할 때 변경될 수 있습니다. 사용자가 앱 화면 공유에서 앱 창을 캡처 영역으로 선택하는 경우 캡처된 콘텐츠가 미디어가 얻은 최대 창 측정항목과 다른 크기 표시됩니다.

미디어 프로젝션을 캡처한 이미지의 크기와 정확하게 정렬되도록 하기 위해 콘텐츠를 캡처하려면 onCapturedContentResize() 콜백으로 캡처 크기를 조절합니다. (자세한 내용은 자세한 내용은 이어지는 맞춤설정 섹션을 참고하세요.

맞춤설정

앱은 다음을 사용하여 미디어 프로젝션 사용자 환경을 맞춤설정할 수 있습니다. MediaProjection.Callback API:

  • onCapturedContentVisibilityChanged(): 호스트 앱 (미디어 프로젝션을 시작한 앱)이 공유 콘텐츠를 숨깁니다.

    이 콜백을 사용하여 캡처된 캡처된 애플리케이션이 있는지 여부에 따라 앱의 UI를 맞춤설정합니다. 리전이 사용자에게 표시됩니다 예를 들어 앱이 앱의 UI 내에 캡처된 콘텐츠를 표시하고 있습니다. 캡처된 앱이 사용자에게도 표시됩니다 (이 콜백) 같은 콘텐츠가 사용자에게 두 번 표시됩니다. 콜백을 사용하여 업데이트 앱의 UI를 사용하여 캡처된 콘텐츠를 숨기고 확인할 수 있습니다.

  • onCapturedContentResize(): 호스트 앱이 가상 머신에서 미디어 프로젝션의 크기를 변경할 수 있도록 사용 설정합니다. 캡처된 크기를 기반으로 Surface 디스플레이 및 미디어 프로젝션 표시됩니다.

    캡처된 콘텐츠(단일 앱 창 또는 전체)가 발생할 때마다 트리거됩니다. 기기 디스플레이—크기 변경 (기기 회전 또는 캡처된 화면 앱이 다른 윈도잉 모드로 전환됨). 이 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

자바

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

추가 리소스

미디어 프로젝션에 관한 자세한 내용은 동영상 및 오디오 재생 캡처를 참고하세요.