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