Android 14 (niveau d'API 34) introduit des améliorations des API Picture-in-picture (PIP) pour permettre le multitâche. Bien que la compatibilité avec le mode PiP ait été introduite dans Android 8.0 (niveau d'API 26), elle n'était pas largement compatible avec Android TV et n'était pas du tout compatible avec Google TV avant Android 13. La multitâche pour la télévision utilise le mode PIP pour permettre à deux applications distinctes de coexister à l'écran : l'une en plein écran et l'autre en mode PIP. Des exigences différentes s'appliquent aux applications exécutées dans l'un de ces modes.
Par défaut, l'application PiP se superpose à l'application en plein écran. Cela ressemble beaucoup au comportement standard de la fonctionnalité Picture-in-picture d'Android.
Notez que lors de l'intégration du mode multitâche, votre application doit déclarer son types d'utilisation conformément aux consignes relatives à la qualité des applis TV.
Exécuter votre application en mode PiP
Pour les téléviseurs équipés d'Android 14 (niveau d'API 34) ou version ultérieure, exécutez votre application en mode PIP.
en appelant enterPictureInPictureMode()
. Appareils TV fonctionnant plus tôt
versions d'Android ne sont pas compatibles avec le mode PIP.
Voici un exemple d'implémentation de la logique d'un bouton permettant d'entrer Mode 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); } }
L'action n'est ajoutée que si l'appareil dispose de la fonctionnalité système FEATURE_PICTURE_IN_PICTURE
. Par ailleurs, lorsque l'action est déclenchée,
Le format du mode PIP est configuré pour correspondre au format de la vidéo en cours de lecture.
joué.
Veillez à ajouter un titre et un sous-titre pour indiquer à l'utilisateur à quoi sert généralement ce PIP.
Coexister avec des applications s'exécutant en mode PIP
Lorsque votre application s'exécute en mode plein écran, elle peut devoir s'adapter aux autres applications exécutées en mode PiP.
API de clarté
Dans certains cas, l'application PIP peut superposer d'importants composants d'interface utilisateur dans plein écran. Pour atténuer ce problème, il existe des API claires que les applications peuvent utiliser pour identifier les composants d'UI critiques qui ne doivent pas être superposés. Le système s'efforce d'honorer les demandes afin d'éviter de couvrir ces composants en repositionnant la fenêtre PIP.
Pour spécifier qu'une vue ne doit pas être superposée, utilisez preferKeepClear
dans votre mise en page XML, comme dans l'exemple suivant :
<TextView
android:id="@+id/important_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:preferKeepClear="true"
android:text="@string/app_name"/>
Vous pouvez également effectuer cette opération par programmation à l'aide de 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); }
Il peut arriver que vous n'ayez pas besoin de garder une View
entièrement claire, mais
n'en contient qu'une partie. setPreferKeepClearRects()
peut être utilisé pour spécifier les régions de l'View
qui ne doivent pas être superposées. Les UI qui n'utilisent pas de View
de manière native, telles que Flutter, Jetpack Compose et WebView, peuvent avoir des sous-sections nécessitant de conserver des régions vides. Cette API peut être utilisée dans ce cas.
Types d'utilisation
Votre application doit déclarer un attribut de valeur de métadonnées de com.google.android.tv.pip.category
correspondant au ou aux types d'utilisation principaux du mode Picture-in-picture. Tout <activity>
défini
android:supportsPictureInPicture="true"
doit déclarer cet attribut avec un
la valeur la plus pertinente dans le tableau ci-dessous.
Les types d'utilisation qui ne rentrent dans aucune de ces catégories, en particulier la lecture de contenus multimédias, ne sont pas autorisés en mode Picture-in-picture sur TV.
Valeur | Description |
---|---|
"communication " |
Cas d'utilisation pour les communications, comme les appels vidéo ou vocaux. |
"smartHome " |
Intégrations à la maison connectée, comme les sonnettes ou les babyphones connectés |
"health " |
Cas d'utilisation liés à la santé, tels que le suivi de l'activité physique ou le suivi de la santé |
"ticker " |
Cas d'utilisation d'indices, comme les résultats sportifs en direct, les actualités et les valeurs boursières. |
Les valeurs multiples sont séparées par une barre verticale (|
). Par exemple:
<meta-data android:name="com.google.android.tv.pip.category" android:value="smartHome|health" />