Mit den android.media.projection
-APIs, die in Android 5 (API-Level 21) eingeführt wurden, können Sie den Inhalt eines Gerätedisplays als Medienstream erfassen, der auf anderen Geräten wie Fernsehern wiedergegeben, aufgezeichnet oder gestreamt werden kann.
Mit Android 14 (API-Level 34) wird die Bildschirmfreigabe für Apps eingeführt. Nutzer können dann unabhängig vom Fenstermodus ein einzelnes App-Fenster anstelle des gesamten Gerätebildschirms freigeben. Bei der App-Bildschirmfreigabe werden die Statusleiste, die Navigationsleiste, Benachrichtigungen und andere System-UI-Elemente vom freigegebenen Display ausgeschlossen – auch wenn die App-Bildschirmfreigabe verwendet wird, um eine App im Vollbildmodus aufzuzeichnen. Es werden nur die Inhalte der ausgewählten App freigegeben.
Die Bildschirmfreigabe von Apps schützt die Privatsphäre der Nutzer, steigert deren Produktivität und verbessert das Multitasking, da Nutzer mehrere Apps ausführen, die Freigabe von Inhalten jedoch auf eine einzelne App beschränken können.
Drei Displaydarstellungen
Bei einer Medienprojektion wird der Inhalt eines Gerätedisplays oder App-Fensters erfasst und dann auf ein virtuelles Display projiziert, das das Bild auf einem Surface
darstellt.
Die Anwendung stellt dem Surface
über einen MediaRecorder
, SurfaceTexture
oder ImageReader
den Inhalt des erfassten Displays zur Verfügung. So können Sie Bilder, die auf dem Surface
gerendert werden, in Echtzeit verwalten. Sie können die Bilder als Aufnahme speichern oder auf einen Fernseher oder ein anderes Gerät streamen.
Echte Anzeige
Um eine Sitzung zur Projektion von Medieninhalten zu starten, müssen Sie ein Token abrufen, das Ihrer App die Möglichkeit gibt, den Inhalt des Displays oder App-Fensters des Geräts zu erfassen. Das Token wird durch eine Instanz der Klasse MediaProjection
dargestellt.
Verwenden Sie die Methode getMediaProjection()
des Systemdienstes MediaProjectionManager
, um eine MediaProjection
-Instanz zu erstellen, wenn Sie eine neue Aktivität starten. Starten Sie die Aktivität mit einem Intent aus der Methode createScreenCaptureIntent()
, um einen Vorgang zum Aufnehmen des Bildschirms 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 das virtuelle Display, das Sie erstellen, indem Sie createVirtualDisplay()
auf einer MediaProjection
-Instanz 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 des virtuellen Displays an. Verwenden Sie die in Android 11 (API-Level 30) eingeführten APIs WindowMetrics
, um Werte für Breite und Höhe abzurufen. Weitere Informationen finden Sie im Abschnitt Größe der Medienprojektion.
Surface
Größe der Projektionsfläche für Medien festlegen, um eine Ausgabe in der richtigen Auflösung zu erzielen Wählen Sie eine große Oberfläche (niedrige Auflösung) für das Streamen von Inhalten auf Fernseher oder Computermonitore und eine kleine Oberfläche (hohe Auflösung) für die Aufzeichnung des Displays des Geräts.
Ab Android 12L (API-Level 32) skaliert das System beim Rendern aufgenommener Inhalte auf der Oberfläche die Inhalte einheitlich und beibehält dabei das Seitenverhältnis, sodass beide Abmessungen der Inhalte (Breite und Höhe) gleich oder kleiner als die entsprechenden Abmessungen der Oberfläche sind. Die erfassten Inhalte werden dann auf der Oberfläche zentriert.
Mit dem Skalierungsansatz von Android 12L wird das Streamen von Inhalten auf Fernseher und andere große Displays verbessert, indem die Größe des Oberflächenbilds maximiert und gleichzeitig das richtige Seitenverhältnis beibehalten wird.
Berechtigung für Dienste im Vordergrund
Wenn Ihre App auf Android 14 oder höher ausgerichtet ist, muss das App-Manifest eine Berechtigungsdeklaration 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 Medienprojektionsservice mit einem Aufruf von startForeground()
.
Wenn Sie den Typ des Dienstes im Vordergrund nicht im Aufruf angeben, wird standardmäßig eine binäre Ganzzahl der im Manifest definierten Typen von Diensten im Vordergrund verwendet. Wenn im Manifest keine Diensttypen angegeben sind, wirft das System MissingForegroundServiceTypeException
aus.
Nutzereinwilligung
Ihre App muss vor jeder Medienprojektionssitzung die Einwilligung des Nutzers einholen. Eine Sitzung ist ein einzelner Aufruf von createVirtualDisplay()
. Ein MediaProjection
-Token muss nur einmal für den Anruf verwendet werden.
Unter Android 14 oder höher löst die createVirtualDisplay()
-Methode eine SecurityException
aus, wenn Ihre App eine der folgenden Aktionen ausführt:
- Eine
Intent
-Instanz, die voncreateScreenCaptureIntent()
angetMediaProjection()
zurückgegeben wird, wird mehrmals übergeben createVirtualDisplay()
wird mehrmals auf dieselbeMediaProjection
-Instanz aufgerufen
Größe der Medienprojektion
Eine Medienprojektion kann unabhängig vom Fenstermodus das gesamte Display des Geräts oder ein App-Fenster erfassen.
Anfangsgröße
Bei der Medienprojektion im Vollbildmodus muss Ihre App die Größe des Gerätebildschirms ermitteln. Bei der Bildschirmfreigabe in Apps kann Ihre App die Größe des aufgenommenen Displays erst dann bestimmen, wenn der Nutzer den Aufnahmebereich ausgewählt hat. Die anfängliche Größe einer Medienprojektion entspricht also der Größe des Gerätebildschirms.
Verwende die Plattformmethode WindowManager
getMaximumWindowMetrics()
, um ein WindowMetrics
-Objekt für den Gerätebildschirm zurückzugeben, auch wenn die Host-App der Medienprojektion sich im Multifenstermodus befindet und nur einen Teil des Displays belegt.
Für die Kompatibilität bis API-Ebene 14 verwenden Sie 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 abzurufen.
Größenänderungen
Die Größe der Medienprojektion kann sich ändern, wenn das Gerät gedreht wird oder der Nutzer ein App-Fenster als Aufnahmebereich für die Bildschirmfreigabe der App auswählt. Die Medienprojektion wird möglicherweise in Letterbox angezeigt, wenn die erfassten Inhalte eine andere Größe als die maximalen Fenstermesswerte haben, die bei der Einrichtung der Medienprojektion ermittelt wurden.
Damit die Medienprojektion für jede erfasste Region und bei jeder Gerätedrehung genau mit der Größe der erfassten Inhalte übereinstimmt, verwenden Sie den onCapturedContentResize()
-Callback, um die Größe der Aufnahme zu ändern. Weitere Informationen finden Sie im folgenden Abschnitt Anpassen.
Personalisierung
Mit den folgenden MediaProjection.Callback
APIs können Sie die Nutzererfahrung bei der Medienprojektion anpassen:
onCapturedContentVisibilityChanged()
: Mit dieser Option kann die Host-App (die App, die die Medienprojektion gestartet hat) die freigegebenen Inhalte ein- oder ausblenden.Mit diesem Callback können Sie die Benutzeroberfläche Ihrer App anpassen, je nachdem, ob der erfasste Bereich für den Nutzer sichtbar ist. Wenn Ihre App beispielsweise für den Nutzer sichtbar ist und die erfassten Inhalte in der Benutzeroberfläche der App angezeigt werden und die erfasste App auch für den Nutzer sichtbar ist (wie durch diesen Rückruf angegeben), sieht der Nutzer dieselben Inhalte zweimal. Verwenden Sie den Rückruf, um die Benutzeroberfläche Ihrer App zu aktualisieren, um die erfassten Inhalte auszublenden und Layoutplatz in Ihrer App für andere Inhalte freizugeben.
onCapturedContentResize()
: Mit dieser Option kann die Host-App die Größe der Medienprojektion auf dem virtuellen Display und der MedienprojektionSurface
basierend auf der Größe der erfassten Anzeigefläche ändern.Wird ausgelöst, wenn sich die Größe der erfassten Inhalte – ein einzelnes App-Fenster oder das gesamte Display des Geräts – ändert (z. B. durch die Drehung des Geräts oder wenn die erfasste App in einen anderen Fenstermodus wechselt). Mit dieser API können Sie sowohl das virtuelle Display als auch die Oberfläche anpassen, damit das Seitenverhältnis zu den aufgenommenen Inhalten passt und die Aufnahme nicht letterboxed ist.
Ressourcenwiederherstellung
Ihre App sollte den Rückruf MediaProjection
onStop()
registrieren, um benachrichtigt zu werden, wenn die Medienprojektionssitzung beendet und ungültig wird. Wenn die Sitzung beendet wird, sollte Ihre App die von ihr gehaltenen Ressourcen freigeben, z. B. das virtuelle Display und die Projektionsfläche. Nach dem Beenden einer Medienprojektionssitzung kann kein neues virtuelles Display mehr erstellt werden, auch wenn Ihre App zuvor kein virtuelles Display für diese Medienprojektion erstellt hat.
Das System ruft den Callback auf, wenn die Medienprojektion beendet wird. Das kann verschiedene Gründe haben, z. B.:
- der Nutzer die Sitzung über die Benutzeroberfläche der App oder den Status-Bar-Chip für die Medienprojektion des Systems beendet
- das Display gesperrt wird.
- eine weitere Sitzung zur Medienprojektion gestartet wird
- der App-Prozess beendet wird
Wenn Ihre App den Rückruf nicht registriert, wird bei jedem Aufruf von createVirtualDisplay()
die Fehlermeldung IllegalStateException
ausgegeben.
Widerrufen
Unter Android 14 oder höher ist die App-Bildschirmfreigabe standardmäßig aktiviert. Bei jeder Medienprojektionssitzung haben Nutzer die Möglichkeit, ein App-Fenster oder das gesamte Display zu teilen.
Sie können die Bildschirmfreigabe für Ihre App deaktivieren, indem Sie die Methode createScreenCaptureIntent(MediaProjectionConfig)
mit dem Argument MediaProjectionConfig
aufrufen, das von einem Aufruf von createConfigForDefaultDisplay()
zurückgegeben wird.
Ein Aufruf von createScreenCaptureIntent(MediaProjectionConfig)
mit einem MediaProjectionConfig
-Argument, das von einem Aufruf von createConfigForUserChoice()
zurückgegeben wird, entspricht dem Standardverhalten, d. h. einem Aufruf von createScreenCaptureIntent()
.
Größe kann geändert werden
Ihre Apps für die Medienprojektion müssen immer skalierbar sein (resizeableActivity="true"
). Skalierbare Apps unterstützen Gerätekonfigurationsänderungen und den Multifenstermodus (siehe Multifenstermodus unterstützen).
Wenn Ihre App nicht skalierbar ist, muss sie die Displaygrenzen aus einem Fensterkontext abfragen und mit getMaximumWindowMetrics()
die WindowMetrics
des maximalen Displaybereichs abrufen, 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();
Statusleisten-Chip und automatisches Beenden
Bei Ausnutzung von Bildschirmprojektion werden personenbezogene Nutzerdaten wie Finanzinformationen offengelegt, da Nutzer nicht wissen, dass ihr Gerätedisplay geteilt wird.
In Android 15 (API-Level 35) QPR1 wird ein neuer Status-Bar-Chip eingeführt, der groß und gut sichtbar ist. Er soll Nutzer auf eine laufende Bildschirmprojektion aufmerksam machen. Nutzer können auf den Chip tippen, um zu verhindern, dass ihr Bildschirm geteilt, gestreamt oder aufgezeichnet wird.
Unter Android 15 QPR1 und höher wird die Bildschirmprojektion automatisch beendet, wenn das Display des Geräts gesperrt wird.
Weitere Informationen
Weitere Informationen zur Medienprojektion finden Sie unter Video- und Audiowiedergabe erfassen.