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