В Android 14 (уровень API 34) добавлены улучшения в API режима "Картинка в картинке", которые позволяют выполнять несколько задач одновременно. Режим "Картинка в картинке" появился в Android 8.0 (уровень API 26), но до Android 13 он не поддерживался на Google TV и был доступен не на всех устройствах Android TV. Многозадачность на телевизоре позволяет одновременно использовать два приложения: одно в полноэкранном режиме, а другое – в режиме "картинка в картинке". Для приложений, работающих в этих режимах, действуют разные требования.
По умолчанию приложение с функцией "картинка в картинке" перекрывает полноэкранное приложение. Это похоже на стандартное поведение 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. Кроме того, при запуске действия соотношение сторон мини-проигрывателя устанавливается в соответствии с соотношением сторон воспроизводимого видео.
Обязательно добавьте заголовок и подзаголовок, чтобы пользователь понимал, для чего используется режим "Картинка в картинке".
Совместимость с приложениями, работающими в режиме "Картинка в картинке"
Если ваше приложение работает в полноэкранном режиме, ему может потребоваться адаптироваться к другим приложениям, запущенным в режиме "Картинка в картинке".
API для зон безопасности
В некоторых случаях приложение в режиме "Картинка в картинке" может перекрывать важные элементы интерфейса полноэкранного приложения. Чтобы этого не происходило, существуют API, которые позволяют определить, какие элементы интерфейса нельзя перекрывать. Система пытается выполнить запросы, чтобы избежать перекрытия этих компонентов, перемещая окно PiP.
Чтобы указать, что представление не должно перекрываться, используйте 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" />