نافذة ضمن النافذة

تتيح ميزة "نافذة ضمن النافذة" (PIP) لأجهزة Android الجوّالة للمستخدمين تغيير حجم تطبيق يتضمّن نشاطًا مستمرًا إلى نافذة صغيرة. تُعدّ ميزة "نافذة ضمن النافذة" مفيدة بشكل خاص لتطبيقات الفيديو لأنّ المحتوى يستمر في التشغيل بينما يمكن للمستخدم تنفيذ إجراءات أخرى. يمكن للمستخدمين التحكّم في موضع هذه النافذة من خلال SystemUI والتفاعل مع التطبيق المعروض حاليًا في وضع "نافذة ضمن النافذة" باستخدام (ما يصل إلى ثلاثة) إجراءات يوفّرها التطبيق.

تتطلّب ميزة "نافذة ضمن النافذة" موافقة صريحة من التطبيقات التي تتيحها، وتعمل على أساس كل نشاط على حدة. (يمكن أن يتضمّن تطبيق واحد أنشطة متعددة، ولكن يمكن عرض نشاط واحد فقط في وضع "نافذة ضمن النافذة"). تطلب الأنشطة فتح النوافذ باستخدام وضع "نافذة ضمن النافذة" من خلال استدعاء enterPictureInPictureMode()، وتتلقّى عمليات معاودة الاتصال الخاصة بالنشاط في شكل onPictureInPictureModeChanged().

تتيح طريقة setPictureInPictureParams() للأنشطة التحكّم في نسبة العرض إلى الارتفاع أثناء عرضها في وضع "نافذة ضمن النافذة" وفي الإجراءات المخصّصة التي تتيح للمستخدمين التفاعل مع النشاط بدون الحاجة إلى توسيعه. في وضع "نافذة ضمن النافذة"، يكون النشاط في حالة إيقاف مؤقت، ولكن يتم عرضه، ولا يتلقّى مباشرةً إدخال اللمس أو تركيز النافذة. يمكن عرض مهمة واحدة فقط في وضع "نافذة ضمن النافذة" في كل مرة.

تتوفّر معلومات إضافية في مستندات وضع "نافذة ضمن النافذة" على موقع "مطوّرو تطبيقات Android".

متطلبات الأجهزة

لاستخدام ميزة "نافذة ضمن النافذة"، فعِّل ميزة النظام PackageManager#FEATURE_PICTURE_IN_PICTURE في /android/frameworks/base/core/java/android/content/pm/PackageManager.java. يجب أن تتضمّن الأجهزة التي تتوافق مع ميزة "نافذة ضمن النافذة" شاشة أكبر من 220 وحدة بكسل مستقلة الكثافة في أصغر عرض لها. وعلى غرار ميزة النوافذ المتعددة في وضع تقسيم الشاشة، تتيح ميزة "نافذة ضمن النافذة" تشغيل أنشطة متعددة على الشاشة في الوقت نفسه. لذلك، يجب أن تتوفّر في الأجهزة سعة كافية من وحدة المعالجة المركزية وذاكرة الوصول العشوائي لدعم حالة الاستخدام هذه.

التنفيذ

تتم إدارة معظم مراحل نشاط التطبيق في النظام بين ActivityManager وWindowManager. يتم تنفيذ واجهة المستخدم المرجعية في حزمة SystemUI.

يجب ألا تؤثر التعديلات التي يتم إجراؤها على النظام في سلوكه الأساسي على النحو المحدّد في اختبارات مجموعة أدوات اختبار التوافق (CTS). تتمحور منطق النظام في وضع "نافذة ضمن النافذة" بشكل أساسي حول إدارة المهام والأنشطة في الحزمة "المثبّتة". في ما يلي نظرة عامة سريعة على الصف:

  • ActivityRecord: يتتبّع حالة كل نشاط في وضع "نافذة ضمن النافذة". لمنع المستخدمين من تفعيل وضع "نافذة ضمن النافذة" في ظروف معيّنة، مثل شاشة القفل أو أثناء استخدام الواقع الافتراضي، أضِف حالات إلى checkEnterPictureInPictureState().
  • ActivityManagerService: هي الواجهة الأساسية من النشاط لطلب الدخول إلى وضع "نافذة ضمن النافذة" والواجهة التي تتلقّى طلبات من WindowManager وSystemUI لتغيير حالة نشاط "نافذة ضمن النافذة".
  • ActivityStackSupervisor: تم استدعاؤها من ActivityManagerService لنقل المهام إلى الحزمة المثبّتة أو خارجها، وتعديل WindowManager حسب الحاجة.
  • PinnedStackWindowController: واجهة WindowManager من ActivityManager
  • تعرض PinnedStackController: التغييرات التي تطرأ على النظام إلى SystemUI، مثل عرض/إخفاء طريقة الإدخال، أو تغيير نسبة العرض إلى الارتفاع، أو تغيير الإجراءات.
  • BoundsAnimationController: تحرّك نوافذ نشاط وضع "نافذة ضمن النافذة" بطريقة لا تؤدي إلى تغيير في الإعدادات أثناء تغيير الحجم.
  • PipSnapAlgorithm: فئة مشتركة مستخدَمة في كل من النظام وSystemUI تتحكّم في سلوك المحاذاة لنافذة وضع "الصورة داخل الصورة" بالقرب من حواف الشاشة.

يوفّر المرجع SystemUI عملية تنفيذ كاملة لوضع "نافذة ضمن النافذة" تتيح عرض إجراءات مخصّصة للمستخدمين وإجراءات عامة، مثل التوسيع والإغلاق. يمكن لمصنّعي الأجهزة الاستفادة من هذه التغييرات، شرط ألا تؤثّر في السلوكيات الأساسية المحدّدة في مستند تعريف التوافق. في ما يلي نظرة عامة سريعة على الفئة:

  • استبدِل PipManagerبمكوّن SystemUI الذي يبدأ بـ SystemUI.
  • PipTouchHandler: معالج اللمس الذي يتحكّم في الإيماءات التي يتم من خلالها التعامل مع وضع "نافذة ضمن النافذة" يتم استخدام هذا الإجراء فقط عندما يكون مستهلك الإدخال في وضع "نافذة ضمن النافذة" نشطًا (راجِع InputConsumerController). ويمكن إضافة إيماءات جديدة هنا.
  • PipMotionHelper: فئة ملائمة تتتبّع موضع وضع "نافذة ضمن النافذة" والمنطقة المسموح بها على الشاشة. يتم إجراء مكالمات من خلال ActivityManagerService لتعديل موضع نافذة العرض أثناء التنقل وحجمها أو تحريكها.
  • يبدأ PipMenuActivityController: نشاطًا يعرض الإجراءات التي يوفّرها النشاط الحالي في وضع "نافذة ضمن النافذة". هذا النشاط هو نشاط تراكب المهام، ويزيل مستهلك الإدخال المتراكب للسماح بأن يكون تفاعليًا.
  • PipMenuActivity: يمثّل هذا الحقل عملية التنفيذ الخاصة بنشاط القائمة.
  • PipMediaController: المستمع الذي يعدّل SystemUI عند تغيُّر جلسة الوسائط بطريقة قد تؤثّر في الإجراءات التلقائية في وضع "نافذة ضمن النافذة"
  • PipNotificationController: هو أداة التحكّم التي تضمن بقاء الإشعار نشطًا أثناء استخدام المستخدم لميزة "نافذة ضمن النافذة".
  • PipDismissViewController: هي الطبقة التي تظهر للمستخدمين عند بدء التفاعل مع وضع "نافذة ضمن النافذة" للإشارة إلى أنّه يمكن إغلاقها.

موضع الإعلان التلقائي

تتوفّر العديد من موارد النظام التي تتحكّم في الموضع التلقائي لنافذة "وضع الصورة داخل الصورة":

  • config_defaultPictureInPictureGravity: عدد صحيح يمثّل موضع الجاذبية، ويتحكّم في الزاوية التي سيتم وضع نافذة "الصورة في الصورة" فيها، مثل BOTTOM|RIGHT.
  • config_defaultPictureInPictureScreenEdgeInsets: الإزاحات من جوانب الشاشة لوضع نافذة وضع "الصورة داخل الصورة"
  • config_pictureInPictureDefaultSizePercent وconfig_pictureInPictureDefaultAspectRatio: تتحكّم مجموعة نسبة عرض الشاشة إلى ارتفاعها ونسبة العرض إلى الارتفاع في حجم نافذة وضع "الصورة داخل الصورة". يجب ألا يقل حجم وضع "نافذة ضمن النافذة" التلقائي المحسوب عن @dimen/default_minimal_size_pip_resizable_task، كما هو محدّد في اختبار التوافق مع نظام التشغيل (CTS) ووثيقة تعريف التوافق (CDD).
  • استبدِل config_pictureInPictureSnapMode بسلوك المحاذاة كما هو محدّد في PipSnapAlgorithm.

يجب ألا تغيّر عمليات تنفيذ الأجهزة الحد الأدنى والحد الأقصى لنسبة العرض إلى الارتفاع المحدّدة في مستند تعريف التوافق ومجموعة اختبارات التوافق.

الأذونات

يتيح خيار "عملية التطبيق" (OP_PICTURE_IN_PICTURE) لكل حزمة في AppOpsManager (main/core/java/android/app/AppOpsManager.java) للمستخدمين التحكّم في ميزة "نافذة ضمن النافذة" على مستوى كل تطبيق من خلال إعدادات النظام. يجب أن تراعي عمليات تنفيذ الأجهزة هذا التحقّق عندما يطلب أحد الأنشطة الدخول إلى وضع "نافذة ضمن النافذة".

الاختبار

لاختبار عمليات تنفيذ ميزة "نافذة ضمن النافذة"، شغِّل جميع الاختبارات ذات الصلة بهذه الميزة والموجودة في اختبارات CTS من جهة المضيف ضمن /cts/hostsidetests/services/activitymanager، وخاصةً في ActivityManagerPinnedStackTests.java.