Suporte a telas conectadas

As telas conectadas estendem a experiência do Modo Janela para Computador a smartphones comuns, oferecendo aos usuários acesso a telas grandes em dispositivos móveis. Essa capacidade abre novas possibilidades de interação com apps e produtividade do usuário.

Todos os recursos exclusivos do Modo Janela para Computador se aplicam a telas conectadas. Quando você conecta um smartphone a uma tela, o estado do smartphone permanece inalterado, e uma sessão de computador em branco é iniciada na tela conectada. O dispositivo e a tela atuam como dois sistemas individuais, com apps específicos para cada tela.

Figura 1. Smartphone conectado a uma tela externa, com uma sessão de computador na tela enquanto o smartphone mantém o próprio estado.

Se você conectar um dispositivo com o Modo Janela para Computador ativado, como um tablet, a um monitor externo, a sessão de computador será estendida para as duas telas. As duas telas funcionam como um sistema contínuo. Essa configuração permite que janelas, conteúdo e o cursor se movam livremente entre as duas telas.

Figura 2. Tablet conectado a um monitor externo, estendendo a sessão de computador para as duas telas.

Para oferecer suporte a telas conectadas de maneira eficaz, é necessário prestar atenção a vários aspectos do design e da implementação do app. As práticas recomendadas a seguir garantem uma experiência do usuário tranquila e produtiva.

Processar mudanças dinâmicas de tela

Muitos apps são criados com a suposição de que o Display objeto e as características dele não vão mudar durante o ciclo de vida do app. No entanto, quando um usuário conecta ou desconecta um monitor externo ou até mesmo move uma janela do app entre telas, o objeto Display subjacente associado ao contexto ou à janela do app pode mudar. As propriedades da tela, como tamanho, resolução, taxa de atualização, suporte a HDR e densidade, podem ser diferentes. Se você fixar valores no código com base na tela do smartphone, por exemplo, é provável que os layouts sejam interrompidos em uma tela externa.

As telas externas também podem ter densidades de pixel muito diferentes. É necessário garantir que o app responda corretamente às mudanças de densidade. Isso envolve o uso de pixels de densidade independente (dp) para layouts, o fornecimento de recursos específicos de densidade e a garantia de que a interface seja dimensionada adequadamente.

Se uma atividade estiver em execução em uma tela externa quando ela for desconectada, o sistema vai mover a atividade para a tela principal. A movimentação aciona mudanças de configuração, como tamanho e densidade da tela, que podem fazer com que a atividade seja recriada. O app precisa processar a mudança de configuração salvando e restaurando o estado da interface para evitar perda de dados ou uma experiência do usuário confusa.

Usar o contexto certo

Usar o contexto certo é fundamental em ambientes com várias telas. Ao acessar recursos, o contexto da atividade (exibido) é diferente do contexto do app (que não é exibido).

O contexto da atividade contém informações sobre a tela e é sempre ajustado para a área da tela em que a atividade aparece. Isso permite que você tenha as informações corretas sobre a densidade ou as métricas de janela de exibição do app. Use sempre o contexto da atividade (ou outro contexto baseado na interface) para acessar informações sobre a janela ou tela atual. Isso também afeta algumas APIs do sistema que usam informações do contexto.

No Jetpack Compose, é possível acessar informações específicas da tela usando CompositionLocal objetos como LocalConfiguration.current e LocalDensity.current. Quando uma atividade ou janela se move entre telas, a configuração do dispositivo muda, acionando a recomposição com novas métricas de exibição. Os objetos CompositionLocal permitem que a interface se adapte perfeitamente.

Receber informações da tela

É possível usar a classe Display para receber informações como tamanho de exibição, densidade ou flags. Use o serviço do sistema DisplayManager para receber as telas disponíveis. Para identificar telas externas, filtre o Display.DEFAULT_DISPLAY, que normalmente é a tela integrada do smartphone ou 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 }

Gerenciar a inicialização e a configuração da atividade

Com telas conectadas, os apps podem especificar em qual tela um app deve ser executado quando é iniciado ou quando cria outra atividade. Esse comportamento depende do modo de inicialização da atividade definido no arquivo de manifesto, bem como das flags de intents e opções definidas pela entidade que está iniciando a atividade.

Quando uma atividade é movida para uma tela secundária, o app pode passar por uma atualização de contexto, redimensionamento de janela e mudanças de configuração e recursos. Se a atividade processar a mudança de configuração, ela será notificada em onConfigurationChanged(). Caso contrário, a atividade será reiniciada.

Se o modo de inicialização selecionado para uma atividade permitir várias instâncias, a inicialização em uma tela secundária pode criar uma nova instância da atividade. As duas atividades são retomadas ao mesmo tempo, o que pode ser benéfico para determinados cenários de multitarefas.

É possível iniciar uma atividade em uma tela específica usando ActivityOptions. O launchDisplayId exige o Android 8 (nível 26 da API) ou mais recente.

// 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.
}

Evitar listas de permissões de dispositivos

Às vezes, os apps restringem a interface e os recursos de tela grande a dispositivos selecionados por meio de uma lista de permissões ou verificando BUILD.MODEL e o tamanho de exibição integrado. Essa abordagem não é eficaz para telas conectadas, porque praticamente qualquer dispositivo pode ser conectado a uma tela grande, e o modelo do dispositivo não muda quando uma tela externa é conectada.

Em vez de usar listas de permissões ou verificar BUILD.MODEL e o tamanho de exibição integrado, verifique as métricas de janela ou os recursos do dispositivo no tempo de execução para tomar decisões de interface. Use as APIs do Jetpack WindowManager ou as classes de tamanho de janela para criar layouts responsivos e adaptáveis para vários tamanhos e densidades de tela.

Oferecer suporte a periféricos externos

Quando os usuários se conectam a uma tela externa, eles costumam criar um ambiente mais parecido com um computador. Isso geralmente envolve o uso de teclados, mouses, trackpads, webcams, microfones e alto-falantes externos. É necessário garantir que o app funcione perfeitamente com esses periféricos. Isso inclui o processamento de atalhos de teclado, o gerenciamento de interações do ponteiro do mouse, o suporte correto a câmeras ou microfones externos e o respeito ao roteamento de saída de áudio. Para mais detalhes, consulte Compatibilidade de entrada em telas grandes.

Aumentar a produtividade do usuário

As telas conectadas oferecem uma oportunidade significativa para melhorar a produtividade do usuário. Agora você tem as ferramentas para criar apps para dispositivos móveis que podem oferecer experiências comparáveis a aplicativos para computador. Considere implementar os seguintes recursos para aumentar a produtividade do usuário:

  • Permitir que os usuários abram várias instâncias do mesmo app. Isso é inestimável para tarefas como comparar documentos, gerenciar conversas diferentes ou visualizar vários arquivos simultaneamente.
  • Permitir que os usuários compartilhem dados avançados dentro e fora do app com a função arrastar e soltar.
  • Ajudar os usuários a manter o fluxo de trabalho em mudanças de configuração por implementar um sistema robusto de gerenciamento de estado.

Ao seguir estas diretrizes e usar os exemplos de código fornecidos, você pode criar apps que se adaptam perfeitamente a telas conectadas, oferecendo aos usuários uma experiência mais rica e produtiva.