تعدد المهام على التلفزيون

يقدّم نظام Android 14 (المستوى 34 لواجهة برمجة التطبيقات) بعض التحسينات على واجهات برمجة التطبيقات الخاصة بوضع نافذة ضمن النافذة (PiP) لتنفيذ عدة مهام في الوقت نفسه. على الرغم من أنّ هذه الميزة أصبحت متاحة في نظام التشغيل Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات)، لم تكن متاحة على نطاق واسع على Android TV، ولم تكن متاحة على الإطلاق على Google TV قبل الإصدار 13 من نظام التشغيل Android. تستخدِم ميزة "تعدّد المهام" على التلفزيون وضع PiP للسماح بتشغيل تطبيقَين منفصلَين على الشاشة في الوقت نفسه: أحدهما في وضع ملء الشاشة، والآخر في وضع "نافذة ضمن النافذة". يجب استيفاء متطلبات مختلفة للتطبيقات التي تعمل في أيٍّ من هذين الوضعين.

في الإعداد التلقائي، يظهر تطبيق "نافذة ضمن النافذة" فوق التطبيق الذي يملأ الشاشة،، وهو يشبه إلى حد كبير الإعداد التلقائي لميزة "نافذة ضمن النافذة" في Android.

يُرجى العِلم أنّه عند دمج ميزة تعدد المهام، يجب أن يوضّح تطبيقك أنواع الاستخدام وفقًا لإرشادات جودة تطبيقات البث التلفزيوني.

تشغيل تطبيقك في وضع "نافذة ضمن النافذة"

بالنسبة إلى أجهزة التلفزيون التي تعمل بالإصدار 14 من Android (المستوى 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.

واجهات برمجة تطبيقات keep-clear

في بعض الحالات، قد يعرض تطبيق PiP طبقة فوق عناصر مهمة في واجهة المستخدم ضمن تطبيق ملء الشاشة. ولتجنّب ذلك، تتوفّر واجهات برمجة التطبيقات keep-clear التي تتيح للتطبيقات تحديد عناصر واجهة المستخدم المهمة التي يجب عدم تغطيتها. يحاول النظام الاستجابة للطلبات لتجنُّب تغطية هذه المكوّنات من خلال إعادة ضبط موضع نافذة PiP.

تحديد موضع نافذة "نافذة ضمن النافذة" لتجنُّب تغطية عناصر واجهة المستخدم المهمة
الشكل 1 ضبط موضع نافذة 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، أقسامًا فرعية تحتاج إلى إبقاء مناطقها واضحة. يمكن استخدام واجهة برمجة التطبيقات هذه في هذه الحالات.

أنواع الاستخدام

يجب أن يحدّد تطبيقك سمة قيمة البيانات الوصفية بقيمةcom.google.android.tv.pip.category تتوافق مع النوع الأساسي أو أنواع الاستخدام لوضع PiP. يجب أن يحدّد أي <activity> تم ضبط android:supportsPictureInPicture="true" له هذه السمة مع قيمة ذات صلة من الجدول التالي.

لا يُسمح باستخدام أنواع لا تنتمي إلى أي من هذه الفئات، وخاصةً أي تشغيل لمحتوى وسائط، في وضع "نافذة ضمن النافذة" على التلفزيون.

القيمة الوصف
"communication" حالات استخدام الاتصالات، مثل مكالمات الفيديو أو المكالمات الصوتية
"smartHome" عمليات الدمج مع منزل مزوّد بأجهزة ذكية، مثل أجراس الأبواب المتصلة أو أجهزة مراقبة الأطفال
"health" حالات الاستخدام المتعلقة بالصحة، مثل تتبُّع اللياقة البدنية أو مراقبة الصحة
"ticker" حالات استخدام شريط الأخبار، مثل نتائج المباريات الرياضية المباشرة أو شريط الأخبار والأسهم

يتم فصل القيم المتعددة بشريط عمودي (|). على سبيل المثال:

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