Navegação condicional do Android com login

Este codelab faz parte do curso Android avançado no Kotlin. Você vai aproveitar mais este curso se fizer os codelabs em sequência, mas isso não é obrigatório. Todos os codelabs do curso estão listados na página de destino dos codelabs do Android avançado em Kotlin.


Este codelab se baseia no Implementing Login on Android with FirebaseUI. Você pode baixar o código inicial deste codelab se não tiver feito o anterior, mas talvez seja melhor concluir primeiro o codelab Implementar login no Android com o FirebaseUI.

Introdução

Se o app for compatível com login, um caso de uso comum é reservar partes dele apenas para usuários conectados. Por exemplo, talvez você queira reservar a tela Configurações do seu app para usuários conectados.

Nesses casos, use a navegação condicional para levar os usuários à tela adequada com base no estado de autenticação deles.

Neste codelab, você vai criar um app com base em um app existente para adicionar uma tela de configurações que só poderá ser acessada pelos usuários se eles fizerem login. Você vai usar os componentes de navegação do Android para essa tarefa.

O que você já precisa saber

O que você vai aprender

  • Como direcionar os usuários para as telas adequadas do seu app com base no status de login.

Atividades deste laboratório

  • Lide corretamente com a navegação dos usuários para a tela correta depois que eles fizerem login.
  • Impedir que os usuários acessem a tela Configurações se não estiverem conectados e redirecioná-los para a tela Login.

No codelab anterior, você trabalhou em um app que mostrava fatos sobre o Android. O app também permitia que os usuários fizessem login e logout. Neste codelab, você vai adicionar uma tela de configurações ao app atual. Ela só vai ficar acessível para o usuário se ele fizer login.

Se o usuário não estiver conectado, ao tentar acessar a tela de configurações, o app vai redirecioná-lo para a tela de login. Depois que o fluxo de login for concluído, o usuário vai voltar para a tela de configurações que tentou acessar originalmente.

Este codelab se baseia no Implementing Login on Android with FirebaseUI. Você pode baixar o código inicial deste codelab se não tiver feito o anterior, mas talvez seja melhor concluir primeiro o codelab Implementar login no Android com o FirebaseUI.

Para fazer o download do app de exemplo, você pode:

Fazer o download do ZIP


... ou clone o repositório do GitHub pela linha de comando usando o comando abaixo e mude para a ramificação start do repositório:

$  git clone https://github.com/googlecodelabs/android-kotlin-login-navigation

Depois de carregar o projeto no Android Studio:

  1. Execute o app em um emulador ou dispositivo físico para garantir que o ambiente foi configurado corretamente para iniciar o desenvolvimento.

Se tudo der certo, a tela inicial vai mostrar uma curiosidade divertida sobre o Android e um botão de login no canto superior esquerdo.


Recursos atuais do app inicial:

  • Se o usuário não estiver conectado, tocar no botão Fazer login vai iniciar o fluxo de login e permitir que ele faça login com um endereço de e-mail ou uma Conta do Google.
  • Se o usuário estiver conectado, o botão vai mudar para Fazer logout, permitindo que ele se desconecte.

Nesta tarefa, você vai adicionar um botão à tela inicial para que o usuário possa navegar até a tela de configurações. Na tela de configurações, o usuário pode escolher que tipo de curiosidades quer exibir na tela inicial. Na tela de configurações, é possível escolher ver fatos sobre o Android ou sobre o estado da Califórnia.

  1. Abra fragment_main.xml.
  2. Em fragment_main.xml,, adicione um botão Configurações aninhado em ConstraintLayout e posicione-o no canto superior direito da tela.

fragment_main.xml

<TextView
       android:id="@+id/settings_btn"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_margin="@dimen/text_margin"
       android:background="@color/colorAccent"
       android:padding="10dp"
       android:text="@string/settings_btn"
       android:textColor="#ffffff"
       android:textSize="20sp"
       app:layout_constraintRight_toRightOf="parent"
       app:layout_constraintTop_toTopOf="parent"/>
  1. Abra nav_graph.xml.
  2. Adicione uma ação dentro de mainFragment. O id da ação é action_mainFragment_to_customizeFragment, e o destino é customizeFragment.

nav_graph.xml

<fragment
       android:id="@+id/mainFragment"
       android:name="com.example.android.firebaseui_login_sample.MainFragment"
       android:label="MainFragment">
   <action
           android:id="@+id/action_mainFragment_to_settingsFragment"
           app:destination="@id/settingsFragment"/>
</fragment>
  1. Abra MainFragment.kt.
  2. Em onViewCreated(), defina um onClickListener para settings_btn. Assim, ao tocar no botão, o usuário será direcionado para customizeFragment.

MainFragment.kt

binding.settingsBtn.setOnClickListener {
   val action = MainFragmentDirections.actionMainFragmentToSettingsFragment()
   findNavController().navigate(action)
}
  1. Se você encontrar erros não resolvidos, recompile o app no menu Build para gerar e usar as novas ações de navegação criadas.
  2. Reinicie o app. Agora, deve haver um botão Configurações funcional no canto superior direito.
  3. Clique no botão que vai levar você à tela Configurações. A tela Configurações tem apenas uma opção: permitir que o usuário escolha o tipo de curiosidade que quer ver na tela inicial.
  4. Clique no botão "Voltar" do dispositivo Android para voltar à tela inicial.

Nesta tarefa, você vai adicionar código para navegar até a tela de login se o usuário tentar acessar a tela de configurações sem fazer login.

  1. Abra SettingsFragment.kt.
  2. Em onViewCreated(), observe o authenticationState e redirecione o usuário para LoginFragment se ele não estiver autenticado.

SettingsFragment.kt

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
   super.onViewCreated(view, savedInstanceState)
   val navController = findNavController()
   viewModel.authenticationState.observe(viewLifecycleOwner, Observer { authenticationState ->
       when (authenticationState) {
           LoginViewModel.AuthenticationState.AUTHENTICATED -> Log.i(TAG, "Authenticated")
           // If the user is not logged in, they should not be able to set any preferences,
           // so navigate them to the login fragment
           LoginViewModel.AuthenticationState.UNAUTHENTICATED -> navController.navigate(
               R.id.loginFragment
           )
           else -> Log.e(
               TAG, "New $authenticationState state that doesn't require any UI change"
           )
       }
   })
}

Como o app leva o usuário à tela de login se ele tentar acessar a tela de configurações, o app também precisa processar o comportamento do botão "Voltar" na tela de login. Se o app não personalizar o comportamento do botão "Voltar", o usuário vai ficar preso em um loop infinito de tentativas de voltar para a tela de configurações, mas será redirecionado para a tela de login novamente.

  1. Abra LoginFragment.kt.
  2. Em onViewCreated(), processe as ações do botão "Voltar" levando o usuário de volta ao MainFragment.

LoginFragment.kt

// If the user presses the back button, bring them back to the home screen
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
   navController.popBackStack(R.id.mainFragment, false)
}
  1. Reinicie o app e confirme se, caso você não tenha feito login, as tentativas de acessar a tela de configurações agora vão redirecionar você para o fluxo de login.

Embora você tenha redirecionado o usuário para o login, não processou o que acontece depois que ele faz login. Por isso, as tentativas de login vão parecer que não estão funcionando. Isso será corrigido na próxima etapa.

Até agora, você configurou seu app para redirecionar o usuário à tela de login se ele tentar acessar a tela de configurações sem fazer login.

No entanto, depois de passar pelo fluxo de login, você volta para a tela de login. Essa não é uma boa experiência do usuário e pode ser confusa.

Para oferecer a experiência ideal, o app precisa levar o usuário de volta à tela de configurações depois que ele fizer login.

  1. Ainda em LoginFragment.kt, em qualquer lugar em onViewCreated(), observe o authenticationState e navegue de volta para SettingsFragment quando o usuário for autenticado.

LoginFragment.kt

// Observe the authentication state so we can know if the user has logged in successfully.
// If the user has logged in successfully, bring them back to the settings screen.
// If the user did not log in successfully, display an error message.
viewModel.authenticationState.observe(viewLifecycleOwner, Observer { authenticationState ->
   when (authenticationState) {
      // Since our login flow is only one screen instead of multiple 
      // screens, we can utilize popBackStack(). If our login flow 
      // consisted of multiple screens, we would have to call 
      // popBackStack() multiple times.
       LoginViewModel.AuthenticationState.AUTHENTICATED -> navController.popBackStack()
       else -> Log.e(
           TAG,
           "Authentication state that doesn't require any UI change $authenticationState"
       )
   }
})
  1. Execute o app novamente e confirme se, ao fazer login, você acessa a página Configurações em vez da página Login.

Confira o app completo com todo o código da solução neste repositório do GitHub: https://github.com/googlecodelabs/android-kotlin-login-navigation.

Neste codelab, você aprendeu as práticas recomendadas para criar uma boa experiência do usuário em um app que oferece suporte ao login. Ao observar o status de autenticação do app, você conseguiu determinar quais telas o usuário pode acessar e redirecioná-lo para a tela de login quando necessário.

Para saber mais sobre as práticas recomendadas de navegação no Android, confira os seguintes recursos:

Documentação do desenvolvedor Android:

Codelabs:

Para acessar links de outros codelabs deste curso, consulte a página inicial dos codelabs do curso Android avançado no Kotlin.