Реализация Picture-in-Picture режима для Android-приложения

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1735 услуг
Реализация Picture-in-Picture режима для Android-приложения
Средний
~2-3 дня
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    495

Реализация Picture-in-Picture режима для Android-приложения

PiP на Android появился в API 26 (Android 8.0) и за несколько версий заметно эволюционировал. На Android 12+ появились автоматический PiP при свайпе домой и seamless resize. Но базовые ошибки при реализации — те же: Activity не восстанавливается корректно, управляющие кнопки не работают, видео зависает после выхода из PiP.

Включение PiP

В AndroidManifest.xml для Activity:

<activity
    android:name=".VideoActivity"
    android:supportsPictureInPicture="true"
    android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation" />

configChanges — критично. Без этого при входе в PiP Activity пересоздаётся (onDestroy → onCreate), видео прерывается.

Вход в PiP — через enterPictureInPictureMode:

override fun onUserLeaveHint() {
    // автоматически при нажатии Home — API 26+
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val params = PictureInPictureParams.Builder()
            .setAspectRatio(Rational(16, 9))
            .build()
        enterPictureInPictureMode(params)
    }
}

На Android 12+ (API 31): setAutoEnterEnabled(true) в PictureInPictureParams — PiP при свайпе в фон без переопределения onUserLeaveHint. Плюс setSeamlessResizeEnabled(true) для плавного изменения размера окна.

Lifecycle и управление воспроизведением

Когда Activity переходит в PiP, вызывается onPictureInPictureModeChanged. В PiP-режиме UI-контролы должны быть скрыты, плеер должен продолжать воспроизведение.

override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, newConfig: Configuration) {
    super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
    if (isInPictureInPictureMode) {
        videoControlsView.visibility = View.GONE
        // ExoPlayer продолжает играть — ничего не делаем
    } else {
        videoControlsView.visibility = View.VISIBLE
        // пользователь вернулся — восстановить UI
    }
}

Проблема с onResume / onPause: при переходе в PiP вызывается onPause. Если в onPause стоит player.pause() — видео остановится. Проверка isInPictureInPictureMode() в onPause решает это:

override fun onPause() {
    super.onPause()
    if (!isInPictureInPictureMode) {
        player.pause()
    }
}

Кастомные Remote Actions

В PiP-окне можно добавить до 3 кнопок через RemoteAction. Например, «Предыдущий трек», «Пауза», «Следующий трек»:

fun buildPipParams(isPlaying: Boolean): PictureInPictureParams {
    val playPauseIntent = PendingIntent.getBroadcast(
        this, REQUEST_PLAY_PAUSE,
        Intent(ACTION_PLAY_PAUSE),
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )
    val playPauseAction = RemoteAction(
        Icon.createWithResource(this, if (isPlaying) R.drawable.ic_pause else R.drawable.ic_play),
        if (isPlaying) "Пауза" else "Воспроизвести",
        if (isPlaying) "Пауза" else "Воспроизвести",
        playPauseIntent
    )

    return PictureInPictureParams.Builder()
        .setAspectRatio(Rational(16, 9))
        .setActions(listOf(playPauseAction))
        .build()
}

BroadcastReceiver обрабатывает ACTION_PLAY_PAUSE и после обработки обновляет параметры PiP через setPictureInPictureParams для актуализации иконки кнопки.

Видеозвонки и кастомный контент

Для PiP с произвольным View (не только видео) — тот же подход: Activity в PiP-режиме с кастомным layout. Отличие от iOS: на Android нет ограничения «только видеозвонок» — любой контент может быть в PiP. WebRTC, камера, игровой экран — всё работает.

Для WebRTC-видеозвонка: SurfaceViewRenderer из org.webrtc помещается в Activity, при переходе в PiP скрываются контролы вызова, остаётся только видео. EglRenderer продолжает рендеринг в PiP-режиме без изменений.

Частые проблемы

Activity пересоздаётся при PiP. Забытый configChanges в манифесте.

Чёрный экран в PiP при ExoPlayer. SurfaceView иногда не корректно масштабируется в маленьком PiP-окне. Заменить на TextureView через playerView.useController = false и SimpleExoPlayer.setVideoTextureView.

PiP не работает на MIUI / ColorOS. Производители могут ограничивать PiP в своих оболочках. На MIUI нужно отдельное разрешение в настройках приложения. Тестировать на реальных устройствах, не только на эмуляторе.

Сроки

2–3 рабочих дня для стандартной интеграции с ExoPlayer. Кастомные Remote Actions и сложный lifecycle с видеозвонком — до 4–5 дней. Стоимость рассчитывается индивидуально.