应用程序可以录制从另一个应用程序播放的视频或音频。此类应用程序必须正确处理 MediaProjection
令牌。本页介绍了如何操作。它还展示了设备管理员如何禁用录制任何屏幕快照的功能,以及音频应用程序如何防止其他应用程序录制其播放的内容。
如何处理 MediaProjection
令牌
MediaProjection
API 允许应用程序获取 MediaProjection
令牌,该令牌使他们能够一次性访问以捕获屏幕内容或音频。Android 操作系统会在将令牌授予您的应用程序之前向用户征求其许可。
操作系统在快速设置 UI 中显示活动的 MediaProjection
令牌,并允许用户随时撤销对令牌的访问权限。当这种情况发生时,与会话关联的虚拟显示或音频流将停止接收媒体流。您的应用必须做出适当的响应,否则它将继续录制静音音频或黑色视频流。
为了处理令牌丢失,请使用 registerCallback
方法在 MediaProjection
实例上注册回调,并在调用 onStop
方法时停止录制。
有关更多信息,请参阅 媒体投影。
捕获视频
请参阅 ScreenCapture 示例应用,了解如何使用 Media Projection API 实时捕获设备屏幕并在 SurfaceView 上显示。
您可以使用 DevicePolicyManager
来阻止屏幕录制。对于企业帐户(Android for Work),管理员可以使用 setScreenCaptureDisabled 方法禁用工作资料的助理数据收集。
代码实验室 无需应用管理 Android 设备 展示了如何禁止截图。
捕获音频播放
Android 10 中引入了 AudioPlaybackCapture API。此 API 使应用能够复制其他应用播放的音频。此功能类似于屏幕捕获,但适用于音频。主要用例是希望捕获游戏播放的音频的流媒体应用。
请注意,AudioPlaybackCapture API 不会影响正在捕获其音频的应用的延迟。
构建捕获应用
出于安全和隐私考虑,播放捕获施加了一些限制。为了能够捕获音频,应用必须满足以下要求
- 应用必须具有
RECORD_AUDIO
权限。 - 应用必须显示
MediaProjectionManager.createScreenCaptureIntent()
显示的提示,并且用户必须批准它。 - 捕获应用和播放应用必须位于相同的用户资料中。
要捕获来自另一个应用的音频,您的应用必须构建一个 AudioRecord
对象,并向其中添加一个 AudioPlaybackCaptureConfiguration
。请按照以下步骤操作
- 调用
AudioPlaybackCaptureConfiguration.Builder.build()
来构建一个AudioPlaybackCaptureConfiguration
。 - 通过调用
setAudioPlaybackCaptureConfig
将配置传递给AudioRecord
。
控制音频捕获
您的应用可以控制它可以录制的内容类型以及哪些其他类型的应用可以录制其自己的播放。
通过音频内容限制捕获
应用可以使用以下方法限制它可以捕获的音频
- 将
AUDIO_USAGE
传递给 AudioPlaybackCaptureConfiguration.addMatchingUsage() 以允许捕获特定用途。多次调用此方法以指定多个用途。 - 将
AUDIO_USAGE
传递给 AudioPlaybackCaptureConfiguration.excludeUsage() 以禁止捕获该用途。多次调用此方法以指定多个用途。 - 将 UID 传递给 AudioPlaybackCaptureConfiguration.addMatchingUid() 以仅捕获具有特定 UID 的应用。多次调用此方法以指定多个 UID。
- 将 UID 传递给 AudioPlaybackCaptureConfiguration.excludeUid() 以禁止捕获该 UID。多次调用此方法以指定多个 UID。
请注意,您不能将 addMatchingUsage()
和 excludeUsage()
方法一起使用。您必须选择其中一个。同样,您不能同时使用 addMatchingUid()
和 excludeUid()
。
通过其他应用限制捕获
您可以配置应用以阻止其他应用捕获其音频。只有当应用满足以下要求时,才能捕获来自应用的音频
用途
生成音频的播放器必须 设置其用途 为 USAGE_MEDIA
、USAGE_GAME
或 USAGE_UNKNOWN
。
捕获策略
播放器的捕获策略必须为 AudioAttributes.ALLOW_CAPTURE_BY_ALL
,允许其他应用捕获播放。这可以通过多种方式实现
- 要在所有播放器上启用捕获,请在应用的
manifest.xml
文件中包含android:allowAudioPlaybackCapture="true"
。 - 您还可以通过调用
AudioManager.setAllowedCapturePolicy(AudioAttributes.ALLOW_CAPTURE_BY_ALL)
来在所有播放器上启用捕获。 - 您可以在构建单个播放器时使用
AudioAttributes.Builder.setAllowedCapturePolicy(AudioAttributes.ALLOW_CAPTURE_BY_ALL)
设置其策略。(如果您使用的是AAudio
,请调用AAudioStreamBuilder_setAllowedCapturePolicy(AAUDIO_ALLOW_CAPTURE_BY_ALL)
。)
如果满足这些先决条件,则可以捕获播放器生成的任何音频。
禁用系统捕获
上面描述的允许捕获的保护措施仅适用于应用。Android 系统组件默认情况下可以捕获播放。其中许多组件由 Android 供应商定制,并支持辅助功能和字幕等功能。因此,建议应用允许系统捕获其播放。在极少数情况下,如果您不希望系统捕获应用的播放,请将捕获策略设置为 ALLOW_CAPTURE_BY_NONE
。
在运行时设置策略
您可以在应用运行时调用 AudioManager.setAllowedCapturePolicy()
来更改捕获策略。如果您在调用该方法时正在播放 MediaPlayer 或 AudioTrack,则音频不会受到影响。您必须关闭并重新打开播放器或轨道才能使策略更改生效。
策略 = 清单 + AudioManager + AudioAttributes
由于可以在多个地方指定捕获策略,因此了解有效策略是如何确定的非常重要。始终应用最严格的捕获策略。例如,清单中包含 setAllowedCapturePolicy="false"
的应用永远不会允许非系统应用捕获其音频,即使 AudioManager#setAllowedCapturePolicy
设置为 ALLOW_CAPTURE_BY_ALL
。类似地,如果 AudioManager#setAllowedCapturePolicy
设置为 ALLOW_CAPTURE_BY_ALL
并且清单设置了 setAllowedCapturePolicy="true"
,但媒体播放器的 AudioAttributes
使用 AudioAttributes.Builder#setAllowedCapturePolicy(ALLOW_CAPTURE_BY_SYSTEM)
构建,则此媒体播放器将无法被非系统应用捕获。
下表总结了清单属性和有效策略的影响
allowAudioPlaybackCapture | ALLOW_CAPTURE_BY_ALL | ALLOW_CAPTURE_BY_SYSTEM | ALLOW_CAPTURE_BY_NONE |
---|---|---|---|
true | 任何应用 | 仅系统 | 不捕获 |
false | 仅系统 | 仅系统 | 不捕获 |