Android 5 (API 級別 21) 中導入的媒體投影 API 可讓您將裝置螢幕的內容擷取為媒體串流,以便播放、錄製或投放到電視等其他裝置。
媒體投影包含裝置螢幕的三種表示法:

Surface
。媒體投影功能會擷取裝置螢幕的內容,然後將擷取的圖片投影到虛擬螢幕上,以在 Surface
轉譯圖片。
應用程式會透過 SurfaceView
或 ImageReader
提供 Surface
,兩種方式都會取用擷取的螢幕內容。ImageReader
的 OnImageAvailableListener
可讓您即時管理 Surface
上轉譯的圖片。您可以將圖片儲存為錄製內容,或是將圖片投放到電視或其他裝置。
MediaProjection
取得權杖,允許應用程式擷取螢幕內容、裝置音訊,或同時擷取兩者,以啟動媒體投影工作階段。權杖由 MediaProjection
類別的執行個體表示。您可以在開始一項新的活動時建立此類別的執行個體。
舊版做法
如要使用舊版做法取得媒體投影權杖,請使用從 MediaProjectionManager
系統服務的 createScreenCaptureIntent()
方法傳回的意圖呼叫 startActivityForResult()
:
Kotlin
startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION)
Java
startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
呼叫會顯示一個確認對話方塊,通知使用者媒體投影擷取所有顯示的資訊,包括任何敏感資訊或個人識別資訊。
如果使用者提供了確認,startActivityForResult()
會將結果代碼和資料傳送至 onActivityResult()
回呼。
接著,您可以將資料從 MediaProjectionManager
傳送至 getMediaProjection()
方法,藉此建立 MediaProjection
的執行個體:
Kotlin
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, resultData)
Java
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, resultData);
建議做法
如要取得媒體投影權杖,建議您使用 Jetpack Activity 資料庫的 API:
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()); } } );
虛擬螢幕
媒體投影的核心部分是虛擬螢幕,您可以透過 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
參數會指定虛擬螢幕的寬度和高度。如要取得符合媒體投影寬度與高度的值,請使用 Android 11 (API 級別 30) 中導入的 WindowMetrics
API。
WindowMetrics
無論建立媒體投影的應用程式是以全螢幕模式或多視窗模式執行,媒體投影都會擷取整個螢幕。
正確取得媒體投影維度的方法為 WindowManager#getMaximumWindowMetrics()
。這個方法會傳回整個螢幕的 WindowMetrics
物件;即使媒體投影應用程式為多視窗模式且只涵蓋部分螢幕也一樣。
為了往下與 API 級別 14 相容,請使用 Jetpack WindowManager 資源庫的 WindowMetricsCalculator#computeMaximumWindowMetrics()
。
呼叫 WindowMetrics#getBounds()
以取得媒體投影虛擬螢幕的正確寬度與高度 (請參閱虛擬螢幕)。
請確保您的媒體投影應用程式可調整大小。可調整大小的應用程式支援裝置設定變更和多視窗模式 (請參閱「多視窗模式支援」)。
如果應用程式無法重新調整大小,則必須使用視窗內容查詢螢幕邊界,並使用 WindowManager#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();
途徑
您需要調整媒體途徑的大小,以所需的解析度產生輸出內容。建議您在電視或電腦顯示器上投放畫面時,將螢幕調整為大尺寸 (低解析度);在進行裝置螢幕錄製時調整為小尺寸 (高解析度)。
自 12L (API 級別 32) 起,當系統在途徑轉譯虛擬螢幕時,會使用類似於 ImageView
中 centerInside
選項的流程來縮放虛擬螢幕,使其適合途徑尺寸。
新的縮放方法能夠透過盡量放大途徑影像大小,同時確保適當的顯示比例,來改善電視和其他大螢幕的畫面投放功能。
建議
如想獲得媒體投影的最佳效果,請遵循下列建議做法:
- 讓您的應用程式可調整大小。可調整大小的應用程式支援裝置設定變更和多視窗模式 (請參閱「多視窗模式支援」)。在應用程式資訊清單中,設定
resizeableActivity="true"
。在 Android 7.0 (API 級別 24) 以上版本中,這項設定預設為 true。 - 請讓您的應用程式支援橫向和直向模式,因為這兩種螢幕方向在手機、平板電腦和折疊式裝置板型規格中都很常見。
- 使用
WindowManager#getMaximumWindowMetrics()
取得媒體投影的邊界。為了往下與 API 級別 14 相容,請使用 Jetpack WindowManager (請參閱 WindowMetrics 一節)。 - 如果您的應用程式無法調整大小,請透過視窗內容取得媒體投影邊界 (請參閱 WindowMetrics 一節)。
資源
詳情請參閱「擷取影片和音訊播放」。