As APIs de projeção de mídia introduzidas no Android 5 (nível 21 da API) permitem capturar o conteúdo da tela de um dispositivo como um stream de mídia que pode ser reproduzido, gravado ou transmitido para outros dispositivos, como TVs.
Uma projeção de mídia envolve três representações da tela do dispositivo:

Surface
fornecida pelo
aplicativo.
Uma projeção de mídia captura o conteúdo de uma tela do dispositivo e, em seguida, projeta
a imagem capturada em uma tela virtual que renderiza a imagem em uma
Surface
.
O aplicativo fornece a Surface
usando uma
SurfaceView
ou um
ImageReader
, que consomem
o conteúdo da tela capturada. O
OnImageAvailableListener
de um ImageReader
permite gerenciar imagens renderizadas na Surface
em tempo real. Salve as imagens como uma gravação ou as transmita para uma TV ou
outro dispositivo.
MediaProjection
Inicie uma sessão de projeção de mídia usando um token que conceda ao app a
capacidade de capturar o conteúdo da tela, o áudio do dispositivo ou ambos. O token é
representado por uma instância da
classe
MediaProjection
. É possível criar uma instância dessa classe ao iniciar uma nova atividade.
Abordagem legada
Para acessar um token de projeção de mídia usando a abordagem legada, chame
startActivityForResult()
com uma intent retornada do método
createScreenCaptureIntent()
do serviço do sistema
MediaProjectionManager
:
Kotlin
startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION)
Java
startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
A chamada mostra uma caixa de diálogo de confirmação informando ao usuário que a projeção de mídia captura todas as informações exibidas, incluindo informações confidenciais ou de identificação pessoal.
Se o usuário confirmar, o método startActivityForResult()
vai transmitir um código
de resultado e os dados para o
callback
onActivityResult()
.
Você pode transmitir os dados e o código de resultado ao
método getMediaProjection()
do MediaProjectionManager
para criar uma instância da MediaProjection
:
Kotlin
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, resultData)
Java
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, resultData);
Abordagem recomendada
A abordagem recomendada para acessar um token de projeção de mídia usa APIs da biblioteca Jetpack Activity:
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()); } } );
Tela virtual
O centro de uma projeção de mídia é a tela virtual, que é criada
chamando o método
createVirtualDisplay()
em uma instância 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);
Os parâmetros width
e height
especificam a largura e a altura da
tela virtual. Para usar valores que correspondam à largura e altura da projeção
de mídia, use as APIs WindowMetrics
introduzidas no Android 11 (nível 30 da API).
WindowMetrics
Uma projeção de mídia captura toda a tela, independente do app que cria a projeção estar em execução em tela cheia ou no modo de várias janelas.
Para ver as dimensões de uma projeção de mídia, use o método
WindowManager#getMaximumWindowMetrics()
,
que retorna um objeto
WindowMetrics
para a exibição em tela
cheia, mesmo que o app de projeção de mídia esteja no modo de várias janelas, ocupando
apenas parte da tela.
Para compatibilidade com o nível 14 da API e mais recentes, use o método
WindowMetricsCalculator#computeMaximumWindowMetrics()
da biblioteca Jetpack WindowManager.
Chame o método WindowMetrics#getBounds()
para acessar a largura e a altura corretas da tela virtual da projeção de mídia
(consulte Tela virtual).
Sempre crie apps de projeção de mídia que podem ser redimensionados. Os apps redimensionáveis oferecem suporte a mudanças de configuração de dispositivos e do modo de várias janelas. Consulte Suporte a várias janelas.
Se o app não for redimensionável, ele precisará consultar os limites da tela em um contexto de janela
e extrair as WindowMetrics
da área máxima disponível da tela
para o app usando o método WindowManager#getMaximumWindowMetrics()
:
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();
Superfície
É necessário dimensionar a superfície da projeção de mídia para produzir a saída na resolução pretendida. Aumente o tamanho (baixa resolução) para a transmissão da tela em TVs ou monitores de computador e diminua (alta resolução) para a gravação da tela do dispositivo.
A partir do 12L (API de nível 32), quando o sistema renderiza uma tela virtual na
plataforma, ele a dimensiona para caber na plataforma usando um processo
parecido com a opção
centerInside
da ImageView
.
A nova abordagem de dimensionamento melhora a transmissão de tela para televisões e outras telas grandes, maximizando o tamanho da imagem da plataforma e garantindo a proporção adequada.
Recomendações
Para ter os melhores resultados com a projeção de mídia, siga estas recomendações:
- Torne seu app redimensionável. Os apps redimensionáveis oferecem suporte a mudanças de configuração
do dispositivo e do modo de várias janelas. Consulte
Suporte a várias janelas. No manifesto
do app, defina
resizeableActivity="true"
. No Android 7.0 (nível 24 da API) ou versões mais recentes, essa configuração é verdadeira por padrão. - Ative seus apps para oferecer suporte a orientações de paisagem e retrato, porque as duas orientações são comuns em smartphones, tablets e formatos dobráveis.
- Use
WindowManager#getMaximumWindowMetrics()
para acessar os limites de uma projeção de mídia. Para compatibilidade com o nível 14 da API e mais recentes, use o Jetpack WindowManager. Consulte a seção WindowMetrics. - Se o app não for redimensionável, extraia os limites de projeção de mídia de um contexto de janela. Consulte a seção WindowMetrics.
Outros recursos
Para saber mais sobre projeção de mídia, consulte Capturar reproduções de vídeo e áudio.