התכונה 'תמונה בתוך תמונה' (PIP) במכשירים ניידים עם Android מאפשרת למשתמשים לשנות את גודל האפליקציה שבה מתבצעת פעילות מתמשכת לחלון קטן. התכונה 'תמונה בתוך תמונה' שימושית במיוחד באפליקציות וידאו, כי התוכן ממשיך לפעול בזמן שהמשתמש יכול לבצע פעולות אחרות. המשתמשים יכולים לשנות את המיקום של החלון הזה דרך SystemUI, ולבצע פעולות (עד שלוש) באפליקציה שנמצאת כרגע במצב 'תמונה בתוך תמונה'.
כדי להשתמש ב-PIP, צריך להביע הסכמה מפורשת באפליקציות שתומכות בו, והוא פועל על בסיס כל פעילות. (אפליקציה אחת יכולה לכלול כמה פעילויות, ורק אחת מהן תופיע ב-PIP). פעילויות מבקשות להיכנס למצב 'תמונה בתוך תמונה' באמצעות קריאה ל-enterPictureInPictureMode()
, ומקבלות קריאות חזרה לפעילויות בצורת onPictureInPictureModeChanged()
.
השיטה setPictureInPictureParams()
מאפשרת לפעילויות לשלוט ביחס הגובה-רוחב שלהן במצב PIP ובפעולות בהתאמה אישית, וכך המשתמשים יכולים לקיים אינטראקציה עם הפעילות בלי להרחיב אותה. ב-PIP, הפעילות מושהית אבל עדיין מתבצעת בה עיבוד, והיא לא מקבלת ישירות קלט מגע או מיקוד חלון.
אפשר להציג רק משימה אחת ב-PIP בכל פעם.
מידע נוסף זמין במסמכי התיעוד למפתחים של Android בנושא תמונה בתוך תמונה.
דרישות לגבי מכשירים
כדי לתמוך ב-PIP, מפעילים את תכונת המערכת PackageManager#FEATURE_PICTURE_IN_PICTURE
ב-/android/frameworks/base/core/java/android/content/pm/PackageManager.java
.
במכשירים שתומכים ב-PIP חייב להיות מסך ברוחב קטן ביותר של יותר מ-220dp. בדומה לחלונות מרובים במסך מפוצל, התכונה 'חלון בתוך חלון' מאפשרת להפעיל כמה פעילויות במסך בו-זמנית. לכן, צריך שיהיו במכשירים מעבד (CPU) וזיכרון RAM מספיקים כדי לתמוך בתרחיש לדוגמה הזה.
הטמעה
רוב ניהול מחזור החיים של הפעילות מתבצע במערכת בין ActivityManager
ל-WindowManager
.
הטמעת ממשק המשתמש לדוגמה נמצאת בחבילה SystemUI
.
שינויים במערכת לא אמורים להשפיע על ההתנהגות המובנית שלה כפי שמוגדרת בבדיקות של חבילת בדיקות התאימות (CTS). הלוגיקה של המערכת ב-PIP מתמקדת בעיקר בניהול המשימות והפעילויות בתוך הסטאק 'המוצמדים'. הנה סקירה כללית מהירה על הכיתה:
ActivityRecord
: מעקב אחרי המצב של כל פעילות בחלון משני. כדי למנוע ממשתמשים להיכנס למצב PIP בנסיבות מסוימות, כמו ממסך הנעילה או במהלך שימוש ב-VR, מוסיפים מקרים ל-checkEnterPictureInPictureState()
.ActivityManagerService
: הממשק הראשי מהפעילות לבקשת מעבר למצב PIP, והממשק לשיחות מ-WindowManager
ומ-SystemUI
לשינוי מצב הפעילות ב-PIP.ActivityStackSupervisor
: הפונקציה נקראת מ-ActivityManagerService
כדי להעביר משימות לסטאק המוצמד או ממנו, ולעדכן אתWindowManager
לפי הצורך.PinnedStackWindowController
: ממשקWindowManager
מ-ActivityManager
.PinnedStackController
: דיווח על שינויים במערכת ל-SystemUI
, כמו הצגה או הסתרה של IME, שינוי יחס הגובה-רוחב או שינוי פעולות.BoundsAnimationController
: האנימציה של חלונות הפעילות ב-PIP מתבצעת באופן שלא מפעיל שינוי בתצורה בזמן שינוי הגודל.PipSnapAlgorithm
: כיתה משותפת שמשמשת גם את המערכת וגם את SystemUI, ומשמשת לבקרת התנהגות הצמדת חלון ה-PIP ליד קצוות המסך.
בדוגמה SystemUI
מופיעה הטמעה מלאה של PIP שתומכת בהצגת פעולות בהתאמה אישית למשתמשים ובמניפולציות כלליות, כמו הרחבה וסגירה.
יצרני המכשירים יכולים להסתמך על השינויים האלה, כל עוד הם לא משפיעים על ההתנהגויות המובנות כפי שמוגדרות ב-CDD. הנה סקירה כללית מהירה על הכיתה:
PipManager
: הרכיבSystemUI
שמופעל באמצעותSystemUI
.PipTouchHandler
: הטיפול במגע, שמאפשר לשלוט בתנועות שמפעילות את חלון ה-PIP. הוא משמש רק בזמן שצרכן הקלט של חלון ה-PIP פעיל (ראוInputConsumerController
). אפשר להוסיף כאן תנועות חדשות.PipMotionHelper
: מחלקת נוחות שמשמשת למעקב אחרי המיקום של PIP והאזור המותר במסך. קריאה ל-ActivityManagerService
כדי לעדכן או להוסיף אנימציה למיקום ולגודל של התמונה בתוך התמונה.PipMenuActivityController
: מפעילה פעילות שמציגה את הפעולות שזמינות בפעילות הנוכחית בחלון מלא. הפעילות הזו היא פעילות שכבת-על של משימה, והיא מסירה את צרכן הקלט שכבת-העל כדי לאפשר לה להיות אינטראקטיבית.PipMenuActivity
: ההטמעה של פעילות התפריט.PipMediaController
: המאזין שמעדכן אתSystemUI
כשסשן המדיה משתנה באופן שעלול להשפיע על הפעולות שמוגדרות כברירת מחדל ב-PIP.PipNotificationController
: הפקטור שקובע אם ההתראה פעילה בזמן שהמשתמש משתמש בתכונה PIP.PipDismissViewController
: שכבת-העל שמוצגת למשתמשים כשהם מתחילים לבצע אינטראקציה עם התמונה בתוך התמונה (PIP), כדי לציין שאפשר לסגור אותה.
מיקום ברירת המחדל
יש משאבי מערכת שונים ששולטים במיקום ברירת המחדל של חלון ה-PIP:
config_defaultPictureInPictureGravity
: המספר השלם של gravity, שמגדיר את הפינה שבה יוצג חלון ה-PIP, למשלBOTTOM|RIGHT
.config_defaultPictureInPictureScreenEdgeInsets
: ההזחות מהצדדים של המסך למיקום חלון ה-PIP.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 ברמת האפליקציה דרך הגדרות המערכת.
הטמעות במכשירים צריכות לפעול בהתאם לבדיקה הזו כשפעילות מבקשת לעבור למצב 'תמונה בתוך תמונה'.
בדיקה
כדי לבדוק הטמעות של PIP, מריצים את כל הבדיקות שקשורות לתמונה בתוך תמונה שנמצאות בבדיקות CTS בצד המארח בקטע /cts/hostsidetests/services/activitymanager
, במיוחד ב-ActivityManagerPinnedStackTests.java
.