Compatibilidad con el modo Multiventana

Android 7.0 admite la visualización de más de una app a la vez. En dispositivos de mano, se pueden ejecutar dos apps una al lado de la otra o una por encima de la otra en el modo de pantalla dividida. En dispositivos de TV, las apps pueden usar el modo pantalla en pantalla para continuar la reproducción de video mientras los usuarios interactúan con otra app.

Si tu app está orientada a Android 7.0 (nivel de API 24) o versiones posteriores, puedes configurar la manera en que procesa la visualización multiventana. Por ejemplo, puedes especificar las dimensiones mínimas permitidas de tu actividad. También puedes inhabilitar la visualización multiventana para tu app y asegurarte de que el sistema la muestre solamente en el modo de pantalla completa.

Descripción general

Android permite que varias aplicaciones compartan la pantalla al mismo tiempo. Por ejemplo, un usuario podría dividir la pantalla y ver una página web a la izquierda mientras escribe un correo electrónico a la derecha. La experiencia del usuario depende de la versión del SO Android y del tipo de dispositivo que tenga:

  • Los dispositivos de mano que ejecutan Android 7.0 ofrecen el modo de pantalla dividida. En este modo, el sistema ocupa la pantalla con dos apps y las muestra una al lado de la otra o una encima de la otra. El usuario puede arrastrar la línea que divide las dos aplicaciones para ver una más grande que la otra.
  • A partir de Android 8.0, las apps pueden habilitar de forma automática el modo de pantalla en pantalla. Esto les permite continuar mostrando contenido mientras el usuario explora otras apps o interactúa con ellas.
  • Los fabricantes de dispositivos más grandes pueden optar por habilitar el modo de forma libre, en el que el usuario puede modificar el tamaño de cada actividad como más le guste. Si el fabricante habilita esta función, el dispositivo ofrecerá el modo de forma libre además del modo de pantalla dividida.

Figura 1: Dos apps ejecutándose una al lado de la otra en el modo de pantalla dividida

El usuario puede cambiar al modo multiventana de la siguiente manera:

  • Si el usuario abre la pantalla Recientes y mantiene presionado el título de una actividad, puede arrastrarla a una parte resaltada de la pantalla para usarla en el modo multiventana.
  • Si el usuario mantiene presionado el botón Recientes, el dispositivo coloca la actividad actual en el modo multiventana y abre la pantalla Recientes a fin de permitirle al usuario seleccionar otra actividad para compartir la pantalla.

Los usuarios pueden arrastrar y soltar datos de una actividad a otra mientras las actividades comparten la pantalla.

Ciclo de vida en el modo multiventana

El modo multiventana no cambia el ciclo de vida de la actividad.

En el modo multiventana, solo está activa en un momento determinado la actividad con la que el usuario interactuó más recientemente. Esta actividad se considera principal y es la única actividad que tiene el estado RESUMED. Todas las demás actividades visibles tienen el estado STARTED, pero no pueden aparecer como RESUMED. No obstante, el sistema les da a esas actividades visibles pero no reanudadas una prioridad más alta que a las actividades que no están visibles. Si el usuario interactúa con una de las actividades visibles, esta se reanuda y la actividad principal anterior pasa al estado STARTED.

Nota: En el modo multiventana, una app puede no aparecer con el estado RESUMED aunque sea visible para el usuario. Es posible que una app necesite seguir ejecutándose mientras no sea la principal. Por ejemplo, una app de reproducción de video en este estado debería seguir mostrando su contenido. Por este motivo, recomendamos que las actividades que reproduzcan videos no pausen la reproducción en respuesta al evento de ciclo de vida ON_PAUSE. En su lugar, la actividad debe comenzar a reproducirse en respuesta a ON_START y pausar la reproducción en respuesta a ON_STOP. Si controlas los eventos de ciclo de vida de forma directa en lugar de utilizar el paquete Lifecycle, detén la reproducción de video en tu controlador onStop() y reanuda la reproducción en onStart().

Cuando el usuario coloca una app en el modo multiventana, el sistema notifica a la actividad de un cambio de configuración, como se especifica en Cómo controlar los cambios de configuración. Esto también sucede cuando el usuario modifica el tamaño de la app o la coloca nuevamente en el modo de pantalla completa. Este cambio tiene en esencia las mismas consecuencias en el ciclo de vida de la actividad que cuando el sistema notifica a la app que el dispositivo cambió del modo vertical al de paisaje, excepto porque se modifican las dimensiones del dispositivo en lugar de intercambiarse solamente. Como se explica en Cómo controlar los cambios de configuración, tu actividad puede procesar el cambio de configuración por sí misma o puede permitir que el sistema destruya la actividad y la vuelva a crear con las nuevas dimensiones.

Si el usuario cambia el tamaño de una ventana y la agranda en cualquier dirección, el sistema modifica el tamaño de la actividad para que coincida con la acción del usuario y emite cambios de configuración según sea necesario. Si la app se retrasa en el dibujo de áreas recientemente expuestas, el sistema rellena de forma temporal esas áreas con el color especificado por el atributo windowBackground o por el atributo de estilo predeterminado windowBackgroundFallback.

Cuando la app está en el modo multiventana, el estado reanudado depende de la versión de Android que tenga el dispositivo.

  • En Android 9 (nivel de API 28) y versiones anteriores, solo la actividad enfocada tiene el estado RESUMED. Todas las demás son PAUSED. Cuando hay varias actividades dentro de un solo proceso de app, la actividad con el orden Z más alto es RESUMED y las otras son PAUSED.
  • En Android 10 (nivel de API 29) y versiones posteriores, todas las actividades visibles y enfocables son RESUMED.

Consulta la documentación sobre reanudación múltiple para obtener más información.

Multiventana

Una de las ventajas de las pantallas grandes es que permiten ejecutar varias ventanas. Anteriormente, tener dos apps una al lado de la otra era común en algunos dispositivos. La tecnología ha mejorado hasta el punto en que tres o más apps pueden ejecutarse en la pantalla al mismo tiempo y también compartir contenido entre ellas:

Si una app no admite correctamente el modo Multiventana, puede establecer resizeableActivity=false. Para obtener más información, lee la guía sobre Multiventana.

Dado que el modo Multiventana es cada vez más común, es recomendable que agregues compatibilidad con arrastrar y soltar a tu app.

Reanudación múltiple

Cuando se ejecuta en Android 9.0 y versiones anteriores, solo la app enfocada tiene el estado reanudado. Cualquier otra actividad visible está en pausa. Esto puede crear problemas si las apps cierran recursos o dejan de reproducir contenido cuando se pausan.

En Android 10, se modificó este comportamiento para que todas las actividades permanezcan en el estado reanudada cuando el dispositivo esté en modo multiventana. La función se denomina reanudación múltiple. Ten en cuenta que una actividad se puede pausar si hay una actividad transparente encima o si la actividad no se puede enfocar (p. ej., en el modo pantalla en pantalla). También es posible que ninguna actividad esté enfocada en un momento dado, por ejemplo, si el panel de notificaciones está abierto. OnStop sigue funcionando como de costumbre. Se lo llamará cada vez que se quite la actividad de la pantalla.

La reanudación múltiple también está disponible en ciertos dispositivos con Android 9.0. Para habilitar la reanudación múltiple en esos dispositivos, puedes agregar los siguientes metadatos de manifiesto:

<meta-data
    android:name="android.allow_multiple_resumed_activities" android:value="true" />

Para verificar que un dispositivo en particular admita estos metadatos de manifiesto, consulta sus especificaciones.

Acceso a recursos exclusivos

Para ayudar a admitir la reanudación múltiple, hay una nueva función de devolución de llamada de ciclo de vida: Activity#onTopResumedActivityChanged().

Este método se invoca cuando una actividad gana o pierde la posición de más reanudada. Esto es importante para saber cuándo una actividad utiliza un recurso compartido de un solo usuario, como el micrófono o la cámara.

override fun onTopResumedActivityChanged(topResumed: Boolean) {
    if (topResumed) {
        // Top resumed activity
        // Can be a signal to re-acquire exclusive resources
    } else {
        // No longer the top resumed activity
    }
}

Ten en cuenta que una app puede perder recursos debido a otras razones, como quitar una pieza de hardware compartida.

En cualquier caso, una app debe administrar de manera fluida los eventos de pérdida de recursos y los cambios de estado que afectan a los recursos disponibles.

Para las apps que utilizan una cámara, se recomienda utilizar el método CameraManager.AvailabilityCallback#onCameraAccessPrioritiesChanged() a modo de sugerencia de que podría ser un buen momento para intentar acceder a la cámara. Este método está disponible en Android 10 (nivel de API 29) y versiones posteriores.

Recuerda que resizeableActivity=false no es una garantía de acceso exclusivo a la cámara, ya que otras apps que la utilizan se pueden abrir en otras pantallas.

Cámara en modo Multiventana

No es necesario que tu app libere la cámara cuando pierde el enfoque. Por ejemplo, es posible que quieras continuar con la vista previa de la cámara mientras el usuario interactúa con la app recién enfocada que se reanudó más arriba. No hay problema si tu app sigue ejecutando la cámara cuando no es la app que se reanudó más arriba, pero debe administrar el caso de desconexión correctamente. Cuando la app más reanudada quiera usar la cámara, podrá usarla, y tu app perderá el acceso. Esta luego podrá reabrir la cámara cuando recupere el enfoque.

Después de que una app reciba una devolución de llamada CameraDevice.StateCallback#onDisconnected(), las llamadas subsecuentes del dispositivo de cámara arrojarán un CameraAccessException.

Pantallas múltiples

En el futuro, es posible que veas teléfonos plegables que admitan más de una pantalla o visualización a la vez. Administrar esta configuración es similar a la forma en que los desarrolladores trabajan actualmente con pantallas proyectadas en el Sistema operativo Chrome.

Android 10 (nivel de API 29) y las versiones posteriores admiten actividades en pantallas secundarias. Si una actividad se ejecuta en un dispositivo con pantallas múltiples, los usuarios pueden mover la actividad de una pantalla a otra. La reanudación múltiple también se aplica a los casos con pantallas múltiples. Varias actividades pueden recibir la entrada del usuario al mismo tiempo.

Una app puede especificar en qué pantalla debe ejecutarse 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. Consulta ActivityOptions para obtener más información.

Al igual que con las transiciones de plegado, cuando una actividad se traslada a una pantalla secundaria, puede atravesar una actualización de contexto, un cambio de tamaño de ventana y modificaciones en la configuración y los recursos. Si la actividad administra el cambio de configuración, se le notificará en onConfigurationChanged(). Si no lo hace, se volverá a iniciar.

Una actividad debe verificar la visualización actual en onCreate y onConfigurationChanged si se los administra. Asegúrate de actualizar los recursos y diseños cuando cambie la pantalla.

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

Varias instancias de una actividad en múltiples pantallas

También recomendamos leer acerca de las API de pantallas múltiples existentes que se agregaron en Android 8.0.

Cortes de pantalla

Los dispositivos plegables pueden tener una geometría de cortes diferente cuando se pliegan y se despliegan. Para evitar problemas relacionados con los cortes, lee las prácticas recomendadas para los cortes de pantalla.

Contexto de la actividad frente a contexto de la aplicación

Usar el contexto correcto es crucial en las 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. Esto te permite obtener la información correcta sobre la densidad o las métricas de la ventana que tu app tiene en la actualidad. Siempre debes usar 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 API del sistema que usan información del contexto (como Toast).

La configuración de la ventana de la actividad y la pantalla superior definen recursos y contexto. Para obtener la pantalla actual, usa lo siguiente:

val activityDisplay = activity.display

Para obtener las métricas de la ventana de la actividad actual, usa lo siguiente:

val windowMetrics = activity.windowManager.getCurrentWindowMetrics()

Si quieres obtener las métricas máximas de la ventana para la configuración actual del sistema, usa el siguiente comando:

val maximumWindowMetrics = activity.windowManager.getMaximumWindowMetrics()

Las métricas máximas de la ventana son información útil para realizar cálculos, elegir el diseño o determinar el tamaño de los recursos que se deben recuperar con anticipación. Tener esta información disponible en onCreate() te permite tomar estas decisiones antes del primer pase de diseño. Estos datos no se deben utilizar para distribuir elementos de diseño específicos y, en su lugar, debes usar información del objeto Configuration.

Uso de pantallas secundarias

Puedes obtener las pantallas disponibles del servicio del sistema DisplayManager:

val dm = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
val displays = dm.displays

Usa la clase Display para obtener información sobre una pantalla en particular, como verificar las marcas para ver si una pantalla es segura.

Sin embargo, no supongas que el tamaño de la pantalla será el tamaño constante en el que se colocará tu app. Recuerda que, en el modo multiventana, tu app estará en un subconjunto de la pantalla.

Para determinar si una actividad puede iniciarse en una pantalla:

activityManager.isActivityStartAllowedOnDisplay(context, displayId, intent)

Para iniciar una actividad en una pantalla:

val options = ActivityOptions.makeBasic()
options.launchDisplayId = targetDisplay.displayId
startActivity(intent, options.toBundle())

Compatibilidad con pantallas múltiples

Android ya es compatible con teclados de software, fondos de pantalla y selectores.

Teclado de software

Se puede mostrar un teclado en una pantalla secundaria si está configurada para admitir decoraciones del sistema. El editor del método de entrada aparecerá automáticamente si un campo de texto solicita una entrada en esa pantalla.

Teclado en una pantalla secundaria

Fondo de pantalla

En Android 10 (nivel de API 29) y versiones posteriores, las pantallas secundarias pueden tener un fondo de pantalla. El framework crea una instancia separada de WallpaperService.Engine para cada pantalla. Asegúrate de que se dibuje la superficie de cada motor de forma independiente. Los desarrolladores pueden cargar recursos utilizando el contexto de visualización de WallpaperService.Engine#getDisplayContext(). Además, asegúrate de que tu archivo WallpaperInfo.xml establezca android:supportsMultipleDisplays="true".

Fondos de pantalla en el teléfono y en la pantalla secundaria

Selectores

Hay una nueva categoría SECONDARY_HOME de filtro de intents que permite proporcionar una actividad dedicada para las pantallas secundarias. Las instancias de esta actividad se utilizan en todas las pantallas que admiten decoraciones del sistema, una por cada pantalla.

<activity>
    ...
    <intent-filter>
        <category android:name="android.intent.category.SECONDARY_HOME" />
        ...
    </intent-filter>
</activity>

La actividad debe tener un modo de inicio que no impida múltiples instancias y que pueda adaptarse a diferentes tamaños de pantalla. El modo de lanzamiento no puede ser singleInstance ni singleTask.

Como ejemplo, la implementación de AOSP de Launcher3 admite una actividad SECONDARY_HOME.

Selector con aspecto de material design en un teléfono

Selector con aspecto de Material Design en una pantalla secundaria.

Cómo configurar tu app para el modo multiventana

Si tu app está orientada a un nivel de API 24 o superior, puedes configurar si quieres que las actividades de la app admitan la visualización multiventana y cómo quieres que lo hagan. Puedes establecer atributos en tu manifiesto para controlar el tamaño y el diseño. La configuración de atributos de una actividad raíz se aplica a todas las actividades de su pila de tareas. Por ejemplo, si el objeto android:resizeableActivity está configurado en verdadero para la actividad raíz, se puede modificar el tamaño de todas las actividades de la pila de tareas.

Nota: Si compilas una app para varias orientaciones con un nivel de API 23 o inferior, y el usuario utiliza la app en el modo multiventana, el sistema redimensiona la app de manera forzosa. El sistema presenta un cuadro de diálogo en el que se advierte al usuario que la app puede comportarse de forma inesperada. El sistema no modifica el tamaño de apps con orientación fija; si el usuario intenta abrir una de esas aplicaciones en el modo multiventana, la app ocupará toda la pantalla.

En algunos dispositivos más grandes, como las Chromebooks, tu app podría ejecutarse en una ventana que cambia de tamaño incluso si especificas android:resizeableActivity=”false”. Si eso hace que tu app falle, puedes usar filtros para restringir la disponibilidad de la app en esos dispositivos.

android:resizeableActivity

Establece este atributo en el elemento <activity> o <application> de tu manifiesto para habilitar o inhabilitar la visualización en el modo multiventana:

android:resizeableActivity=["true" | "false"]

Si este atributo se establece en verdadero, la actividad puede iniciarse en los modos de pantalla dividida y forma libre. Si el atributo se establece en falso, la actividad no admite el modo multiventana. Si este valor es falso, y el usuario intenta iniciar la actividad en el modo multiventana, la actividad ocupará toda la pantalla.

Si tu app está orientada al nivel de API 24, pero no especificas un valor para este atributo, el valor predeterminado se establecerá como verdadero.

android:supportsPictureInPicture

Establece este atributo en el nodo <activity> de tu manifiesto para indicar si la actividad admite la visualización de pantalla en pantalla. Este atributo se ignora si el objeto android:resizeableActivity es falso.

android:supportsPictureInPicture=["true" | "false"]

Atributos de diseño

Con Android 7.0, el elemento de manifiesto <layout> admite varios atributos que afectan cómo se comporta una actividad en el modo multiventana:

android:defaultWidth
Es el ancho predeterminado de la actividad cuando se inicia en modo de forma libre.
android:defaultHeight
Es la altura predeterminada de la actividad cuando se inicia en modo de forma libre.
android:gravity
Es la ubicación inicial de la actividad cuando se inicia en el modo de forma libre. Consulta la referencia de Gravity para obtener valores adecuados.
android:minHeight, android:minWidth
Son la altura y el ancho mínimos para la actividad tanto en el modo de pantalla dividida como en el de forma libre. Si el usuario mueve la línea divisoria en el modo de pantalla dividida para reducir el tamaño de la actividad a un valor menor al mínimo especificado, el sistema recorta la actividad para ajustarla a los requisitos del usuario.

Por ejemplo, el siguiente código muestra cómo especificar la ubicación y el tamaño predeterminados de una actividad, y su tamaño mínimo, cuando la actividad se visualiza en el modo de forma libre:

<activity android:name=".MyActivity">
    <layout android:defaultHeight="500dp"
          android:defaultWidth="600dp"
          android:gravity="top|end"
          android:minHeight="450dp"
          android:minWidth="300dp" />
</activity>

Cómo controlar correctamente los cambios de la configuración

Si controlas los cambios de la configuración del modo multiventana por tu cuenta, por ejemplo, lo que sucede cuando un usuario cambia el tamaño de una ventana, agrega el atributo android:configChanges a tu manifiesto con al menos los siguientes valores:

<activity
  android:name=".MyActivity"
  android:configChanges="screenSize|smallestScreenSize
      |screenLayout|orientation"
/>

Después de agregar android:configChanges, tu actividad y tus fragmentos recibirán una devolución de llamada a onConfigurationChanged() en lugar de destruirse y volver a crearse. Luego, podrás actualizar manualmente las vistas, volver a cargar los recursos y realizar otras operaciones según sea necesario.

Cómo ejecutar tu app en el modo multiventana

A partir de Android 7.0, el sistema ofrece funcionalidad para admitir apps que pueden ejecutarse en el modo multiventana.

Funciones inhabilitadas en el modo multiventana

Ciertas funciones están inhabilitadas o se ignoran cuando un dispositivo se encuentra en el modo multiventana, ya que no resultan útiles para una actividad que podría estar compartiendo la pantalla del dispositivo con otras actividades o apps. Esas funciones incluyen las siguientes:

  • Algunas opciones de personalización de la IU del sistema están inhabilitadas; por ejemplo, las apps no pueden ocultar la barra de estado si no se están ejecutando en el modo de pantalla completa.
  • El sistema ignora los cambios del atributo android:screenOrientation.

Búsqueda y notificaciones de cambios en el modo multiventana

Activity ofrece los siguientes métodos para admitir la visualización multiventana.

isInMultiWindowMode()
Realiza una llamada para averiguar si la actividad está en el modo multiventana.
isInPictureInPictureMode()
Realiza una llamada para averiguar si la actividad está en el modo de pantalla en pantalla.

Nota: El modo de pantalla en pantalla es un caso especial del modo multiventana. Si myActivity.isInPictureInPictureMode() muestra un valor verdadero, myActivity.isInMultiWindowMode() también muestra el mismo valor.

onMultiWindowModeChanged()
El sistema llama a este método siempre que la actividad entra en el modo multiventana o sale de él. El sistema le pasa al método el valor verdadero si la actividad ingresa al modo multiventana y el valor falso si sale de él.
onPictureInPictureModeChanged()
El sistema llama a este método siempre que la actividad entra en el modo de pantalla en pantalla o sale de él. El sistema le pasa al método el valor verdadero si la actividad ingresa al modo de pantalla en pantalla y el valor falso si sale de él.

La clase Fragment expone versiones de muchos de estos métodos, como Fragment.onMultiWindowModeChanged().

Cómo ingresar al modo de pantalla en pantalla

Para que una actividad ingrese al modo de pantalla en pantalla, debes llamar a Activity.enterPictureInPictureMode(). Este método no tiene efecto si el dispositivo no admite el modo de pantalla en pantalla. Para obtener más información, consulta la documentación sobre la función Pantalla en pantalla.

Cómo iniciar nuevas actividades en el modo multiventana

Cuando inicias una nueva actividad, puedes indicar que la actividad nueva se debe mostrar adyacente a la actual si es posible. Para hacer esto, usa la marca de intent FLAG_ACTIVITY_LAUNCH_ADJACENT. Esta marca le indica al sistema que intente crear la actividad nueva junto a la actividad que la inició, de modo que las dos compartan la pantalla. El sistema hace su mejor esfuerzo para llevarlo a cabo, pero no se garantiza que lo logre.

Si un dispositivo está en el modo de forma libre e inicias una actividad nueva, puedes especificar las dimensiones y la ubicación de la pantalla de la nueva actividad llamando a ActivityOptions.setLaunchBounds(). Este método no tiene efecto si el dispositivo no está en el modo multiventana.

Nota: Si inicias una actividad en una pila de tareas, esa actividad reemplazará la que esté en pantalla y heredará todas sus propiedades multiventana. Si quieres iniciar la actividad nueva en una ventana independiente en el modo multiventana, debes iniciarla en una nueva pila de tareas.

Cómo agregar compatibilidad con arrastrar y soltar

Los usuarios pueden arrastrar y soltar datos de una actividad a otra mientras las dos actividades comparten la pantalla. (Antes de Android 7.0, los usuarios solo podían arrastrar y soltar datos dentro de una sola actividad). A fin de agregar compatibilidad rápidamente para aceptar contenido que se soltó en widgets TextView editables, consulta OnReceiveContentListener en Jetpack. Para agregar compatibilidad más completa con la función de arrastrar y soltar, como habilitar la función de arrastrar contenido desde tu app, consulta el tema arrastrar y soltar.

DragAndDropPermissions
Es el objeto token responsable de especificar los permisos otorgados a la app que recibe datos mediante la funcionalidad de arrastrar y soltar.
View.startDragAndDrop()
Alias de View.startDrag(). Para habilitar la funcionalidad de arrastrar y soltar entre diferentes actividades, pasa la marca DRAG_FLAG_GLOBAL. Si necesitas otorgar permisos de URI a la actividad receptora, pasa los marcadores DRAG_FLAG_GLOBAL_URI_READ o DRAG_FLAG_GLOBAL_URI_WRITE según corresponda.
View.cancelDragAndDrop()
Cancela una operación de arrastre actualmente en curso. Solo lo puede llamar la app que originó la operación de arrastre.
View.updateDragShadow()
Reemplaza la sombra de arrastre por una operación de arrastre actualmente en curso. Solo lo puede llamar la app que originó la operación de arrastre.
Activity.requestDragAndDropPermissions()
Solicita los permisos para los URI de contenido que se pasan con el ClipData incluido en un DragEvent.
DragAndDropPermissions.release()
Actualiza los permisos necesarios para acceder a los datos en la URI de contenido que se proporcionan en ClipData. Si no llamas a este método, los permisos se actualizan automáticamente cuando se destruye la actividad que los contiene.

Instancias múltiples

Cada actividad raíz tiene su propia tarea, que se ejecuta en un proceso independiente y se muestra en su propia ventana. Para iniciar una instancia nueva de tu app en otra ventana, puedes iniciar actividades nuevas con la marca FLAG_ACTIVITY_NEW_TASK. Puedes combinar esto con algunos de los atributos de ventanas múltiples para solicitar una ubicación específica de la ventana nueva. Por ejemplo, una app de compras puede mostrar varias ventanas para comparar productos.

No confundas las instancias múltiples con un diseño de varios paneles, como un diseño de lista y detalles que usa SlidingPaneLayout. Esto se ejecuta en una sola ventana.

Ten en cuenta que cuando varias instancias se ejecutan en ventanas separadas en un dispositivo plegable, se pueden enviar una o más instancias a segundo plano si la cambia la forma. Por ejemplo, supongamos que un dispositivo está expandido y tiene dos instancias de apps ejecutándose en dos ventanas a ambos lados de la mitad superior. Si el dispositivo está plegado, una de las instancias podría finalizar en lugar de intentar ajustarse a las ventanas de ambas instancias en una pantalla más pequeña.

Cómo probar la compatibilidad de tu app con el modo multiventana

Independientemente de si tu app está orientada al nivel de API 24 o posterior, debes verificar cómo se comporta en el modo multiventana en caso de que un usuario intente iniciarla en un dispositivo que ejecute Android 7.0 o una versión posterior.

Cómo configurar un dispositivo de prueba

Si un dispositivo ejecuta Android 7.0 o una versión posterior, automáticamente admite el modo de pantalla dividida.

Si tu app está orientada al nivel de API 23 o inferior

Si tu app está orientada al nivel de API 23 o anterior y el usuario intenta usarla en el modo multiventana, el sistema cambia el tamaño de la app de manera forzosa, a menos que la aplicación declare una orientación fija.

Si tu app no declara una orientación fija, debes iniciarla en un dispositivo con Android 7.0 o una versión posterior, e intentar colocar la app en el modo de pantalla dividida. Cuando se modifique el tamaño de la app de manera forzosa, verifica que la experiencia del usuario sea aceptable.

Si la app declara una orientación fija, debes intentar colocarla en el modo multiventana. Cuando lo hagas, verifica que la app continúe en el modo de pantalla completa.

Si admites el modo multiventana

Si tu app está orientada al nivel de API 24 o posterior y no inhabilita la compatibilidad con el modo multiventana, verifica el siguiente comportamiento tanto en el modo de pantalla dividida como en el de forma libre.

  • Inicia la app en el modo de pantalla completa y, luego, cambia al modo multiventana manteniendo presionado el botón Recientes. Verifica que la app pase de un modo al otro correctamente.
  • Inicia la app directamente en el modo multiventana y verifica que se inicie en forma correcta. Puedes iniciar una app en el modo multiventana presionando el botón Recientes y, luego, manteniendo presionada la barra de título de la app y arrastrándola a una de las áreas resaltadas de la pantalla.
  • Cambia el tamaño de tu app en el modo de pantalla dividida arrastrando la línea divisoria. Verifica que la app cambie de tamaño sin presentar fallas y que estén visibles los elementos necesarios de la IU.
  • Si especificaste dimensiones mínimas para tu app, intenta cambiar el tamaño a dimensiones menores que las especificadas. Verifica que no puedas modificar el tamaño de la app para que sea más pequeña que la dimensión mínima especificada.
  • En todas las pruebas, verifica que el rendimiento de la app sea aceptable. Por ejemplo, verifica que la actualización de la IU después de cambiar el tamaño de la app no tarde mucho.

Lista de tareas para pruebas

Para verificar el rendimiento de tu app en el modo multiventana, realiza las siguientes operaciones. Debes probar estas operaciones tanto en el modo de pantalla dividida como en el modo multiventana, excepto cuando se indique algo diferente.

  • Ingresa en el modo multiventana y luego sal de él.
  • Pasa de tu app a otra y verifica que la app se comporte correctamente mientras esté visible pero inactiva. Por ejemplo, si tu app está reproduciendo un video, comprueba que este se siga reproduciendo mientras el usuario interactúa con otra aplicación.
  • En el modo de pantalla dividida, prueba a mover la barra divisora para agrandar y achicar la app. Realiza estas operaciones en las configuraciones una al lado de la otra y una encima de la otra. Verifica que la app no presente fallas, que las funcionalidades necesarias estén visibles y que la operación de cambio de tamaño no tarde mucho.
  • Realiza varias operaciones de cambio de tamaño en una sucesión rápida. Verifica que tu app no falle ni pierda memoria. Para obtener información sobre cómo comprobar el uso de memoria de tu app, utiliza el Generador de perfiles de memoria de Android Studio.
  • Usa tu app en diferentes configuraciones de ventanas y verifica que se comporte correctamente. Verifica que el texto sea legible y que los elementos de la IU sean lo suficientemente grandes como para interactuar con ellos.

Si inhabilitaste la compatibilidad con el modo multiventana

Si inhabilitaste la compatibilidad con el modo multiventana configurando android:resizeableActivity="false", debes iniciar tu app en un dispositivo con Android 7.0 o versiones posteriores, e intentar colocar la aplicación en los modos de forma libre y de pantalla dividida. Cuando lo hagas, verifica que la app continúe en el modo de pantalla completa.

Si deseas obtener más información sobre la compatibilidad con el modo multiventana en Android, consulta Cinco sugerencias para brindar compatibilidad con el modo multiventana en Android N y la app de ejemplo Multi-Window Playground.