API android.media.projection
được giới thiệu trong Android 5 (API cấp 21) cho phép bạn chụp lại nội dung của màn hình thiết bị dưới dạng luồng nội dung đa phương tiện bạn có thể phát lại, quay hoặc truyền sang các thiết bị khác 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ổ là gì. Tính năng chia sẻ màn hình ứng dụng sẽ loại trừ thanh trạng thái, thanh điều hướng, 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 khỏi màn hình dùng chung, ngay cả khi tính năng chia sẻ màn hình ứng dụng được dùng để chụp ứ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ế việc chia sẻ nội dung chỉ trên một ứng dụng duy nhất.
Ba phần đại diện cho màn hình
Tính năng chiếu nội dung đa phương tiện sẽ chụp lại nội dung của màn hình thiết bị hoặc cửa sổ ứng dụng, sau đó chiếu hình ảnh đã chụp lên màn hình ảo để kết xuất hình ảnh đó trên Surface
.
Ứng dụng cung cấp Surface
thông qua MediaRecorder
, SurfaceTexture
hoặc ImageReader
, giúp sử dụng nội dung của màn hình đã chụp và cho phép bạn quản lý hình ảnh 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 vào 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 giúp ứng dụng của bạn có thể chụp lại nội dung trên 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 thực thể của lớp MediaProjection
.
Sử dụng phương thức getMediaProjection()
của dịch vụ hệ thống MediaProjectionManager
để tạo 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 thao tác chụp màn hình:
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 kích thước của màn hình ảo. Để lấy giá trị cho chiều rộng và chiều cao, hãy sử dụng các API WindowMetrics
được giới thiệu trong Android 11 (API cấp 30). (Để biết thông tin chi tiết, vui lòng xem phần Kích thước chiếu nội dung đa phương tiện.)
Bề mặt
Định kích thước bề mặt chiếu nội dung đa phương tiện để tạo đầu ra ở độ phân giải thích hợp. Kích thước bề mặt lớn (độ phân giải thấp) để truyền sang TV hoặc màn hình máy tính và kích thước 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 đã ghi trên nền tảng, hệ thống sẽ đ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 của nội dung (chiều rộng và chiều cao) bằng hoặc nhỏ hơn kích thước tương ứng của nền tảng. Sau đó, nội dung đã chụp sẽ được căn giữa trên nền tảng.
Phương pháp điều chỉnh theo tỷ lệ của Android 12L giúp cải thiện tính năng 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 bao gồm nội dung 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 này sẽ mặc định thành 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 loại dịch vụ nào, hệ thống sẽ gửi 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. Phiên là một lệnh gọi duy nhất đến createVirtualDisplay()
. Bạn chỉ được sử dụng mã thông báo MediaProjection
một lần để thực hiện lệnh gọi.
Trên Android 14 trở lên, phương thức createVirtualDisplay()
sẽ gửi SecurityException
nếu ứng dụng của bạn thực hiện một trong những thao tác sau:
- Truyền một thực thể
Intent
được trả về từcreateScreenCaptureIntent()
đếngetMediaProjection()
nhiều lần - Gọi
createVirtualDisplay()
nhiều lần trên cùng một bản saoMediaProjection
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ế độ cửa sổ.
Kích thước ban đầu
Khi 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 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ị.
Dùng phương thức nền tảng WindowManager
getMaximumWindowMetrics()
để trả về một WindowMetrics
đối tượng cho màn hình thiết bị ngay cả khi phần ứng dụng lưu trữ tính năng chiếu nội dung đa phương tiện chỉ đang ở chế độ hiển thị.
Để tương thích xuống API cấp 14, hãy sử dụng phương thức 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 kích thước
Kích thước của phép chiếu nội dung đa phương tiện có thể thay đổi khi xoay thiết bị hoặc người dùng chọn một cửa sổ ứng dụng làm vùng 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 đã chụp có kích thước khác với chỉ số cửa sổ tối đa thu được khi thiết lập tính năng chiếu nội dung đa phương tiện.
Để đảm bảo phép chiếu nội dung đa phương tiện khớp chính xác với kích thước của nội dung được chụp cho mọi khu vực được chụp và giữa các chế độ 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 khi chiếu nội dung đa phương tiện bằng các API MediaProjection.Callback
sau:
onCapturedContentVisibilityChanged()
: Bật ứng dụng lưu trữ (ứng dụng đã bắt đầu tính năng chiếu nội dung đa phương tiện) để hiện 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 người dùng có nhìn thấy khu vực đã chụp hay không. Ví dụ: nếu người dùng nhìn thấy ứng dụng của bạn và đang cho thấy nội dung được ghi lại trong giao diện người dùng của ứng dụng, đồng thời ứng dụng được chụp cũng hiển thị cho người dùng (như được thể hiện trong lệnh gọi lại này), thì người dùng sẽ thấy cùng một nội dung hai lần. Hãy 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 nhằm ẩn nội dung đã chụp và giải phóng không gian bố cục trong ứng dụng cho nội dung khác.
onCapturedContentResize()
: Cho phép ứng dụng lưu trữ thay đổi kích thước của hình chiếu nội dung đa phương tiện trên màn hình ảo và phép chiếu nội dung đa phương tiệnSurface
dựa trên kích thước của vùng hiển thị đã chụp.Được kích hoạt bất cứ khi nào nội dung được ghi (một cửa sổ ứng dụng hoặc màn hình toàn thiết bị) thay đổi kích thước (do việc xoay thiết bị hoặc ứng dụng đã chụp chuyển sang chế độ cửa sổ khác). Dùng API này để đổi kích thước cả màn hình và giao diện ảo nhằm đảm bảo tỷ lệ khung hình khớp với nội dung đã 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 nên đăng ký lệnh gọi lại MediaProjection
onStop()
để giải phóng các tài nguyên mà ứng dụng giữ, chẳng hạn như màn hình ảo và bề mặt chiếu.
Lệnh gọi lại được gọi khi tính năng chiếu nội dung đa phương tiện kết thúc hoặc khi người dùng không đồng ý để tiếp tục phiên chụp.
Nếu ứng dụng của bạn không đăng ký lệnh gọi lại và người dùng không đồng ý với phiên chiếu nội dung đa phương tiện, thì các lệnh gọi đến createVirtualDisplay()
sẽ gửi IllegalStateException
.
Ngừng
Theo mặc định, Android 14 trở lên sẽ bật tính năng chia sẻ màn hình ứng dụng. Mỗi phiên chiếu nội dung đa phương tiện cho phép người dùng 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 sử dụng tính năng chia sẻ màn hình ứng dụng bằng cách gọi phương thức createScreenCaptureIntent(MediaProjectionConfig)
với đối số MediaProjectionConfig
được trả về từ lệnh gọi đến createConfigForDefaultDisplay()
.
Lệnh gọi đến createScreenCaptureIntent(MediaProjectionConfig)
có đối số MediaProjectionConfig
được trả về từ lệnh gọi đến createConfigForUserChoice()
cũng giống như 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
Hãy luôn làm cho ứng dụng chiếu nội dung đa phương tiện có thể đổi kích thước (resizeableActivity="true"
). Các ứng dụng có thể thay đổi kích thước hỗ trợ thay đổi cấu hình thiết bị và chế độ nhiều cửa sổ (xem phần Hỗ trợ nhiều cửa sổ).
Nếu không thể đổi kích thước, ứng dụng của bạn phải truy vấn các ranh giới hiển thị từ ngữ cảnh cửa sổ 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.