android.media.projection
API ra mắt trong Android 5 (API cấp 21) cho phép bạn thu thập nội dung
của màn hình thiết bị dưới dạng luồng nội dung nghe nhìn mà bạn có thể phát lại, ghi hoặc truyền đến
các thiết bị khác, chẳng hạn như TV.
Android 14 (API cấp 34) ra mắt tính năng chia sẻ màn hình ứng dụng, cho phép người dùng chia sẻ một cửa sổ ứng dụng thay vì toàn bộ màn hình thiết bị bất kể chế độ cửa sổ. Tính năng chia sẻ màn hình ứng dụng không bao gồm thanh trạng thái, thanh điều hướng các thông báo và các thành phần khác trên giao diện người dùng hệ thống từ màn hình dùng chung, thậm chí cả khi tính năng chia sẻ màn hình ứng dụng được dùng để chụp một ứng dụng ở chế độ toàn màn hình. Chỉ nội dung của ứng dụng đã chọn mới được chia sẻ.
Tính năng chia sẻ màn hình ứng dụng đảm bảo quyền riêng tư của người dùng, tăng năng suất của người dùng và tăng cường khả năng đa nhiệm bằng cách cho phép người dùng chạy nhiều ứng dụng nhưng hạn chế nội dung chia sẻ với một ứng dụng duy nhất.
Ba cách hiển thị
Tính năng chiếu nội dung đa phương tiện chụp lại nội dung của màn hình thiết bị hoặc cửa sổ ứng dụng và
sau đó chiếu hình ảnh được chụp lên một màn hình ảo để kết xuất hình ảnh đó trên
Surface
.
![Màn hình thiết bị thực tế chiếu lên màn hình ảo. Nội dung của màn hình ảo được ghi vào `Bề mặt` (Surface) do ứng dụng cung cấp.](https://developer.android.google.cn/static/media/images/grow/media-projection.png?authuser=9&hl=vi)
Surface
.
Ứng dụng cung cấp Surface
thông qua một giao diện
MediaRecorder
,
SurfaceTexture
hoặc
ImageReader
, tiêu thụ
nội dung của màn hình đã chụp và cho phép bạn quản lý hình ảnh được kết xuất
trên Surface
theo thời gian thực. Bạn có thể lưu hình ảnh dưới dạng bản ghi hoặc truyền
chúng sang TV hoặc thiết bị khác.
Màn hình thực
Bắt đầu phiên chiếu nội dung đa phương tiện bằng cách lấy mã thông báo cấp cho ứng dụng của bạn
khả năng chụp nội dung của màn hình thiết bị hoặc cửa sổ ứng dụng. Mã thông báo
được biểu thị bằng một bản sao của
MediaProjection
.
Sử dụng phương thức getMediaProjection()
của
Dịch vụ hệ thống của MediaProjectionManager
để tạo một thực thể MediaProjection
khi bạn bắt đầu một hoạt động mới. Bắt đầu hoạt động bằng ý định trong
Phương thức createScreenCaptureIntent()
để chỉ định một màn hình
thao tác chụp:
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());
Màn hình ảo
Tâm điểm của tính năng chiếu nội dung đa phương tiện là màn hình ảo mà bạn tạo bằng cách gọi
createVirtualDisplay()
cho thực thể MediaProjection
:
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);
Các tham số width
và height
chỉ định các kích thước của ảo
màn hình. Để nhận giá trị cho chiều rộng và chiều cao, hãy sử dụng
Ra mắt các API WindowMetrics
trong Android 11 (API cấp 30). (Để biết chi tiết, hãy xem
Kích thước chiếu nội dung đa phương tiện.)
Bề mặt
Xác định kích thước bề mặt chiếu nội dung đa phương tiện để tạo ra đầu ra ở mức thích hợp độ phân giải. Tạo bề mặt lớn (độ phân giải thấp) để truyền màn hình sang TV hoặc và màn hình máy tính nhỏ (độ phân giải cao) để ghi màn hình thiết bị.
Kể từ Android 12L (API cấp 32), khi hiển thị nội dung được ghi trên nền tảng, hệ thống điều chỉnh tỷ lệ nội dung một cách đồng nhất, duy trì tỷ lệ khung hình, để cả hai kích thước nội dung (chiều rộng và chiều cao) bằng hoặc nhỏ hơn so với kích thước tương ứng của bề mặt. Sau đó, nội dung đã ghi sẽ nằm ở giữa bề mặt.
Cách tiếp cận mở rộng quy mô của Android 12L cải thiện việc truyền màn hình đến TV và các màn hình lớn khác bằng cách tối đa hoá kích thước của hình ảnh bề mặt trong khi vẫn đảm bảo tỷ lệ khung hình phù hợp.
Quyền cho dịch vụ trên nền trước
Nếu ứng dụng của bạn nhắm đến Android 14 trở lên, thì tệp kê khai ứng dụng phải chứa một
khai báo quyền cho
Loại dịch vụ trên nền trước 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>
Bắt đầu dịch vụ chiếu nội dung đa phương tiện bằng lệnh gọi đến startForeground()
.
Nếu bạn không chỉ định kiểu dịch vụ trên nền trước trong lệnh gọi, thì kiểu mặc định
thành một số nguyên bitwise của các kiểu dịch vụ trên nền trước được xác định trong tệp kê khai. Nếu
tệp kê khai không chỉ định bất kỳ loại dịch vụ nào, hệ thống sẽ gửi ra
MissingForegroundServiceTypeException
.
Sự đồng ý của người dùng
Ứng dụng của bạn phải yêu cầu người dùng đồng ý trước mỗi phiên chiếu nội dung đa phương tiện. Đáp
là một lệnh gọi đến createVirtualDisplay()
. Mã thông báo MediaProjection
chỉ được sử dụng một lần để thực hiện cuộc gọi.
Trên Android 14 trở lên, phương thức createVirtualDisplay()
sẽ gửi một
SecurityException
nếu
ứng dụng thực hiện một trong những việc sau:
- Truyền một thực thể
Intent
được trả về từcreateScreenCaptureIntent()
chogetMediaProjection()
nhiều lần - Gọi
createVirtualDisplay()
nhiều lần trên cùng mộtMediaProjection
thực thể
Kích thước chiếu nội dung đa phương tiện
Phép chiếu nội dung đa phương tiện có thể chụp toàn bộ màn hình thiết bị hoặc cửa sổ ứng dụng bất kể chế độ kết xuất cửa sổ hiện tại.
Kích thước ban đầu
Với tính năng chiếu nội dung nghe nhìn toàn màn hình, ứng dụng của bạn phải xác định kích thước của phần tử màn hình thiết bị. Trong tính năng chia sẻ màn hình ứng dụng, ứng dụng của bạn sẽ không thể xác định kích thước của màn hình được chụp cho đến khi người dùng chọn khu vực chụp. Vì vậy, kích thước ban đầu của mọi phép chiếu nội dung đa phương tiện là kích thước của màn hình thiết bị.
Sử dụng nền tảng WindowManager
Phương thức getMaximumWindowMetrics()
để trả về một
WindowMetrics
cho thuộc tính
màn hình thiết bị ngay cả khi ứng dụng lưu trữ tính năng chiếu nội dung đa phương tiện ở chế độ nhiều cửa sổ
chỉ chiếm một phần màn hình.
Để tương thích xuống API cấp 14, hãy sử dụng WindowMetricsCalculator
computeMaximumWindowMetrics()
từ thư viện Jetpack WindowManager
.
Gọi phương thức WindowMetrics
getBounds()
để lấy chiều rộng và chiều cao của màn hình thiết bị.
Thay đổi về kích thước
Kích thước của hình chiếu nội dung đa phương tiện có thể thay đổi khi thiết bị được xoay hoặc người dùng chọn một cửa sổ ứng dụng làm khu vực chụp trong tính năng chia sẻ màn hình ứng dụng. Phép chiếu nội dung đa phương tiện có thể ở dạng hòm thư nếu nội dung được chụp là kích thước khác với chỉ số cửa sổ tối đa thu được khi nội dung nghe nhìn phép chiếu đã được thiết lập.
Để đảm bảo phép chiếu nội dung đa phương tiện căn chỉnh chính xác với kích thước của ảnh được chụp
nội dung cho bất kỳ vùng nào được chụp và trên các xoay thiết bị, hãy sử dụng
Lệnh gọi lại onCapturedContentResize()
để đổi kích thước ảnh chụp. (Để biết thêm thông tin
hãy xem phần Tuỳ chỉnh bên dưới).
Tuỳ chỉnh
Ứng dụng của bạn có thể tuỳ chỉnh trải nghiệm người dùng với tính năng chiếu nội dung đa phương tiện bằng các cách sau
Các API MediaProjection.Callback
:
onCapturedContentVisibilityChanged()
: Cho phép ứng dụng lưu trữ (ứng dụng đã bắt đầu phép chiếu nội dung đa phương tiện) hiển thị hoặc ẩn nội dung được chia sẻ.Hãy sử dụng lệnh gọi lại này để tuỳ chỉnh giao diện người dùng của ứng dụng dựa trên việc hiển thị cho người dùng. Ví dụ: nếu ứng dụng của bạn hiển thị với và hiển thị nội dung được chụp trong giao diện người dùng của ứng dụng, đồng thời ứng dụng được chụp lại cũng hiển thị với người dùng (như được biểu thị thông qua ), người dùng sẽ thấy cùng một nội dung hai lần. Sử dụng lệnh gọi lại để cập nhật giao diện người dùng của ứng dụng để ẩn nội dung đã ghi và giải phóng không gian bố cục trong cho nội dung khác.
onCapturedContentResize()
: Cho phép ứng dụng lưu trữ thay đổi kích thước của chế độ chiếu nội dung đa phương tiện trên máy ảo chiếu màn hình và nội dung nghe nhìnSurface
dựa trên kích thước của ảnh chụp khu vực hiển thị.Được kích hoạt bất cứ khi nào nội dung được ghi lại – một cửa sổ ứng dụng hoặc toàn bộ màn hình thiết bị — thay đổi kích thước (do xoay thiết bị hoặc ảnh chụp ứng dụng chuyển sang chế độ cửa sổ khác). Sử dụng API này để đổi kích thước cả màn hình và bề mặt ảo để đảm bảo tỷ lệ khung hình khớp với ảnh chụp và ảnh chụp không ở dạng hòm thư.
Khôi phục tài nguyên
Ứng dụng của bạn phải đăng ký MediaProjection
onStop()
lệnh gọi lại để biết thời điểm phiên chiếu nội dung đa phương tiện bị dừng và kết thúc
không hợp lệ. Khi phiên bị dừng, ứng dụng sẽ giải phóng các tài nguyên
nó giữ, chẳng hạn như màn hình ảo và bề mặt chiếu. A đã dừng
phiên chiếu nội dung đa phương tiện không thể tạo màn hình ảo mới được nữa, ngay cả khi
ứng dụng của bạn trước đây chưa tạo màn hình ảo cho phép chiếu nội dung đa phương tiện đó.
Lệnh gọi lại được gọi khi quá trình chiếu nội dung đa phương tiện kết thúc, do người dùng dừng phiên theo cách thủ công hoặc do hệ thống dừng phiên lý do nào đó.
Nếu ứng dụng của bạn không đăng ký lệnh gọi lại, thì mọi lệnh gọi đến createVirtualDisplay()
ném
IllegalStateException
.
Ngừng
Android 14 trở lên cho phép chia sẻ màn hình ứng dụng theo mặc định. Mỗi nội dung nghe nhìn Phiên chiếu cho phép người dùng lựa chọn chia sẻ cửa sổ ứng dụng hoặc toàn bộ màn hình.
Ứng dụng của bạn có thể chọn không chia sẻ màn hình ứng dụng bằng cách gọi
Phương thức createScreenCaptureIntent(MediaProjectionConfig)
có đối số MediaProjectionConfig
được trả về từ lệnh gọi đến
createConfigForDefaultDisplay()
.
Lệnh gọi đến createScreenCaptureIntent(MediaProjectionConfig)
bằng
Đối số MediaProjectionConfig
được trả về từ lệnh gọi tới
createConfigForUserChoice()
giống nhau
làm hành vi mặc định, tức là lệnh gọi đến
createScreenCaptureIntent()
.
Ứng dụng có thể thay đổi kích thước
Kích thước ứng dụng chiếu nội dung đa phương tiện phải luôn có thể đổi kích thước (resizeableActivity="true"
). Có thể thay đổi kích thước
các ứng dụng hỗ trợ thay đổi cấu hình thiết bị và chế độ nhiều cửa sổ (xem
Hỗ trợ nhiều cửa sổ).
Nếu không thể đổi kích thước, ứng dụng phải truy vấn ranh giới hiển thị qua một cửa sổ
ngữ cảnh và sử dụng getMaximumWindowMetrics()
để truy xuất WindowMetrics
của
khu vực hiển thị tối đa có sẵn cho ứng dụng :
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();
Tài nguyên khác
Để biết thêm thông tin về phép chiếu nội dung đa phương tiện, vui lòng xem nội dung Quay video và phát lại âm thanh.