Mit den in Android 5 (API-Level 21) eingeführten android.media.projection
APIs kannst du den Inhalt einer Geräteanzeige als Medienstream erfassen, den du abspielen, aufnehmen oder auf andere Geräte wie Fernseher streamen kannst.
Mit Android 14 (API-Level 34) wird die App-Bildschirmfreigabe eingeführt. Damit können Nutzer unabhängig vom Fenstermodus ein einzelnes App-Fenster statt des gesamten Gerätebildschirms teilen. Bei der App-Bildschirmfreigabe sind Statusleiste, Navigationsleiste, Benachrichtigungen und andere Elemente der System-UI vom gemeinsam genutzten Bildschirm ausgeschlossen – auch dann, wenn die App-Bildschirmfreigabe verwendet wird, um eine App im Vollbildmodus aufzunehmen. Nur die Inhalte der ausgewählten App werden geteilt.
Die App-Bildschirmfreigabe sorgt für Datenschutz, steigert die Produktivität der Nutzer und verbessert das Multitasking, da Nutzer mehrere Apps ausführen können, die Freigabe von Inhalten aber auf eine einzige App beschränkt ist.
Drei Displaydarstellungen
Eine Medienprojektion erfasst den Inhalt eines Gerätedisplays oder App-Fensters und projiziert das aufgenommene Bild auf einen virtuellen Bildschirm, der das Bild auf einem Surface
rendert.
Die Anwendung stellt die Surface
über MediaRecorder
, SurfaceTexture
oder ImageReader
bereit, die den Inhalt des aufgenommenen Displays nutzt und es dir ermöglicht, auf dem Surface
gerenderte Bilder in Echtzeit zu verwalten. Sie können die Bilder als Aufnahme speichern
oder auf einen Fernseher oder ein anderes Gerät streamen.
Echte Displayanzeige
Starten Sie eine Sitzung zur Medienprojektion. Rufen Sie dazu ein Token ab, mit dem Ihre App den Inhalt der Geräteanzeige oder des App-Fensters erfassen kann. Das Token wird durch eine Instanz der Klasse MediaProjection
dargestellt.
Verwenden Sie die Methode getMediaProjection()
des Systemdienstes MediaProjectionManager
, um beim Starten einer neuen Aktivität eine MediaProjection
-Instanz zu erstellen. Starten Sie die Aktivität mit einem Intent aus der Methode createScreenCaptureIntent()
, um einen Bildschirmerfassungsvorgang anzugeben:
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());
Virtuelles Display
Das Herzstück einer Medienprojektion ist die virtuelle Anzeige, die Sie erstellen, indem Sie auf einer MediaProjection
-Instanz createVirtualDisplay()
aufrufen:
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);
Die Parameter width
und height
geben die Abmessungen der virtuellen Anzeige an. Werte für Breite und Höhe kannst du mit den WindowMetrics
APIs erhalten, die in Android 11 (API-Level 30) eingeführt wurden. Weitere Informationen finden Sie im Abschnitt Größe der Medienprojektion.
Surface
Passen Sie die Größe der Projektionsfläche an, um die Ausgabe in der richtigen Auflösung zu produzieren. Gestalten Sie die Oberfläche für das Streamen von Bildschirmen auf Fernseher oder Computerbildschirme groß (niedrige Auflösung) und klein (hohe Auflösung) für die Aufzeichnung des Gerätebildschirms.
Ab Android 12L (API-Level 32) skaliert das System beim Rendern erfasster Inhalte auf der Oberfläche den Inhalt gleichmäßig unter Beibehaltung des Seitenverhältnisses, sodass beide Abmessungen des Inhalts (Breite und Höhe) gleich oder kleiner als die entsprechenden Abmessungen der Oberfläche sind. Der aufgenommene Inhalt wird dann auf der Oberfläche zentriert.
Der Skalierungsansatz von Android 12L verbessert die Bildschirmübertragung auf Fernsehgeräte und andere große Bildschirme, indem die Größe des Oberflächenbilds maximiert und gleichzeitig das richtige Seitenverhältnis sichergestellt wird.
Berechtigung für Dienste im Vordergrund
Wenn Ihre App auf Android 14 oder höher ausgerichtet ist, muss das App-Manifest eine Berechtigungserklärung für den Diensttyp mediaProjection
im Vordergrund enthalten:
<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>
Starten Sie den Medienprojektionsdienst mit einem Aufruf von startForeground()
.
Wenn Sie im Aufruf keinen Diensttyp im Vordergrund angeben, wird standardmäßig eine bitweise Ganzzahl der Typen von Diensten im Vordergrund verwendet, die im Manifest definiert sind. Wenn im Manifest keine Diensttypen angegeben sind, gibt das System MissingForegroundServiceTypeException
aus.
Nutzereinwilligung
Ihre App muss vor jeder Sitzung der Medienprojektion die Nutzereinwilligung einholen. Eine Sitzung ist ein einzelner Aufruf von createVirtualDisplay()
. Ein MediaProjection
-Token darf nur einmal für den Aufruf verwendet werden.
Unter Android 14 oder höher gibt die Methode createVirtualDisplay()
ein SecurityException
aus, wenn Ihre App eine der folgenden Aktionen ausführt:
- Übergibt eine von
createScreenCaptureIntent()
zurückgegebeneIntent
-Instanz mehrmals angetMediaProjection()
- Ruft
createVirtualDisplay()
mehrmals in derselbenMediaProjection
-Instanz auf
Größe der Medienprojektion
Eine Medienprojektion kann unabhängig vom Windowing-Modus den gesamten Bildschirm des Geräts oder ein App-Fenster erfassen.
Anfangsgröße
Bei der Medienprojektion im Vollbildmodus muss Ihre App die Größe des Gerätebildschirms bestimmen. Bei der App-Bildschirmfreigabe kann die App die Größe des aufgenommenen Displays erst dann ermitteln, wenn der Nutzer den Aufnahmebereich ausgewählt hat. Die anfängliche Größe einer Medienprojektion entspricht also der Größe des Gerätebildschirms.
Verwenden Sie die Methode WindowManager
getMaximumWindowMetrics()
der Plattform, um ein WindowMetrics
-Objekt für den Gerätebildschirm zurückzugeben, auch wenn sich die Host-App für die Medienprojektion im Mehrfenstermodus befindet und nur einen Teil des Bildschirms einnimmt.
Verwenden Sie für die Kompatibilität bis hin zu API-Level 14 die Methode WindowMetricsCalculator
computeMaximumWindowMetrics()
aus der Jetpack-Bibliothek WindowManager
.
Rufen Sie die Methode WindowMetrics
getBounds()
auf, um die Breite und Höhe des Gerätedisplays zu erhalten.
Größenänderungen
Die Größe der Medienprojektion kann sich ändern, wenn das Gerät gedreht wird oder der Nutzer bei der App-Bildschirmfreigabe ein App-Fenster als Aufnahmebereich auswählt. Die Medienprojektion kann im Letterbox-Format dargestellt werden, wenn der erfasste Inhalt eine andere Größe als die Messwerte für das maximale Fenster hat, die bei der Einrichtung der Medienprojektion ermittelt wurden.
Damit die Medienprojektion für jede erfasste Region und über Geräterotationen hinweg genau mit der Größe des erfassten Inhalts übereinstimmt, verwenden Sie den onCapturedContentResize()
-Callback, um die Größe der Aufnahme anzupassen. Weitere Informationen finden Sie im nachfolgenden Abschnitt Anpassung.
Anpassbare
Ihre App kann die Medienprojektion über die folgenden MediaProjection.Callback
APIs anpassen:
onCapturedContentVisibilityChanged()
: Dadurch kann die Host-App, also die App, die die Medienprojektion gestartet hat, geteilte Inhalte ein- oder ausblenden.Mit diesem Callback können Sie die UI Ihrer App abhängig davon anpassen, ob der erfasste Bereich für den Nutzer sichtbar ist. Wenn Ihre Anwendung beispielsweise für den Nutzer sichtbar ist und den aufgenommenen Inhalt in der Benutzeroberfläche der Anwendung anzeigt und die erfasste Anwendung auch für den Nutzer sichtbar ist (wie durch diesen Callback angegeben), sieht der Nutzer denselben Inhalt zweimal. Verwende den Callback, um die Benutzeroberfläche deiner App zu aktualisieren, um die aufgenommenen Inhalte auszublenden und Layoutbereich in deiner App für andere Inhalte freizugeben.
onCapturedContentResize()
: Ermöglicht der Host-App, die Größe der Medienprojektion auf dem virtuellen Display und der MedienprojektionSurface
basierend auf der Größe des erfassten Anzeigebereichs zu ändern.Wird ausgelöst, wenn sich die Größe des aufgenommenen Inhalts – eines einzelnen App-Fensters oder einer vollständigen Geräteanzeige – ändert (aufgrund der Gerätedrehung oder wenn die erfasste App in einen anderen Windowing-Modus wechselt). Mit dieser API können Sie die Größe des virtuellen Displays und der Oberfläche anpassen. So sorgen Sie dafür, dass das Seitenverhältnis dem erfassten Inhalt entspricht und die Aufnahme nicht im Letterbox-Format dargestellt wird.
Ressourcenwiederherstellung
Ihre App sollte den MediaProjection
onStop()
-Callback registrieren, um die von der App bereitgestellten Ressourcen freizugeben, z. B. die virtuelle Anzeige und die Projektionsoberfläche.
Der Callback wird aufgerufen, wenn die Medienprojektion beendet wird oder wenn der Nutzer keine Einwilligung zum Fortsetzen einer Erfassungssitzung erteilt.
Wenn Ihre App den Callback nicht registriert und der Nutzer der Medienprojektionssitzung nicht zustimmt, lösen createVirtualDisplay()
-Aufrufe IllegalStateException
aus.
Widerrufen
Unter Android 14 oder höher ist die App-Bildschirmfreigabe standardmäßig aktiviert. Bei jeder Sitzung zur Medienprojektion haben Nutzer die Möglichkeit, ein App-Fenster oder den gesamten Bildschirm zu teilen.
Ihre App kann die App-Bildschirmfreigabe deaktivieren. Dazu rufen Sie die Methode createScreenCaptureIntent(MediaProjectionConfig)
mit dem Argument MediaProjectionConfig
auf, das von einem Aufruf an createConfigForDefaultDisplay()
zurückgegeben wird.
Ein Aufruf von createScreenCaptureIntent(MediaProjectionConfig)
mit einem MediaProjectionConfig
-Argument, das von einem Aufruf an createConfigForUserChoice()
zurückgegeben wird, entspricht dem Standardverhalten, d. h. einem Aufruf von createScreenCaptureIntent()
.
Apps mit anpassbarer Größe
Achten Sie darauf, dass die Größe Ihrer Apps zur Projektion von Mediendateien immer angepasst werden kann (resizeableActivity="true"
). Apps mit anpassbarer Größe unterstützen Gerätekonfigurationsänderungen und den Mehrfenstermodus. Weitere Informationen finden Sie unter Unterstützung des Mehrfenstermodus.
Wenn die Größe Ihrer App nicht geändert werden kann, muss sie die Anzeigegrenzen aus einem Fensterkontext abfragen und getMaximumWindowMetrics()
verwenden, um den WindowMetrics
des maximalen Anzeigebereichs abzurufen, der für die App verfügbar ist :
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();
Weitere Informationen
Weitere Informationen zur Medienprojektion finden Sie unter Video- und Audiowiedergabe aufnehmen.