电视上的多任务处理

Android 14 (API level 34) 为 画中画 (PiP) API 引入了某些增强功能,以允许多任务处理。虽然 PiP 支持是在 Android 8.0 (API level 26) 中引入的,但它在 Android TV 上并未得到广泛支持,并且在 Android 13 之前在 Google TV 上根本不支持。电视多任务处理使用 PiP 模式允许两个独立的应用在屏幕上共存:一个以全屏模式运行,另一个以 PiP 模式运行。在这些模式下运行的应用有不同的要求。

默认行为是 PiP 应用覆盖全屏应用。这与标准 Android 画中画 行为非常相似。

请注意,在集成多任务处理时,您的应用必须在 使用类型 中声明其 符合电视应用质量指南

在 PiP 模式下运行您的应用

对于运行 Android 14 (API level 34) 或更高版本的电视设备,通过调用 enterPictureInPictureMode() 在 PiP 模式下运行您的应用。运行早期版本的 Android 的电视设备不支持 PiP 模式。

以下是如何实现进入 PiP 模式按钮的逻辑的示例

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 的一般用途的信息。

与以 PiP 模式运行的应用共存

当您的应用以全屏模式运行时,可能需要适应其他以 PiP 模式运行的应用。

保持清晰的 API

在某些情况下,PiP 应用可能会覆盖全屏应用中的重要 UI 组件。为了缓解这种情况,有一些保持清晰的 API,应用可以使用它们来识别不应被覆盖的关键 UI 组件。系统尝试满足这些请求,以避免通过重新定位 PiP 窗口来覆盖这些组件。

Keep-Clear

要指定视图不应被覆盖,请在您的 XML 布局中使用 preferKeepClear,如下例所示

<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 原生 UI 的 UI,例如 Flutter、Jetpack Compose 和 WebView,可能需要保持某些区域清晰。此 API 可用于这些情况。

使用类型

您的应用必须声明一个 元数据值属性,即 com.google.android.tv.pip.category,它对应于画中画模式的主要使用类型或类型。任何设置了 android:supportsPictureInPicture="true"<activity> 应该使用下表中的相关值声明此属性。

不属于这些类别中的任何使用类型,特别是任何媒体内容的播放,在电视上的画中画模式下都不允许。

描述
"communication" 通信用例,例如视频或语音通话。
"smartHome" 智能家居集成,例如联网门铃或婴儿监视器。
"health" 健康用例,例如健身追踪或健康监测。
"ticker" 跑马灯用例,例如实时体育比分或新闻和股票跑马灯。

多个值用竖线 (|) 分隔。例如

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