Meta Quest 的媒体投影 API 经用户同意,Meta Quest 允许应用使用
Android 媒体投影 API 访问头戴设备上显示的视频和设备音频。此 API 旨在启用远程投屏、直播和屏幕共享体验。
此 API 的工作方式与其在基础 Android 中的方式几乎相同,因此在常规 Android 设备上使用 API 的现有代码也可以在 Meta Quest 上运行。
您在使用媒体投影 API 时必须始终遵守
开发者数据使用政策 以及所有适用的 Oculus 和 Meta 政策、条款和条件。
在 Meta Quest 上,应用只能根据我们的政策和守则,且不得出于其他目的,使用媒体投影 API 启用投屏、直播或屏幕共享功能。
用户必须同意应用访问用户在头戴设备中看到和听到的内容。媒体投影 API 受到口令的保护。应用必须先获得该口令,才能执行视频或音频采集。要获得该口令,您的应用必须启动 MediaProjectionPermissionActivity,才能向用户请求采集屏幕的权限。用户将看到一个对话框,如果用户接受对话框,系统将提供媒体投影口令。
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());
媒体投影视频拍摄 API 通过接受
Android 表面 来运作。Horizon 操作系统将使用屏幕内容填充该表面。该 API 还会返回
VirtualDisplay 对象。在基础 Android 中,屏幕内容会投影到
VirtualDisplay 上,然后
Surface 会被该
VirtualDisplay 填充。但是,在 Horizon 操作系统中,表面会直接被我们自己的合成器填充。详情请见下文的
API 差异 版块。
Surface 需要由客户端应用创建,该应用还负责连接
Surface 的消费者端。然后,应用可以通过
createVirtualDisplay 方法将
Surface 传递到媒体投影 API。此操作将连接生产者端,用屏幕内容填充表面。
以下展示了如何从 Android 文档调用此方法:
virtualDisplay = mediaProjection.createVirtualDisplay(
"ScreenCapture",
width,
height,
screenDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
surface,
null, null);
Android 不允许同时进行多个媒体投影采集。因此,每当另一个应用请求并获得媒体投影口令时,任何现有的媒体投影会话都会结束。原来的应用会通过
媒体投影回调 收到通知。
您的应用必须处理系统结束媒体投影会话的情况。您必须通过回调和注册 来正确地结束媒体投影会话和清理任何资源。 此 API 在 Horizon 操作系统中的实现方式的主要差异是,返回的 VirtualDisplay 对象实际上并没有填充表面。也就是说,在返回的 VirtualDisplay 上调用 resize 方法不会产生与基础 Android 中一样的行为。
图像在表面上的缩放也由 XrRuntime 内的自定义合成器处理,这意味着
此版块 中介绍的缩放/宽银幕行为可能并不准确。
使音频静音实际上并不会使传入系统的音频静音,这是一个已知的问题。目前,可以通过将播放器的 AudioUsage 属性设为 AUDIO_UNKNOWN 来修复这个问题。因此,如果您希望应用的音频采集能够实现音频静音,则不应在 AudioPlaybackCaptureConfiguration 中添加 AudioAttributes.USAGE_UNKNOWN 属性。