android.media.projection
Interfejsy API wprowadzone w Androidzie 5 (poziom API 21) umożliwiają przechwytywanie treści
wyświetlacza urządzenia jako strumienia multimediów, na który można odtwarzać, nagrywać lub przesyłać
na innych urządzeniach, takich jak telewizory.
Android 14 (poziom interfejsu API 34) wprowadza udostępnianie ekranu aplikacji, udostępniać okno aplikacji zamiast całego ekranu urządzenia niezależnie od tego, w trybie okien. Udostępnianie ekranu aplikacji nie obejmuje paska stanu, paska nawigacyjnego, powiadomień i innych elementów interfejsu systemu ze wspólnego wyświetlacza – nawet gdy udostępnianie ekranu aplikacji jest używane do przechwytywania jej na pełnym ekranie. Udostępniana jest tylko zawartość wybranej aplikacji.
Udostępnianie ekranu aplikacji zapewnia prywatność użytkowników, zwiększa produktywność usprawnia wielozadaniowość, umożliwiając użytkownikom uruchamianie wielu aplikacji, udostępnianie treści tylko w jednej aplikacji.
Trzy sposoby wyświetlania
W ramach wyświetlania multimediów rejestruje się zawartość wyświetlacza urządzenia lub okna aplikacji
a następnie rzutuje zarejestrowany obraz na wyświetlacz wirtualny, na którym jest on wyświetlany
Surface
.
Aplikacja udostępnia Surface
za pomocą
MediaRecorder
,
SurfaceTexture
lub
ImageReader
, która zużywa
treści na przechwyconym ekranie i umożliwia zarządzanie wyrenderowanymi obrazami
na urządzeniu Surface
w czasie rzeczywistym. Możesz zapisać obrazy jako nagranie lub przesyłanie
na telewizor lub inne urządzenie.
Prawdziwa reklama displayowa
Rozpocznij sesję wyświetlania multimediów, uzyskując token, który przyzna Twojej aplikacji
możliwość rejestrowania zawartości wyświetlacza urządzenia lub okna aplikacji. Token
jest reprezentowana przez wystąpienie
MediaProjection
zajęcia.
Użyj metody getMediaProjection()
do
usługa systemowa MediaProjectionManager
, aby utworzyć instancję MediaProjection
gdy rozpoczynasz nową aktywność. Rozpocznij aktywność od intencji z
Metoda createScreenCaptureIntent()
określająca ekran
operacja przechwytywania:
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());
Wyświetlacz wirtualny
Podstawą wyświetlania multimediów jest wyświetlacz wirtualny,
Połączenie
createVirtualDisplay()
w instancji 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);
Parametry width
i height
określają wymiary obiektu wirtualnego
wyświetlacz. Aby uzyskać wartości szerokości i wysokości, użyj funkcji
Wprowadzone interfejsy API WindowMetrics
w Androidzie 11 (poziom API 30). (Aby dowiedzieć się więcej, zobacz
Rozmiar wyświetlania multimediów).
Natynkowe
Dobierz odpowiedni rozmiar powierzchni projekcji multimediów, i ich rozwiązania. Ustaw dużą powierzchnię (niską rozdzielczość), aby umożliwić przesyłanie ekranu na telewizory. z małymi monitorami (w wysokiej rozdzielczości) do nagrywania na wyświetlaczu urządzenia.
Od Androida 12L (poziom interfejsu API 32) w przypadku renderowania przechwyconych treści system równomiernie skaluje treści z zachowaniem współczynnika proporcji. aby oba wymiary treści (szerokość i wysokość) były równe lub mniejsze niż analogiczne wymiary powierzchni. Przechwycona zawartość jest następnie jest wyśrodkowany na powierzchni.
Skalowanie Androida 12L poprawia przesyłanie ekranu na telewizory na innych dużych ekranach, maksymalizując rozmiar obrazu powierzchni, jednocześnie z odpowiednim współczynnikiem proporcji.
Uprawnienia usługi na pierwszym planie
Jeśli Twoja aplikacja jest kierowana na Androida 14 lub nowszego, plik manifestu musi zawierać
deklaracja uprawnień dla
mediaProjection
Typ usługi na pierwszym planie:
<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>
Uruchom usługę wyświetlania multimediów, wywołując metodę startForeground()
.
Jeśli w wywołaniu nie określisz typu usługi na pierwszym planie, domyślnie zostanie wybrany typ
do bitowej liczby całkowitej typów usług na pierwszym planie zdefiniowanych w pliku manifestu. Jeśli
w pliku manifestu nie określono żadnych typów usług, system generuje
MissingForegroundServiceTypeException
Zgoda użytkownika
Twoja aplikacja musi prosić użytkownika o zgodę przed każdą sesją wyświetlania multimediów. O
sesja to pojedyncze wywołanie do funkcji createVirtualDisplay()
. Token MediaProjection
należy użyć tylko raz w celu nawiązania połączenia.
W Androidzie 14 lub nowszym metoda createVirtualDisplay()
generuje błąd
SecurityException
, jeśli
wykonuje jedną z tych czynności:
- Przekazuje instancję
Intent
zwrócona zcreateScreenCaptureIntent()
dogetMediaProjection()
więcej niż raz - Dzwoni do
createVirtualDisplay()
więcej niż raz w tym samym urządzeniuMediaProjection
instancja
Rozmiar wyświetlania multimediów
W ramach wyświetlania multimediów można rejestrować cały wyświetlacz urządzenia lub okno aplikacji bez względu na tryb okna.
Rozmiar początkowy
W przypadku wyświetlania multimediów na pełnym ekranie aplikacja musi określić rozmiar ekranu urządzenia. Podczas udostępniania ekranu aplikacji aplikacja nie jest w stanie określić wielkości wyświetlanego obrazu do czasu, aż użytkownik wybierze region przechwytywania. Początkowy rozmiar każdego projekcji multimediów jest więc rozmiarem ekranu urządzenia.
Skorzystaj z platformy WindowManager
metody getMaximumWindowMetrics()
, która zwraca
WindowMetrics
dla
ekranu urządzenia, nawet jeśli aplikacja hostująca wyświetlanie multimediów działa w trybie wielu okien.
zajmuje tylko część ekranu.
Aby uzyskać zgodność do poziomu interfejsu API 14, użyj interfejsu WindowMetricsCalculator
computeMaximumWindowMetrics()
z biblioteki Jetpack WindowManager
.
Wywołaj metodę WindowMetrics
getBounds()
, aby uzyskać szerokość i wysokość wyświetlacza urządzenia.
Zmiany rozmiaru
Rozmiar projekcji multimediów może się zmieniać, gdy obrócisz urządzenie lub użytkownik wybiera okno aplikacji jako region zrzutu ekranu podczas udostępniania ekranu aplikacji. Na obrazie mogą być widoczne czarne pasy, jeśli przechwycony materiał jest rozmiar inny niż maksymalne wskaźniki okna uzyskane, gdy – skonfigurowano projekcję.
Aby projekcja multimediów była dokładnie dopasowana do
dla dowolnego przechwyconego regionu i obrotu urządzenia, użyj
onCapturedContentResize()
wywołanie zwrotne w celu zmiany rozmiaru zapisu. (Więcej
więcej informacji znajdziesz w sekcji Dostosowywanie poniżej).
Dostosowywanie
Aplikacja może dostosować środowisko wyświetlania multimediów za pomocą tych opcji:
Interfejsy API MediaProjection.Callback
:
onCapturedContentVisibilityChanged()
: Umożliwia wyświetlanie lub wyświetlanie w aplikacji hostującej (aplikacji, która rozpoczęła wyświetlanie multimediów) ukryć udostępnioną treść.To wywołanie zwrotne pozwala dostosować interfejs aplikacji zależnie od tego, czy przechwycony region jest widoczny dla użytkownika. Jeśli na przykład Twoja aplikacja jest widoczna dla: użytkownika i wyświetla przechwyconą zawartość w interfejsie aplikacji, przechwycona aplikacja jest również widoczna dla użytkownika (zgodnie z tym wywołania zwrotnego), użytkownik zobaczy tę samą treść dwukrotnie. Aby zaktualizować, użyj wywołania zwrotnego UI aplikacji, aby ukryć zapisane treści i zwolnić miejsce w przypadku innych treści.
onCapturedContentResize()
: Pozwala aplikacji hostującej zmieniać rozmiar projekcji multimediów w środowisku wirtualnym i wyświetlanie multimediówSurface
w zależności od rozmiaru przechwyconych region wyświetlania.Wywoływane za każdym razem, gdy przechwycona zawartość – pojedyncze okno aplikacji lub pełne wyświetlacz urządzenia – zmienia rozmiar (pod wpływem obrotu urządzenia lub przejście w inny tryb okna). Za pomocą tego interfejsu API możesz zmienić rozmiar wirtualnego wyświetlacza i powierzchni, aby zapewnić zgodność współczynnika proporcji na zdjęciu nie ma czarnych pasów bądź zdjęcie.
Odzyskiwanie zasobów
Aplikacja powinna rejestrować MediaProjection
onStop()
.
wywołanie zwrotne, aby otrzymać informację, kiedy sesja wyświetlania multimediów zostanie zatrzymana i staje się
jest nieprawidłowa. Po zatrzymaniu sesji aplikacja powinna zwolnić zasoby, które
takich jak wirtualny wyświetlacz i powierzchnia projekcji. Zatrzymano A
w trakcie sesji wyświetlania multimediów nie można już utworzyć nowego wyświetlacza wirtualnego,
aplikacja nie utworzyła wcześniej wyświetlacza wirtualnego dla tego projekcji multimediów.
Wywołanie zwrotne jest wywoływane po zakończeniu wyświetlania multimediów, ponieważ użytkownik ręcznie zatrzymasz sesję lub system zatrzyma ją z jakiegoś powodu.
Jeśli aplikacja nie zarejestruje wywołania zwrotnego, każde wywołanie createVirtualDisplay()
rzuty
IllegalStateException
Zrezygnuj
Android 14 lub nowszy włącza udostępnianie ekranu aplikacji domyślnie. Każdy plik multimedialny sesja projekcji umożliwia użytkownikom udostępnienie okna aplikacji lub cały ekran.
Możesz zrezygnować z udostępniania ekranu aplikacji, wywołując metodę
Metoda createScreenCaptureIntent(MediaProjectionConfig)
z argumentem MediaProjectionConfig
zwróconym z wywołania do
createConfigForDefaultDisplay()
.
Połączenie z numerem createScreenCaptureIntent(MediaProjectionConfig)
i
Zwrócono MediaProjectionConfig
argument z wywołania do
createConfigForUserChoice()
jest identyczne
jako domyślne działanie, czyli wywołanie
createScreenCaptureIntent()
Aplikacje z możliwością zmiany rozmiaru
Zawsze zmieniaj rozmiar aplikacji do wyświetlania multimediów (resizeableActivity="true"
). Możliwość zmiany rozmiaru
aplikacje obsługują zmiany w konfiguracji urządzenia oraz tryb wielu okien (patrz
Obsługa wielu okien).
Jeśli aplikacji nie można zmienić, musi ona wysyłać zapytania do granic wyświetlania z poziomu okna
i użyj polecenia getMaximumWindowMetrics()
, aby pobrać WindowMetrics
maksymalny obszar wyświetlania dostępny dla aplikacji :
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();
Dodatkowe materiały
Więcej informacji na temat wyświetlania multimediów znajdziesz w artykule Nagrywanie dźwięku i obrazu.