Làm nhiều việc cùng lúc trên TV

Android 14 (cấp độ API 34) giới thiệu một số điểm cải tiến cho các API hình trong hình (PiP) để cho phép thực hiện nhiều tác vụ. Mặc dù tính năng hỗ trợ PIP (Hình trong hình) đã được giới thiệu trong Android 8.0 (cấp độ API 26), nhưng tính năng này không được hỗ trợ rộng rãi trên Android TV và hoàn toàn không được hỗ trợ trên Google TV trước Android 13. Tính năng đa nhiệm cho TV sử dụng chế độ PIP (Hình trong hình) để cho phép hai ứng dụng riêng biệt cùng tồn tại trên màn hình: một ứng dụng chạy ở chế độ toàn màn hình và ứng dụng thứ hai chạy ở chế độ PIP (Hình trong hình). Có nhiều yêu cầu khác nhau đối với các ứng dụng chạy ở một trong hai chế độ này.

Hành vi mặc định là ứng dụng PiP phủ lên ứng dụng toàn màn hình. Điều này giống như hành vi hình trong hình tiêu chuẩn của Android.

Xin lưu ý rằng khi tích hợp tính năng đa nhiệm, ứng dụng của bạn phải khai báo các loại hình thức sử dụng theo Nguyên tắc về chất lượng đối với ứng dụng truyền hình.

Chạy ứng dụng ở chế độ PiP

Đối với các thiết bị TV chạy Android 14 (API cấp 34) trở lên, hãy chạy ứng dụng ở chế độ PiP bằng cách gọi enterPictureInPictureMode(). Các thiết bị TV chạy phiên bản Android cũ hơn không hỗ trợ chế độ PiP.

Sau đây là ví dụ về cách triển khai logic của một nút để chuyển sang chế độ 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);
    }
}

Thao tác này chỉ được thêm nếu thiết bị có tính năng hệ thống FEATURE_PICTURE_IN_PICTURE. Ngoài ra, khi thao tác được kích hoạt, tỷ lệ khung hình của chế độ PiP được đặt để khớp với tỷ lệ khung hình của video đang phát.

Hãy nhớ thêm tiêu đềphụ đề để cung cấp cho người dùng thông tin về mục đích sử dụng chung của PIP này.

Cùng tồn tại với các ứng dụng chạy ở chế độ PiP

Khi chạy dưới dạng ứng dụng toàn màn hình, ứng dụng của bạn có thể cần điều chỉnh để phù hợp với các ứng dụng khác chạy ở chế độ PiP.

API giữ cho vùng hiển thị không bị che khuất

Trong một số trường hợp, ứng dụng PiP có thể phủ lên các thành phần quan trọng của giao diện người dùng trong ứng dụng toàn màn hình. Để giảm thiểu vấn đề này, có các API giữ cho vùng hiển thị không bị che khuất mà ứng dụng có thể sử dụng để xác định các thành phần quan trọng của giao diện người dùng không được phủ lên. Hệ thống cố gắng đáp ứng các yêu cầu để tránh che phủ các thành phần này bằng cách định vị lại cửa sổ PiP.

Keep-Clear

Để chỉ định rằng một chế độ xem không được phủ lên, hãy sử dụng preferKeepClear trong bố cục XML như trong ví dụ sau:

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

Bạn cũng có thể thực hiện việc này theo phương thức lập trình bằng cách sử dụng 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);
}

Có thể có những lúc bạn không cần giữ cho toàn bộ View không bị che khuất mà chỉ cần giữ cho một phần của chế độ xem không bị che khuất. Bạn có thể sử dụng setPreferKeepClearRects() để chỉ định các vùng của View không được phủ lên. Các giao diện người dùng không sử dụng View một cách tự nhiên, chẳng hạn như Flutter, Jetpack Compose và WebView, có thể có các phần phụ cần giữ cho vùng hiển thị không bị che khuất. Bạn có thể sử dụng API này cho những trường hợp đó.

Các loại hình thức sử dụng

Ứng dụng của bạn phải khai báo thuộc tính giá trị siêu dữ liệu của com.google.android.tv.pip.category tương ứng với loại hoặc các loại hình thức sử dụng chính cho chế độ hình trong hình. Mọi <activity> đã đặt android:supportsPictureInPicture="true" đều phải khai báo thuộc tính này bằng một giá trị thích hợp trong bảng bên dưới.

Các loại hình thức sử dụng không thuộc bất kỳ danh mục nào trong số này, đặc biệt là mọi hoạt động phát nội dung nghe nhìn, đều không được phép ở chế độ hình trong hình trên TV.

Giá trị Mô tả
"communication" Các trường hợp sử dụng thông tin liên lạc, chẳng hạn như cuộc gọi video hoặc cuộc gọi thoại.
"smartHome" Các tính năng tích hợp nhà thông minh, chẳng hạn như chuông cửa có kết nối hoặc thiết bị theo dõi trẻ em.
"health" Các trường hợp sử dụng sức khoẻ, chẳng hạn như theo dõi việc luyện tập thể chất hoặc theo dõi sức khoẻ.
"ticker" Các trường hợp sử dụng bảng tin, chẳng hạn như tỷ số thể thao trực tiếp hoặc bảng tin tức và chứng khoán.

Nhiều giá trị được phân tách bằng dấu gạch đứng (|). Ví dụ:

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