API-интерфейсы android.media.projection , представленные в Android 5 (уровень API 21), позволяют захватывать содержимое экрана устройства в виде медиапотока, который можно воспроизводить, записывать или транслировать на другие устройства, например, телевизоры.
В Android 14 (уровень API 34) появилась функция совместного использования экрана приложения, которая позволяет пользователям делиться окном одного приложения, а не всем экраном устройства, независимо от режима оконного отображения. Совместное использование экрана приложения исключает из общего отображения строку состояния, панель навигации, уведомления и другие элементы системного интерфейса — даже если совместное использование экрана приложения используется для захвата приложения в полноэкранном режиме. Передаётся только содержимое выбранного приложения.
Совместное использование экрана приложения обеспечивает конфиденциальность пользователя, повышает его производительность и улучшает многозадачность, позволяя запускать несколько приложений, но ограничивая совместное использование контента только одним приложением.
Три варианта отображения
Проекция медиаконтента захватывает содержимое экрана устройства или окна приложения, а затем проецирует захваченное изображение на виртуальный дисплей, который отображает изображение на устройстве Surface .

Surface . Приложение предоставляет доступ к Surface через MediaRecorder , SurfaceTexture или ImageReader , которые обрабатывают содержимое захваченного экрана и позволяют управлять изображениями, отображаемыми на Surface в режиме реального времени. Вы можете сохранять изображения в виде записи или транслировать их на телевизор или другое устройство.
Реальный дисплей
Для начала сеанса проекции мультимедиа получите токен, который предоставляет вашему приложению возможность захватывать содержимое экрана устройства или окна приложения. Токен представлен экземпляром класса MediaProjection .
Используйте метод getMediaProjection() системной службы MediaProjectionManager для создания экземпляра MediaProjection при запуске новой активности. Запустите активность с помощью интента из метода createScreenCaptureIntent() , чтобы указать операцию захвата экрана:
Котлин
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];
ActivityResultLauncherstartMediaProjection = registerForActivityResult( new StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK) { mediaProjection[0] = mediaProjectionManager .getMediaProjection(result.getResultCode(), result.getData()); } } );
startMediaProjection.launch(mediaProjectionManager.createScreenCaptureIntent());
Виртуальный дисплей
Центральным элементом медиапроекции является виртуальный дисплей, который создается путем вызова метода createVirtualDisplay() для экземпляра MediaProjection :
Котлин
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);
Параметры width и height определяют размеры виртуального дисплея. Для получения значений ширины и высоты используйте API WindowMetrics , представленный в Android 11 (уровень API 30). (Подробнее см. раздел « Размер проекции мультимедиа» .)
Поверхность
Измените размер проекционной поверхности для получения изображения с соответствующим разрешением. Сделайте поверхность большой (с низким разрешением) для трансляции на телевизоры или компьютерные мониторы и маленькой (с высоким разрешением) для записи на экран устройства.
Начиная с Android 12L (уровень API 32), при отображении захваченного контента на поверхности система масштабирует контент равномерно, сохраняя соотношение сторон, так что оба размера контента (ширина и высота) равны или меньше соответствующих размеров поверхности. Затем захваченный контент центрируется на поверхности.
В Android 12L используется подход масштабирования, улучшающий трансляцию изображения на телевизоры и другие большие дисплеи за счет максимизации размера изображения при сохранении правильного соотношения сторон.
Разрешение для службы переднего плана
Если ваше приложение ориентировано на Android 14 или выше, манифест приложения должен включать объявление разрешения для типа службы переднего плана mediaProjection :
<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>
Запустите службу проекции мультимедиа, вызвав метод startForeground() .
Если в вызове не указан тип службы переднего плана, по умолчанию используется побитовое целое число из типов служб переднего плана, определенных в манифесте. Если в манифесте не указаны никакие типы служб, система выдает исключение MissingForegroundServiceTypeException .
Согласие пользователя
Ваше приложение должно запрашивать согласие пользователя перед каждым сеансом проекции медиаконтента. Сеанс представляет собой один вызов функции createVirtualDisplay() . Для выполнения этого вызова необходимо использовать токен MediaProjection только один раз.
В Android 14 и более поздних версиях метод createVirtualDisplay() генерирует исключение SecurityException если ваше приложение выполняет одно из следующих действий:
- Передает экземпляр
Intent, возвращенный функциейcreateScreenCaptureIntent()в функциюgetMediaProjection()более одного раза. - Вызов функции
createVirtualDisplay()происходит более одного раза для одного и того же экземпляраMediaProjection
размер проекции медиа
Проекция мультимедиа может захватывать весь экран устройства или окно приложения независимо от режима отображения окна.
Начальный размер
При полноэкранной проекции мультимедиа ваше приложение должно определить размер экрана устройства. При совместном использовании экрана приложение не сможет определить размер захватываемого экрана, пока пользователь не выберет область захвата. Таким образом, начальный размер любой проекции мультимедиа равен размеру экрана устройства.
Используйте метод getMaximumWindowMetrics() из класса WindowManager , чтобы получить объект WindowMetrics для экрана устройства, даже если приложение для проекции мультимедиа находится в многооконном режиме, занимая лишь часть экрана.
Для обеспечения совместимости с API уровня 14 используйте метод computeMaximumWindowMetrics() из библиотеки Jetpack WindowManager , реализующий интерфейс WindowMetricsCalculator .
Вызовите метод getBounds() класса WindowMetrics , чтобы получить ширину и высоту экрана устройства.
Изменения размера
Размер проекции медиаконтента может изменяться при повороте устройства или выборе пользователем окна приложения в качестве области захвата при демонстрации экрана приложения. Проекция медиаконтента может быть с черными полосами сверху и снизу, если размер захваченного контента отличается от максимальных размеров окна, заданных при настройке проекции.
Чтобы обеспечить точное соответствие проекции медиаконтента размеру захваченного изображения для любой захваченной области и при поворотах устройств, используйте функцию обратного вызова onCapturedContentResize() для изменения размера захваченного изображения. (Дополнительную информацию см. в разделе «Настройка» ниже).
Настройка
Ваше приложение может настраивать пользовательский интерфейс проекции медиаконтента с помощью следующих API-функций MediaProjection.Callback :
onCapturedContentVisibilityChanged(): Позволяет хост-приложению (приложению, запустившему проекцию мультимедиа) отображать или скрывать общий контент.Используйте этот коллбэк для настройки пользовательского интерфейса вашего приложения в зависимости от того, видна ли пользователю захваченная область. Например, если ваше приложение видно пользователю и отображает захваченный контент в пользовательском интерфейсе приложения, и захваченное приложение также видно пользователю (как указано в этом коллбэке), пользователь увидит один и тот же контент дважды. Используйте коллбэк для обновления пользовательского интерфейса вашего приложения, чтобы скрыть захваченный контент и освободить место в макете приложения для другого контента.
onCapturedContentResize(): Позволяет хост-приложению изменять размер проекции мультимедиа на виртуальном дисплее иSurfaceпроекции мультимедиа в зависимости от размера захваченной области отображения.Этот API срабатывает всякий раз, когда размер захваченного контента — отдельного окна приложения или всего экрана устройства — изменяется (из-за поворота устройства или перехода захваченного приложения в другой оконный режим). Используйте этот API для изменения размера как виртуального экрана, так и поверхности, чтобы гарантировать соответствие соотношения сторон захваченного контента и отсутствие черных полос по краям.
Восстановление ресурсов
Ваше приложение должно зарегистрировать функцию обратного вызова onStop() MediaProjection , чтобы получать уведомления о завершении сеанса проекции мультимедиа и его недействительности. После завершения сеанса ваше приложение должно освободить удерживаемые ресурсы, такие как виртуальный дисплей и проекционная поверхность. Остановленный сеанс проекции мультимедиа больше не может создавать новый виртуальный дисплей, даже если ваше приложение ранее не создавало виртуальный дисплей для этой проекции мультимедиа.
Система вызывает функцию обратного вызова при завершении проекции медиафайлов. Это завершение может произойти по нескольким причинам, например:
- Пользователь останавливает сессию, используя пользовательский интерфейс приложения или индикатор состояния медиапроекции системы.
- Экран блокируется
- Начинается очередной сеанс медиапроекции
- Процесс приложения завершен.
Если ваше приложение не регистрирует функцию обратного вызова, любой вызов createVirtualDisplay() вызовет исключение IllegalStateException .
Уклоняться
В Android 14 и более поздних версиях функция демонстрации экрана приложений включена по умолчанию. В каждом сеансе проекции мультимедиа пользователям предоставляется возможность демонстрировать либо окно приложения, либо весь экран.
Ваше приложение может отказаться от демонстрации экрана, вызвав метод createScreenCaptureIntent(MediaProjectionConfig) с аргументом MediaProjectionConfig , возвращаемым из вызова createConfigForDefaultDisplay() .
Вызов функции createScreenCaptureIntent(MediaProjectionConfig) с аргументом MediaProjectionConfig , возвращаемым вызовом функции createConfigForUserChoice() , аналогичен поведению по умолчанию, то есть вызову функции createScreenCaptureIntent() .
Приложения с изменяемым размером
Всегда делайте приложения для проекции мультимедиа масштабируемыми ( resizeableActivity="true" ). Масштабируемые приложения поддерживают изменение конфигурации устройства и многооконный режим (см. раздел «Поддержка многооконного режима »).
Если ваше приложение не поддерживает изменение размера, оно должно запрашивать границы отображения из контекста окна и использовать getMaximumWindowMetrics() для получения WindowMetrics максимальной области отображения, доступной приложению:
Котлин
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();
Индикатор состояния и автоматическая остановка
Screen projection exploits expose private user data such as financial information because users don't realize their device screen is being shared.
For apps running on devices with Android 15 QPR1 or higher, a status bar chip that is large and prominent alerts users to any in‑progress screen projection. Users can tap the chip to stop their screen from being shared, cast, or recorded. Also, screen projection automatically stops when the device screen is locked.

Проверьте наличие значка индикатора состояния проекции мультимедиа, запустив демонстрацию экрана, трансляцию или запись. Значок должен отобразиться в строке состояния.
Чтобы гарантировать освобождение ресурсов и обновление пользовательского интерфейса вашего приложения при остановке проекции экрана в результате взаимодействия пользователя с индикатором состояния или активации экрана блокировки, выполните следующие действия:
Создайте экземпляр класса
MediaProjection.Callback.Реализуйте метод
onStop(), который вызывается при остановке проекции экрана. Освободите все ресурсы, которые удерживает ваше приложение, и обновите пользовательский интерфейс приложения по мере необходимости.
Чтобы проверить работу функции обратного вызова, коснитесь значка в строке состояния или заблокируйте экран устройства, чтобы остановить проекцию экрана. Убедитесь, что метод onStop() вызывается и ваше приложение реагирует должным образом.
Дополнительные ресурсы
Для получения дополнительной информации о проекции медиафайлов см. раздел «Захват воспроизведения видео и аудио» .