Многозадачность на телевизоре

В Android 14 (уровень API 34) улучшены API для режима картинка в картинке, чтобы пользователям было удобнее работать в режиме многозадачности. Хотя поддержка режима "картинка в картинке" была введена в Android 8.0 (уровень API 26), она не получила широкого распространения на Android TV и вообще не поддерживалась на Google TV до Android 13. Многозадачность на телевизоре использует режим PiP, чтобы два отдельных приложения могли сосуществовать на экране: одно работает в полноэкранном режиме, а второе – в режиме PiP. Для каждого из этих режимов действуют разные требования.

Режим работы по умолчанию заключается в том, что приложение в режиме "картинка в картинке" накладывается на полноэкранное приложение. Это очень похоже на стандартный режим картинка в картинке в Android.

Обратите внимание, что при интеграции многозадачности ваше приложение должно объявить свои типы использования в соответствии с рекомендациями по обеспечению качества ТВ-приложений.

Как запустить приложение в режиме "Картинка в картинке"

На телевизорах с Android 14 (уровень API 34) или более поздней версии запустите приложение в режиме "Картинка в картинке", вызвав enterPictureInPictureMode(). Телевизоры с более ранними версиями Android не поддерживают режим "Картинка в картинке".

Ниже приведен пример реализации логики кнопки для перехода в режим "Картинка в картинке".

Kotlin

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    pictureInPictureButton.visibility =
        if (requireActivity().packageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
            pictureInPictureButton.setOnClickListener {
                val aspectRatio = Rational(view.width, view.height)
                val params = PictureInPictureParams.Builder()
                    .setAspectRatio(aspectRatio)
                    .build()
                val result = requireActivity().enterPictureInPictureMode(params)
            }
            View.VISIBLE
        } else {
            View.GONE
        }
}

Java

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    if (requireActivity().getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
        pictureInPictureButton.setVisibility(View.VISIBLE);
        pictureInPictureButton.setOnClickListener(v -> {
            Rational aspectRatio = new Rational(view.getWidth(), view.getHeight());
            PictureInPictureParams params = new PictureInPictureParams.Builder()
                    .setAspectRatio(aspectRatio)
                    .setTitle("My Streaming App")
                    .setSubtitle("My On-Demand Content")
                    .build();
            Boolean result = requireActivity().enterPictureInPictureMode(params);
        });
    } else {
        pictureInPictureButton.setVisibility(View.GONE);
    }
}

Действие добавляется, только если на устройстве есть системная функция FEATURE_PICTURE_IN_PICTURE. Кроме того, при запуске действия соотношение сторон в режиме "Картинка в картинке" устанавливается в соответствии с соотношением сторон воспроизводимого видео.

Обязательно добавьте заголовок и подзаголовок, чтобы пользователь понимал, для чего используется этот PIP.

Сосуществование с приложениями, работающими в режиме "картинка в картинке".

Если ваше приложение работает в полноэкранном режиме, оно может адаптироваться к другим приложениям, работающим в режиме PiP.

API для свободных зон

В некоторых случаях приложение в режиме "картинка в картинке" может перекрывать важные компоненты интерфейса полноэкранного приложения. Чтобы этого избежать, можно использовать API, которые позволяют указать, какие компоненты интерфейса не должны перекрываться. Система пытается выполнить запросы, чтобы избежать перекрытия этих компонентов, перемещая окно PiP.

Размещение окна в режиме "картинка в картинке" так, чтобы оно не закрывало важные элементы интерфейса.
Рисунок 1. Расположите окно "Картинка в картинке" так, чтобы оно не закрывало важные элементы интерфейса.

Чтобы указать, что представление не должно перекрываться, используйте preferKeepClear в макете XML, как в следующем примере:

<TextView
    android:id="@+id/important_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:preferKeepClear="true"
    android:text="@string/app_name"/>

Вы также можете сделать это программно с помощью setPreferKeepClear():

Kotlin

private lateinit var binding: MyLayoutBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    binding = MyLayoutBinding.inflate(layoutInflater)
    setContentView(binding.root)
    binding.importantText.isPreferKeepClear = true
}

Java

private MyLayoutBinding binding;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    binding = MyLayoutBinding.inflate(getLayoutInflater());
    setContentView(binding.getRoot());
    binding.importantText.setPreferKeepClear(true);
}

Иногда вам может потребоваться очистить не всю View, а только ее часть. С помощью свойства setPreferKeepClearRects() можно указать, какие области View не должны перекрываться. В интерфейсах, где не используются нативные элементы View, например Flutter, Jetpack Compose и WebView, могут быть подразделы, в которых нужно оставить свободные области. Этот API можно использовать в таких случаях.

Типы использования

В приложении необходимо объявить атрибут значения метаданных com.google.android.tv.pip.category, который соответствует основному типу или типам использования режима "картинка в картинке". Любой элемент <activity>, для которого задан атрибут android:supportsPictureInPicture="true", должен объявлять этот атрибут с соответствующим значением из таблицы ниже.

Типы использования, которые не попадают ни в одну из этих категорий, в частности любое воспроизведение медиаконтента, не разрешены в режиме "картинка в картинке" на телевизорах.

Значение Описание
"communication" Примеры взаимодействия, такие как видео- или голосовые вызовы.
"smartHome" Интеграция с умным домом, например подключение дверных звонков или радионянь.
"health" Приложения для здоровья, например для отслеживания физической активности или состояния здоровья.
"ticker" Бегущие строки, например с результатами спортивных матчей, новостями или котировками акций.

Несколько значений разделяются вертикальной чертой (|). Пример:

<meta-data android:name="com.google.android.tv.pip.category" android:value="smartHome|health" />