Android 14 (nivel de API 34) incluye algunas mejoras en las APIs de pantalla en pantalla (PiP) para permitir la multitarea. Si bien la compatibilidad con PiP se introdujo en Android 8.0 (nivel de API 26), no era compatible con Android TV y no era compatible con Google TV antes de Android 13. La multitarea para TV usa el modo PiP para permitir que dos apps independientes coexistan en la pantalla: una que se ejecuta en pantalla completa y una segunda que se ejecuta en el modo PiP. Existen diferentes requisitos para las apps que se ejecutan en cualquiera de estos modos.
El comportamiento predeterminado es que la app de PiP superpone la app de pantalla completa. Esto es muy similar al comportamiento estándar de pantalla en pantalla de Android.
Ten en cuenta que, cuando integres la multitarea, tu aplicación debe declarar sus tipos de uso de acuerdo con los lineamientos de calidad de apps para TV.
Ejecuta tu app en el modo PiP
Para los dispositivos de TV que ejecutan Android 14 (nivel de API 34) o versiones posteriores, ejecuta tu app en el modo PiP
llamando a enterPictureInPictureMode(). Los dispositivos de TV que ejecutan versiones anteriores de Android no admiten el modo PiP.
Este es un ejemplo de cómo implementar la lógica de un botón para ingresar al modo 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); } }
La acción solo se agrega si el dispositivo tiene la función del sistema
FEATURE_PICTURE_IN_PICTURE. Además, cuando se activa la acción, la relación de aspecto del modo PiP se establece para que coincida con la relación de aspecto del video que se está reproduciendo.
Asegúrate de agregar un título y un subtítulo para brindar al usuario información sobre para qué se usa generalmente este PIP.
Coexistencia con apps que se ejecutan en el modo PiP
Cuando tu app se ejecuta como una app de pantalla completa, es posible que deba adaptarse a otras apps que se ejecutan en el modo PiP.
APIs de Keep-clear
En algunos casos, la app de PiP puede superponer componentes importantes de la IU dentro de la app de pantalla completa. Para mitigar esto, existen APIs de keep-clear que las apps pueden usar para identificar componentes críticos de la IU que no se deben superponer. El sistema intenta respetar las solicitudes para evitar cubrir estos componentes cambiando la posición de la ventana de PiP.

Para especificar que una vista no se debe superponer, usa preferKeepClear en tu
diseño XML como en el siguiente ejemplo:
<TextView
android:id="@+id/important_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:preferKeepClear="true"
android:text="@string/app_name"/>
También puedes hacerlo de manera programática con 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); }
Es posible que, en ocasiones, no necesites mantener despejada una View completa, sino
solo una sección de ella. El setPreferKeepClearRects() se puede usar para
especificar regiones de la View que no se deben superponer. Las IUs que no usan View de forma nativa, como Flutter, Jetpack Compose y WebView, pueden tener subsecciones que necesitan regiones despejadas. Esta API se puede usar para esos casos.
Tipos de uso
Tu app debe declarar un atributo de valor de metadatos de
com.google.android.tv.pip.category que corresponda con el tipo o los
tipos de uso principales para el modo de pantalla en pantalla. Cualquier <activity> que haya configurado
android:supportsPictureInPicture="true" debe declarar este atributo con un
valor pertinente de la siguiente tabla.
Los tipos de uso que no entran en ninguna de estas categorías, en particular, cualquier reproducción de contenido multimedia, no se permiten en el modo de pantalla en pantalla en la TV.
| Valor | Descripción |
|---|---|
"communication" |
Casos de uso de comunicaciones, como llamadas de voz o video |
"smartHome" |
Integraciones de casa inteligente, como timbres conectados o monitores para bebés |
"health" |
Casos de uso de salud, como el seguimiento de actividad física o la supervisión de estado de salud |
"ticker" |
Casos de uso de ticker, como resultados deportivos en vivo o tickers de noticias y acciones |
Si hay más de un valor, se separa con una barra vertical (|), por ejemplo:
<meta-data android:name="com.google.android.tv.pip.category" android:value="smartHome|health" />