ב-Android 14 (רמת API 34) הוספרו שיפורים ל-API של תמונה בתוך תמונה (PiP) כדי לאפשר ריבוי משימות. התמיכה ב-PiP הושקה ב-Android 8.0 (רמת API 26), אבל היא לא נתמכה באופן נרחב ב-Android TV, ולא נתמכה בכלל ב-Google TV לפני Android 13. ריבוי משימות בטלוויזיה מתבצע באמצעות מצב PiP, שמאפשר לשתי אפליקציות נפרדות לפעול בו-זמנית על המסך: אחת פועלת במסך מלא והשנייה פועלת במצב PiP. יש דרישות שונות לאפליקציות שפועלות באחד מהמצבים האלה.
ההתנהגות שמוגדרת כברירת מחדל היא שאפליקציית PiP מוצגת כשכבת-על מעל האפליקציה במסך מלא. זה דומה מאוד להתנהגות הרגילה של תמונה בתוך תמונה ב-Android.
שימו לב: כשמשלבים ריבוי משימות, האפליקציה צריכה להצהיר על סוגי השימוש שלה בהתאם להנחיות האיכות של אפליקציות לטלוויזיה.
הפעלת האפליקציה במצב תמונה בתוך תמונה
במכשירי טלוויזיה שמותקנת בהם מערכת Android 14 (רמת API 34) ואילך, אפשר להפעיל את האפליקציה במצב PiP על ידי קריאה ל-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.
לפעול במקביל לאפליקציות שפועלות במצב תמונה בתוך תמונה
כשהאפליקציה פועלת כאפליקציה במסך מלא, יכול להיות שהיא תצטרך להתאים את עצמה לאפליקציות אחרות שפועלות במצב תמונה בתוך תמונה (PiP).
ממשקי API של אזורים ללא הפרעות
במקרים מסוימים, אפליקציית ה-PiP עשויה להציג שכבת-על של רכיבי ממשק משתמש חשובים באפליקציה במסך מלא. כדי למנוע את זה, יש ממשקי API של keep-clear שאפליקציות יכולות להשתמש בהם כדי לזהות רכיבי ממשק משתמש קריטיים שלא צריכים להיות מוצגים כשכבת-על. המערכת מנסה להיענות לבקשות כדי להימנע מכיסוי הרכיבים האלה על ידי שינוי המיקום של חלון התמונה בתוך תמונה.
כדי לציין שלא תהיה שכבת-על בתצוגה, משתמשים ב-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, יכול להיות שיהיו קטעי משנה שצריך להשאיר בהם אזורים פנויים. אפשר להשתמש ב-API הזה במקרים כאלה.
סוגי שימוש
באפליקציה צריך להצהיר על מאפיין ערך של מטא-נתונים של
com.google.android.tv.pip.category
שמתאים לסוג השימוש העיקרי או לסוגי השימוש העיקריים במצב 'תמונה בתוך תמונה'. כל תג <activity>
עם הערך android:supportsPictureInPicture="true"
צריך להגדיר את המאפיין הזה עם ערך רלוונטי מהטבלה שלמטה.
סוגי שימוש שלא נכללים באף אחת מהקטגוריות האלה, ובמיוחד הפעלה של תוכן מדיה, אסורים במצב 'תמונה בתוך תמונה' בטלוויזיה.
ערך | תיאור |
---|---|
"communication " |
תרחישי שימוש בתקשורת, כמו שיחות וידאו או שיחות קוליות. |
"smartHome " |
שילובים של בית חכם, כמו פעמוני דלת או מוניטורים לתינוקות. |
"health " |
תרחישי שימוש בתחום הבריאות, כמו מעקב אחר כושר או מעקב אחר מצב בריאותי. |
"ticker " |
תרחישי שימוש בטיקרים, כמו תוצאות ספורט בשידור חי או טיקרים של חדשות ומניות. |
כדי להוסיף כמה ערכים, צריך להפריד ביניהם באמצעות קו אנכי (|
). לדוגמה:
<meta-data android:name="com.google.android.tv.pip.category" android:value="smartHome|health" />