Android Q contains a new AudioPlaybackCapture API. This API gives apps the ability to copy the audio being played by other apps. This feature is the analog of screen capture, but for audio. The primary use case is for streaming apps that want to capture the audio being played by games.
Note that the capture API does not affect the latency of the app whose audio is being captured.
Building a capture app
For security and privacy, playback capture imposes some limitations. To be able to capture audio, an app must meet these requirements:
- The app must have the
- The app must bring up the prompt displayed by
MediaProjectionManager.createScreenCaptureIntent(), and the user must approve it.
- The capturing and playing apps must be in the same user profile.
AudioPlaybackCaptureConfiguration.Builder.build()to build an
- Pass the configuration to the
Constraining capture by audio content
An app can limit which audio it can capture by using these methods:
- Pass an
AUDIO_USAGEto AudioPlaybackCaptureConfiguration.addMatchingUsage() to permit capturing a specific usage. Call the method multiple times to specify more than one usage.
- Pass an
AUDIO_USAGEto AudioPlaybackCaptureConfiguration.excludeUsage() to forbid capturing that usage. Call the method multiple times to specify more than one usage.
- Pass a UID to AudioPlaybackCaptureConfiguration.addMatchingUid() to only capture apps with a specific UID. Call the method multiple times to specify more than one UID.
- Pass a UID to AudioPlaybackCaptureConfiguration.excludeUid() to forbid capturing that UID. Call the method multiple times to specify more than one UID.
Note that you cannot use the
together. You must choose one or the other. Likewise, you cannot use
at the same time.
Allowing playback capture
You can configure an app to prevent other apps from capturing its audio. The audio coming from an app can be captured only if the app meets these requirements:
The player's capture policy must be
which allows other apps to capture playback. This can be done in a number of ways:
- To enable capture on all players, include
android:allowAudioPlaybackCapture="true"in the app's
- You can also enable capture on all players by calling
- You can set the policy on an individual player when you build it using
AudioAttributes.Builder.setAllowedCapturePolicy(AudioAttributes.ALLOW_CAPTURE_BY_ALL). (If you are using
If these prerequisites are met, any audio produced by the player can be captured.
Disabling system capture
The protections permitting capture described above apply only to apps. Android
system components ignore these constraints and can capture playback by default.
Many of these components are customized by Android vendors and support features
like accessibility and captioning. For this reason it is recommended that apps
allow the system to capture their playback. In the rare case when you do not
want the system to capture your app's playback, set the capture policy to
Setting policy at runtime
You can call
AudioManager.setAllowedCapturePolicy() to change the capture
policy while an app is running. If a MediaPlayer or AudioTrack is playing
when you call the method, the audio is not affected. You must close and reopen
the player or track for the policy change to take effect.
Policy = manifest + AudioManager + AudioAttributes
Since the capture policy can be specified in several places, it's important
to understand how the effective policy is determined.
The most restrictive capture policy is always applied. For example, an app whose
setAllowedCapturePolicy="false" will never permit non-system
apps to capture its audio, even if
AudioManager#setAllowedCapturePolicy is set
ALLOW_CAPTURE_BY_ALL. Similarly, if the
AudioManager#setAllowedCapturePolicy is set to
ALLOW_CAPTURE_BY_ALL and the
setAllowedCapturePolicy="true", but the media player's
AudioAttributes were built with
this media player will not be capturable by non-system apps.
The table below summarizes the effect of the manifest attribute and the effective policy:
|true||any app||system only||no capture|
|false||system only||system only||no capture|