תמונה בתוך תמונה

התכונה 'תמונה בתוך תמונה' (PIP) למכשירי Android ניידים מאפשרת למשתמשים לשנות את הגודל של חלון קטן של אפליקציה עם פעילות מתמשכת. התכונה 'תמונה בתוך תמונה' שימושית במיוחד באפליקציות וידאו, כי התוכן ממשיך לפעול בזמן שהמשתמש יכול לבצע פעולות אחרות. המשתמשים יכולים לשנות את המיקום של החלון הזה דרך SystemUI ולבצע אינטראקציה עם האפליקציה שמוצגת כרגע במצב 'תמונה בתוך תמונה' באמצעות (עד שלוש) פעולות שסופקו על ידי האפליקציה.

כדי להשתמש ב-PIP, צריך להביע הסכמה מפורשת באפליקציות שתומכות בו, והוא פועל על בסיס כל פעילות בנפרד. (לאפליקציה אחת יכולות להיות כמה פעילויות, אבל רק אחת מהן יכולה להיות במצב PIP). הבקשה להפעלת תמונה בתוך תמונה מתבצעת על ידי קריאה ל-enterPictureInPictureMode(), והפעילויות מקבלות קריאות חוזרות (callback) בצורה של onPictureInPictureModeChanged().

השיטה setPictureInPictureParams() מאפשרת לפעילויות לשלוט ביחס הגובה-רוחב שלהן כשהן מוצגות בתצוגת PIP, וגם בפעולות מותאמות אישית שמאפשרות למשתמשים ליצור אינטראקציה עם הפעילות בלי להרחיב אותה. ב-PIP, הפעילות מושהית, אבל היא מוצגת, והיא לא מקבלת ישירות קלט מגע או מיקוד חלון. אפשר להציג רק משימה אחת במצב PIP בכל פעם.

מידע נוסף זמין בתיעוד למפתחים של Android בנושא תמונה בתוך תמונה.

דרישות לגבי מכשירים

כדי לתמוך ב-PIP, צריך להפעיל את תכונת המערכת PackageManager#FEATURE_PICTURE_IN_PICTURE ב-/android/frameworks/base/core/java/android/content/pm/PackageManager.java. במכשירים שתומכים ב-PIP, המסך צריך להיות גדול מ-220dp ברוחב המינימלי שלו. בדומה למסך מפוצל עם כמה חלונות, PIP מאפשר להפעיל כמה פעילויות במסך בו-זמנית. לכן, למכשירים צריכים להיות מעבד וזיכרון RAM מספיקים כדי לתמוך בתרחיש השימוש הזה.

הטמעה

רוב הפעולות שקשורות לניהול מחזור החיים של הפעילות מתבצעות במערכת בין ActivityManager לבין WindowManager. הטמעת ממשק המשתמש של ההפניה נמצאת בחבילה SystemUI.

שינויים במערכת לא אמורים להשפיע על ההתנהגות הפנימית שלה, כפי שהיא מוגדרת בבדיקות של חבילת בדיקות התאימות (CTS). הלוגיקה של המערכת לגבי PIP מתמקדת בעיקר בניהול של משימות ופעילויות בערימה 'מוצמדת'. הנה סקירה כללית מהירה של הכיתה:

  • ActivityRecord: עוקב אחרי מצב התמונה בתוך תמונה של כל פעילות. כדי למנוע ממשתמשים להיכנס למצב תמונה בתוך תמונה בנסיבות מסוימות, כמו ממסך הנעילה או במהלך שימוש במציאות מדומה, מוסיפים מקרים ל-checkEnterPictureInPictureState().
  • ActivityManagerService: הממשק הראשי של הפעילות שדרכו מבקשים להיכנס למצב תמונה בתוך תמונה, והממשק של שיחות מWindowManager ומSystemUI לשינוי מצב הפעילות של התמונה בתוך התמונה.
  • ActivityStackSupervisor: נקרא מתוך ActivityManagerService כדי להעביר משימות אל הערימה המוצמדת או ממנה, ומעדכן את WindowManager לפי הצורך.
  • PinnedStackWindowController: ממשק WindowManager מ-ActivityManager.
  • PinnedStackController: מדווח על שינויים במערכת ל-SystemUI, כמו הצגה או הסתרה של IME, שינוי יחס הגובה-רוחב או שינוי פעולות.
  • BoundsAnimationController: מפעיל אנימציה של חלונות פעילות ב-PIP באופן שלא גורם לשינוי בהגדרות בזמן שינוי הגודל.
  • PipSnapAlgorithm: מחלקה משותפת שמשמשת גם במערכת וגם ב-SystemUI, ושולטת בהתנהגות ההצמדה של חלון ה-PIP ליד קצוות המסך.

ההפניה SystemUI מספקת הטמעה מלאה של PIP שתומכת בהצגת פעולות מותאמות אישית למשתמשים ובמניפולציה כללית, כמו הרחבה וסגירה. יצרני מכשירים יכולים להסתמך על השינויים האלה, כל עוד הם לא משפיעים על ההתנהגויות המובנות כפי שהן מוגדרות ב-CDD. סקירה כללית מהירה של הכיתה:

  • PipManager: רכיב SystemUI שמופעל באמצעות SystemUI.
  • PipTouchHandler: המטפל במגע, ששולט בתנועות שמפעילות את התמונה בתוך תמונה. האפשרות הזו משמשת רק בזמן שהקלט של צרכן הקלט של PIP פעיל (ראו InputConsumerController). אפשר להוסיף כאן תנועות חדשות.
  • PipMotionHelper: מחלקה נוחה למעקב אחרי מיקום ה-PIP והאזור המותר במסך. שיחות דרך ActivityManagerService כדי לעדכן או להנפיש את המיקום והגודל של התמונה בתוך התמונה.
  • PipMenuActivityController: מתחיל פעילות שמציגה את הפעולות שזמינות בפעילות שמוצגת כרגע במצב PIP. הפעילות הזו היא פעילות של שכבת-על של משימה, והיא מסירה את צרכן הקלט של שכבת-העל כדי לאפשר אינטראקציה.
  • PipMenuActivity: ההטמעה של פעילות התפריט.
  • PipMediaController: רכיב ה-listener שמעדכן את SystemUI כשסשן המדיה משתנה באופן שעשוי להשפיע על פעולות ברירת המחדל ב-PIP.
  • PipNotificationController: בקר שמבטיח שההתראה תהיה פעילה בזמן שהמשתמש משתמש בתכונת ה-PIP.
  • PipDismissViewController: שכבת העל שמוצגת למשתמשים כשהם מתחילים אינטראקציה עם התמונה בתוך תמונה, כדי לציין שאפשר לסגור אותה.

מיקום ברירת המחדל

יש משאבי מערכת שונים ששולטים במיקום ברירת המחדל של התמונה בתוך התמונה:

  • config_defaultPictureInPictureGravity: מספר שלם של gravity, שקובע את הפינה שבה ימוקם ה-PIP, כמו BOTTOM|RIGHT.
  • config_defaultPictureInPictureScreenEdgeInsets: ההיסטים מהצדדים של המסך למיקום התמונה בתוך תמונה.
  • config_pictureInPictureDefaultSizePercent ו-config_pictureInPictureDefaultAspectRatio: השילוב של אחוז מרוחב המסך ויחס הגובה-רוחב קובע את הגודל של התמונה בתוך התמונה. הגודל המחושב של חלון ה-PIP שמוגדר כברירת מחדל לא יכול להיות קטן מ-@dimen/default_minimal_size_pip_resizable_task, כפי שמוגדר ב-CTS וב-CDD.
  • config_pictureInPictureSnapMode: התנהגות ההצמדה כפי שמוגדרת ב-PipSnapAlgorithm.

ההטמעות במכשירים לא צריכות לשנות את יחסי הגובה-רוחב המינימליים והמקסימליים שמוגדרים ב-CDD וב-CTS.

הרשאות

ההגדרה 'פעולת האפליקציה' (OP_PICTURE_IN_PICTURE) לכל חבילה ב-AppOpsManager (main/core/java/android/app/AppOpsManager.java) מאפשרת למשתמשים לשלוט בהצגת תמונה בתוך תמונה ברמת האפליקציה דרך הגדרות המערכת. ההטמעות של המכשירים צריכות להתייחס לבדיקה הזו כשפעילות מבקשת להיכנס למצב 'תמונה בתוך תמונה'.

בדיקה

כדי לבדוק יישומי PIP, מריצים את כל הבדיקות שקשורות לתמונה בתוך תמונה שנמצאות בבדיקות CTS בצד המארח בקטע /cts/hostsidetests/services/activitymanager, במיוחד ב-ActivityManagerPinnedStackTests.java.