Multijanela no Android N: o que os desenvolvedores precisam saber para aproveitar ao máximo

Fornecemos uma visão geral do que o futuro suporte a múltiplas janelas no Android N significa para os desenvolvedores e como tirar o melhor proveito dele!

O suporte a várias janelas é um recurso interessante que esperamos no Android N, e há muito tempo que queríamos que estivesse disponível em todos os dispositivos. Porém, para que seja uma experiência agradável, os desenvolvedores podem ter que fazer algumas alterações em seus aplicativos para suportá-lo corretamente.

Uma das sessões do Google I/O foi para os desenvolvedores aprenderem sobre as novas APIs e as mudanças comportamentais do sistema que o suporte a múltiplas janelas traz.

A sessão foi apresentada por Wale Ogunwale, gerente técnico líder do Android ActivityManager e Componentes da estrutura WindowManager – ele e sua equipe são os responsáveis ​​pelas múltiplas janelas no Android.

Você pode assistir o Sessão em modo multijanela no YouTube, mas também fornecemos uma visão geral da sessão aqui.

N apresenta três modos diferentes de múltiplas janelas:
  • Modo de tela dividida: este é o modo disponível por padrão. Como o nome indica, permite abrir dois aplicativos lado a lado.
  • Modo de forma livre: os fabricantes podem habilitar isso em dispositivos maiores, o que permite aos usuários redimensionar atividades livremente, além do modo de tela dividida.
  • Modo imagem em imagem: voltado para dispositivos Android TV, esse modo é destinado para que players de vídeo sejam executados em uma janela fixada enquanto o usuário interage com outros aplicativos.
Modo de tela dividida do Android NModo Android N PiP
Vale a pena notar isso. já cobrimos várias janelas em N antes e fizemos algumas críticas ao sistema atual. Com isso em mente, esperamos que o modo de forma livre se aproxime um pouco mais do modo picture-in-picture, pois teria aplicações úteis em todos os dispositivos.
Ativar o suporte a múltiplas janelas em seus aplicativos é simples: você não precisa fazer nada se já estiver visando N. Caso opte por desativar a multijanela, você pode fazer isso definindo o. android: resizeableActivity atributo de atividade em seu manifesto para. false. Isso só deve ser feito se for realmente justificado, pois faz com que seu aplicativo se destaque de maneira negativa por sempre iniciar em modo de tela cheia mesmo se o usuário (ou outro aplicativo) tentar iniciá-lo em várias janelas modo. É importante observar que os atributos de uma atividade raiz se aplicam a todas as atividades dentro da sua pilha de tarefas. Em outras palavras, se você tiver uma atividade que possa ser iniciada por outros aplicativos, certifique-se de que ela suporta o modo multijanela já que você não pode garantir que outros aplicativos iniciarão sua atividade em uma nova tarefa usando. Intent#FLAG_ACTIVITY_NEW_TASK O suporte ao modo Picture-in-picture deve ser declarado explicitamente por meio do. android: supportsPictureInPicture atributo. Observe que este atributo é ignorado se. android: resizeableActivity é. false Os atributos .Layout podem ser usados ​​para definir dimensões e posicionamento padrão para janelas de formato livre ou para especificar uma largura ou altura mínima para modos de formato livre e tela dividida:
  • android: defaultWidth/android: defaultHeight: as dimensões padrão da atividade (modo de forma livre).
  • android: gravity: a posição inicial da atividade (modo de forma livre).
  • android: minimalWidth/android: minimalHeight: as dimensões mínimas da atividade (modos de forma livre e tela dividida)
Você pode encontrar um exemplo de código em. Aplicativo de amostra Multi-Window Playground do Google no GitHub: AndroidManifest.xml.
Com a introdução do suporte para múltiplas janelas, pode ser necessário verificar algumas coisas em seus aplicativos para ter certeza de que funcionam corretamente.

Compreendendo o ciclo de vida da atividade

O. ciclo de vida da atividade permanece inalterado no modo de múltiplas janelas: Ciclo de vida básico da atividade Android Dito isto, algumas diferenças sutis entre os estados de atividade podem resultar em comportamento não intencional que você normalmente não notaria antes de N. É importante saber disso. Activity#onResume() e. Activity#onPause() são chamados quando seu aplicativo ganha ou perde o foco, mas não necessariamente quando ele inicia ou deixa de ficar visível. (Lembre-se de que apenas um aplicativo pode ter foco em um determinado momento.) Para aplicativos que atualizam o conteúdo constantemente (por exemplo, reprodução de vídeo), certifique-se de iniciar e interromper atualizações de conteúdo em. Activity#onStart() e. Activity#onStop() em vez de. Não fazer isso para aplicativos de vídeo, por exemplo, significará que a reprodução só ocorrerá se o aplicativo estiver focado, o que anula o propósito do modo de múltiplas janelas. O aplicativo oficial do YouTube teve um problema semelhante quando o Android N Developer Preview foi lançado pela primeira vez.

Lidando com alterações de tempo de execução

Quando um aplicativo é colocado no modo de múltiplas janelas, algumas configurações do dispositivo serão alteradas. Você pode permitir que sua atividade seja reiniciada (nesse caso. retendo fragmentos pode ser uma boa ideia, se sua atividade precisar realizar uma operação intensiva na inicialização), ou optar por fazê-lo. lidar com as alterações de configuração explicitamente em vez de. Quatro configurações de dispositivos podem mudar ao entrar ou dentro do modo de múltiplas janelas: screenSize, smallestScreenSize, screenLayout e. orientation. Consulte o. Documentação para desenvolvedores Android para obter mais informações sobre cada atributo, mas observe isso. orientation não se refere mais à orientação do dispositivo neste caso. Em vez disso, apenas indica se a largura da sua atividade é maior que a altura (paisagem) ou not (retrato). A declaração de que sua atividade irá lidar com essas mudanças pode ser feita a partir do manifesto:
android: name=".MyActivity"android: configChanges="screenSize|smallestScreenSize|screenLayout|orientation"/>
Tenha em mente que isso significa que você realmente precisará lidar com essas alterações. Activity#onConfigurationChanged(), atualizando manualmente as visualizações ou recarregando alguns recursos.

Recursos desativados no modo multijanela

Alguns recursos do sistema não serão afetados pelas suas atividades no modo de múltiplas janelas:
  • Alterações na barra de status e na barra de navegação, como escurecer/ocultar as barras do sistema ou usar o modo imersivo, não terão efeito. Isso faz sentido, pois sua atividade ocupa apenas parte da tela.
  • O android: screenOrientation O atributo de atividade também não tem efeito no modo multi-janela: como sua atividade será redimensionável, não faz mais sentido que ela tenha uma orientação fixa.
Novos retornos de chamada foram adicionados para eventos de múltiplas janelas, bem como métodos para consultar o estado atual.
  • Activity#onMultiWindowModeChanged(boolean inMultiWindow): chamado quando o estado da atividade muda de tela cheia para múltiplas janelas e vice-versa.
  • Activity#onPictureInPictureModeChanged(boolean inPictureOnPicture): chamado quando o estado da atividade muda para/do modo PIP.
  • Activity#isInMultiWindowMode()/Activity#isInPictureInPictureMode(): retorna se a atividade está no modo multi-janela/picture-in-picture ou não.
  • Activity#overlayWithDecorCaption(boolean overlay): para janelas de formato livre, este método pode ser usado para fazer com que a legenda (a barra usada para arrastar a janela) se sobreponha ao conteúdo em vez de empurrá-lo para baixo.
PS. Exceto por. Activity#overlayWithDecorCaption(), esses métodos também são fornecidos pelo. Fragment aula.

Iniciando atividades no modo multijanela

  • Activity#enterPictureInPictureMode() pode ser usado para colocar uma atividade no modo picture-in-picture. Observe que as atividades no modo PiP não são notificadas sobre eventos de entrada – use MediaSession#setMediaButtonReceiver() se você quiser lidar com tais eventos. Certifique-se também de verificar o site de desenvolvedores Android se estiver interessado em Imagem em imagem no Android N.
  • Se o dispositivo estiver no modo de tela dividida, você poderá instruir o sistema a iniciar outra atividade próxima à sua usando o botão Intent#FLAG_ACTIVITY_LAUNCH_ADJACENT bandeira. A bandeira não tem efeito se não estiver no modo de tela dividida.
  • Se o dispositivo estiver no modo de forma livre, ActivityOptions#setLaunchBounds() pode ser usado para especificar as dimensões e localização da nova atividade na tela.
Para obter exemplos de código, confira o aplicativo de exemplo Multi-Window Playground: exemplo de atividade adjacente, exemplo de limites de lançamento.

Arrastar e soltar

Embora o suporte para arrastar e soltar exista desde o Honeycomb, anteriormente só era possível dentro da mesma atividade. É neve. suportado em múltiplas janelas também. Implementar isso parece ser. basicamente o mesmo de antes, com algumas adições para arrastar e soltar entre atividades:
  • View#startDragAndDrop()
    • Novo apelido para View#startDrag().
    • Para ativar o recurso de arrastar e soltar entre atividades, passe o novo sinalizador View#DRAG_FLAG_GLOBAL.
    • Se você precisar conceder permissões de URI para a atividade do destinatário, passe os novos sinalizadores View#DRAG_FLAG_GLOBAL_URI_READ ou View#DRAG_FLAG_GLOBAL_URI_WRITE, como apropriado.
  • View#updateDragShadow()
    • Substitui a sombra de arrastar por uma operação de arrastar em andamento. Só pode ser chamado pelo aplicativo que originou a operação de arrastar.
  • View#cancelDragAndDrop()
    • Cancela uma operação de arrastar em andamento. Só pode ser chamado pelo aplicativo que originou a operação de arrastar.
  • É possível verificar se um dispositivo suporta os modos de forma livre ou picture-in-picture por meio de PackageManager#hasSystemFeature(), usando PackageManager#FEATURE_FREEFORM_WINDOW_MANAGEMENT e PackageManager#FEATURE_FREEFORM_PICTURE_IN_PICTURE respectivamente.
  • O android: windowBackground O atributo pode ser usado como drawable de fundo, se a atividade estiver sendo redimensionada e sua renderização estiver atrasada. Se android: windowBackground está indefinido, android: windowBackgroundFallback é usado em seu lugar. Consulte o aplicativo de amostra Multi-Window Playground para obter um exemplo.
Wale ofereceu algumas práticas recomendadas para garantir que seus usuários tenham a melhor experiência possível:
  • Lidar com mudanças de modo elegantemente:
    • Mantenha a consistência da UI independentemente da orientação. Não faça com que os elementos mudem de posição para permitir transições suaves.
    • Expandindo o acima, não alterne entre layouts muito diferentes para layouts de telefone/tablet. Em vez disso, adapte o layout do tablet para tamanhos menores para obter consistência.
  • Certifique-se de que suas atividades se adaptem a tamanhos pequenos por seguindo os padrões do Material Design.
  • Usar FLAG_ACTIVITY_LAUNCH_ADJACENT quando faz sentido proporcionar uma experiência mais agradável no modo de tela dividida.
  • Declarar incompatibilidade de redimensionamento apenas quando justificado. Como discutimos acima, isso faz com que seu aplicativo se destaque de maneira negativa.
Wale encerrou a sessão oferecendo alguns recursos úteis adicionais:
  • Documentação multijanela.
  • Diretrizes do Material Design para modo de tela dividida.
  • Exemplo de aplicativo multijanela.