Cómo admitir pantallas conectadas

Las pantallas conectadas extienden la experiencia de ventanas de escritorio a los teléfonos estándar, lo que les brinda a los usuarios acceso a pantallas grandes desde sus dispositivos móviles. Esta capacidad abre nuevas posibilidades para la interacción con apps y la productividad del usuario.

Todas las funciones únicas de las ventanas de escritorio se aplican a las pantallas conectadas. Cuando conectas un teléfono a una pantalla, el estado del teléfono permanece sin cambios y se inicia una sesión de escritorio en blanco en la pantalla conectada. El dispositivo y la pantalla actúan como dos sistemas individuales, con apps específicas para cada pantalla.

Figura 1: Teléfono conectado a una pantalla externa, con una sesión de escritorio en la pantalla mientras el teléfono mantiene su propio estado

Si conectas un dispositivo habilitado para ventanas de escritorio, como una tablet, a un monitor externo, la sesión de escritorio se extiende a ambas pantallas. Las dos pantallas funcionan como un sistema continuo. Esta configuración permite que las ventanas, el contenido y el cursor se muevan libremente entre las dos pantallas.

Figura 2: Tablet conectada a un monitor externo, que extiende la sesión de escritorio a ambas pantallas

Para admitir pantallas conectadas de manera eficaz, se requiere atención a varios aspectos del diseño y la implementación de tu app. Las siguientes prácticas recomendadas garantizan una experiencia del usuario fluida y productiva.

Controla los cambios dinámicos de pantalla

Muchas apps se compilan con la suposición de que el Display objeto y sus características no cambiarán durante el ciclo de vida de la app. Sin embargo, cuando un usuario conecta o desconecta un monitor externo, o incluso mueve una ventana de la app entre pantallas, puede cambiar el objeto Display subyacente asociado con el contexto o la ventana de tu app. Las propiedades de la pantalla, como el tamaño, la resolución, la frecuencia de actualización, la compatibilidad con HDR y la densidad, pueden ser diferentes. Si codificas valores de forma rígida en función de la pantalla del teléfono, por ejemplo, es probable que tus diseños se interrumpan en una pantalla externa.

Las pantallas externas también pueden tener densidades de píxeles muy diferentes. Debes asegurarte de que tu app responda correctamente a los cambios de densidad. Esto implica usar píxeles independientes de la densidad (dp) para los diseños, proporcionar recursos específicos de la densidad y garantizar que la IU se ajuste correctamente.

Si una actividad se ejecuta en una pantalla externa cuando se desconecta, el sistema la mueve a la pantalla principal. El movimiento activa cambios de configuración, como cambios en el tamaño y la densidad de la pantalla, que pueden hacer que se vuelva a crear la actividad. Tu app debe controlar el cambio de configuración guardando y restableciendo el estado de la IU para evitar la pérdida de datos o una experiencia del usuario confusa.

Usa el contexto correcto

Usar el contexto correcto es crucial en los entornos de pantallas múltiples. Cuando se accede a recursos, el contexto de la actividad (que se muestra) difiere del contexto de la aplicación (que no se muestra).

El contexto de la actividad contiene información sobre la pantalla y siempre se ajusta de acuerdo con el área de visualización donde aparece la actividad. Esto te permite obtener la información correcta sobre la densidad de la pantalla o las métricas de la ventana de tu app. Siempre usa el contexto de la actividad (u otro contexto basado en la IU) para obtener información sobre la ventana o la pantalla actual. Esto también influye en algunas APIs del sistema que usan información del contexto.

En Jetpack Compose, puedes acceder a información específica de la pantalla con CompositionLocal objetos como LocalConfiguration.current y LocalDensity.current. Cuando una actividad o ventana se mueve entre pantallas, cambia la configuración del dispositivo, lo que activa la recomposición con nuevas métricas de pantalla. Los objetos CompositionLocal permiten que tu IU se adapte sin problemas.

Obtén información de la pantalla

Puedes usar la clase Display para obtener información como el tamaño, la densidad o las marcas de la pantalla. Usa el servicio del sistema DisplayManager para obtener las pantallas disponibles. Para identificar pantallas externas, filtra Display.DEFAULT_DISPLAY, que suele ser la pantalla integrada del teléfono o la tablet:

val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
val displays = displayManager.getDisplays()
// The default display is 0. External displays have other IDs.
val externalDisplays = displays.filter { it.displayId != Display.DEFAULT_DISPLAY }

Administra el inicio y la configuración de la actividad

Con las pantallas conectadas, las apps pueden especificar en qué pantalla debe ejecutarse una app cuando se inicia o cuando crea otra actividad. Este comportamiento depende del modo de inicio de la actividad definido en el archivo de manifiesto, y de las opciones y los marcadores de intent establecidos por la entidad que inicia la actividad.

Cuando una actividad se traslada a una pantalla secundaria, tu app puede experimentar una actualización de contexto, un cambio de tamaño de ventana, y modificaciones en la configuración y los recursos. Si la actividad controla el cambio de configuración, se notifica en onConfigurationChanged(). De lo contrario, se vuelve a iniciar la actividad.

Si el modo de inicio seleccionado para una actividad permite varias instancias, el inicio en una pantalla secundaria puede crear una nueva instancia de la actividad. Se reanudarán ambas actividades al mismo tiempo, lo que puede ser beneficioso para ciertos casos de uso de multitarea.

Puedes iniciar una actividad en una pantalla en particular con ActivityOptions. Ten en cuenta que launchDisplayId requiere Android 8 (nivel de API 26) o versiones posteriores.

// Get DisplayManager and find the first external display.
val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
val externalDisplayId = displayManager.displays
    .firstOrNull { it.displayId != Display.DEFAULT_DISPLAY }
    ?.displayId

// If an external display is found, launch the activity on it.
if (externalDisplayId != null) {
    val intent = Intent(this, MySecondaryActivity::class.java)
    val options = ActivityOptions.makeBasic()
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        options.launchDisplayId = externalDisplayId
    }
    startActivity(intent, options.toBundle())
} else {
    // Optionally, handle the case where no external display is connected.
}

Evita las listas de entidades permitidas de dispositivos

A veces, las apps restringen la IU y las funciones de pantalla grande a dispositivos seleccionados a través de una lista de entidades permitidas o verificando BUILD.MODEL y el tamaño de pantalla integrado. Este enfoque no es eficaz para las pantallas conectadas porque prácticamente cualquier dispositivo se puede conectar a una pantalla grande, y el modelo del dispositivo no cambia cuando se conecta una pantalla externa.

En lugar de usar listas de entidades permitidas o verificar BUILD.MODEL y el tamaño de pantalla integrado, verifica las métricas de la ventana o las capacidades del dispositivo en el tiempo de ejecución para tomar decisiones de IU. Usa las APIs de Jetpack WindowManager o las clases de tamaño de ventana para compilar diseños responsivos y adaptativos para varios tamaños y densidades de pantalla.

Admite periféricos externos

Cuando los usuarios se conectan a una pantalla externa, suelen crear un entorno más similar al de una computadora de escritorio. Esto suele implicar el uso de teclados, mouses, trackpads, cámaras web, micrófonos y bocinas externos. Debes asegurarte de que tu app funcione sin problemas con estos periféricos. Esto incluye controlar combinaciones de teclas, administrar interacciones con el puntero del mouse, admitir correctamente cámaras o micrófonos externos y respetar el enrutamiento de salida de audio. Para obtener más detalles, consulta Compatibilidad de entrada en pantallas grandes.

Aumenta la productividad de los usuarios

Las pantallas conectadas brindan una oportunidad significativa para mejorar la productividad del usuario. Ahora tienes las herramientas para compilar apps para dispositivos móviles que pueden ofrecer experiencias comparables a las aplicaciones de escritorio. Considera implementar las siguientes funciones para aumentar la productividad de los usuarios:

Si sigues estos lineamientos y utilizas los ejemplos de código proporcionados, puedes crear apps que se adapten sin problemas a las pantallas conectadas, lo que les ofrece a los usuarios una experiencia más enriquecida y productiva.