Este tutorial faz parte do curso Android avançado em Kotlin. Você obterá o máximo valor deste curso se trabalhar com os tutoriais em sequência, mas isso não é obrigatório. Todos os tutoriais do curso estão listados na página de destino Android avançado em Kotlin.

Introdução

Ao permitir que os usuários façam login e criem uma identidade em seu aplicativo, você pode fornecer a eles mais maneiras de interagir com o aplicativo.

Com contas personalizadas, os usuários podem personalizar sua experiência no aplicativo, interagir com outros usuários e ter seus dados persistidos e transferidos se estiverem usando o aplicativo em outro dispositivo (como web ou um novo telefone).

Neste tutorial, você aprenderá os fundamentos de como oferecer suporte ao login para seu aplicativo usando a biblioteca FirebaseUI. Essa biblioteca torna mais fácil construir um fluxo de login e lida com o trabalho de gerenciamento de contas de usuário para você.

O que você já deveria saber

O que você aprenderá

O que você vai fazer

Saiba mais sobre LiveData e ViewModel

Para o aplicativo neste tutorial, você precisa de um conhecimento básico de LiveData e ViewModel. Leia as visões gerais LiveData e ViewModel se quiser uma breve visão geral desses conceitos.

Você também pode passar pelo curso Desenvolvimento de aplicativos Android com Kotlin para aprender sobre os tópicos Fundamentos de Android que encontrará como parte deste tutorial. Esse curso está disponível como um curso Udacity e um curso tutoriais.

Neste tutorial, você criará um aplicativo que exibe curiosidades sobre o Android. Mais importante ainda, o aplicativo terá um botão Login/Logout. Quando o usuário está conectado ao aplicativo, qualquer fato Android exibido incluirá uma saudação para o usuário adicionar um toque de personalização.

Baixe o aplicativo de amostra, você pode:

Baixe o Zip

... ou clone o repositório GitHub da linha de comando usando o seguinte comando e mude para o branch start do repo:

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

Importante: como você integrará o aplicativo para usar o Firebase, o aplicativo inicial requer algumas configurações para ser compilado e executado. Você fará isso na próxima etapa do tutorial.

Etapa 1: criar um projeto Firebase

Antes de adicionar o Firebase ao seu aplicativo Android, você precisa criar um projeto do Firebase para se conectar ao seu aplicativo Android.

  1. No Firebase console, clique em Add project.
  2. Selecione ou insira um Project name. Você pode nomear seu projeto de qualquer maneira, mas tente escolher um nome relevante para o aplicativo que você está construindo.
  3. Clique em Continue.
  4. Você pode pular a configuração do Google Analytics e escolher a opção Not Right Now.
  5. Clique em Create Project para concluir a configuração do projeto Firebase.

Etapa 2: registre seu aplicativo no Firebase

Agora que você tem um projeto Firebase, pode adicionar seu aplicativo Android a ele.

  1. No centro da página de visão geral do projeto do console do Firebase, clique no ícone Android para iniciar o fluxo de trabalho de configuração.
  2. Insira o ID do aplicativo do seu aplicativo no campo Android package name. Certifique-se de inserir o ID que seu aplicativo está usando, pois você não pode adicionar ou modificar esse valor depois de registrar seu aplicativo com o projeto Firebase.
  1. Um ID de aplicativo às vezes é chamado de nome de pacote.
  2. Encontre este ID de aplicativo em seu arquivo Gradle do módulo (nível de aplicativo), geralmente app/build.gradle (ID de exemplo: com.yourcompany.yourproject).
  3. Insira o certificado de assinatura de depuração SHA-1. Você pode gerar essa chave digitando o seguinte comando em seu terminal de linha de comando.
keytool -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v -storepass android
  1. Clique em Register app.

Etapa 3: adicione o arquivo de configuração do Firebase ao seu projeto

Adicione o arquivo de configuração do Firebase Android ao seu aplicativo:

  1. Clique em Download google-services.json para obter seu arquivo de configuração do Firebase Android (google-services.json).
  1. Mova seu arquivo de configuração para o diretório do módulo (nível de aplicativo) do seu aplicativo.

Etapa 4: configure seu projeto Android para habilitar produtos Firebase

  1. Para habilitar produtos Firebase em seu aplicativo, adicione o plug-in google-services aos seus arquivos Gradle.
  1. No arquivo Gradle de nível raiz (nível de projeto) (build.gradle), adicione regras para incluir o plug-in de serviços do Google. Verifique se você também possui o repositório Maven do Google.

build.gradle

buildscript {

  repositories {
    // Check that you have the following line (if not, add it):
    google()  // Google's Maven repository
  }

  dependencies {
    // ...

    // Add the following line:
    classpath 'com.google.gms:google-services:4.3.0'  // Google Services plugin
  }
}

allprojects {
  // ...

  repositories {
    // Check that you have the following line (if not, add it):
    google()  // Google's Maven repository
    // ...
  }
}
  1. No seu arquivo Gradle do módulo (nível do aplicativo) (geralmente app/build.gradle), adicione uma linha ao final do arquivo.

app/build.gradle

apply plugin: 'com.android.application'

android {
  // ...
}

// Add the following line to the bottom of the file:
apply plugin: 'com.google.gms.google-services'  // Google Play services Gradle plugin

Etapa 4: adicionar dependência do Firebase

Neste tutorial, o principal motivo para integrar o Firebase é ter uma maneira de criar e gerenciar usuários. Para isso, você precisa adicionar uma biblioteca do Firebase que permite implementar a funcionalidade de login / logout.

  1. Adicione a seguinte dependência em seu arquivo build.gradle (Module:app) para que você possa usar o SDK em seu aplicativo. O SDK firebase-auth permite o gerenciamento de usuários autenticados de seu aplicativo.

app / build.gradle:

implementation 'com.firebaseui:firebase-ui-auth:5.0.0'
  1. Sincronize seu projeto com arquivos gradle para se certificar de que todas as dependências estão disponíveis para seu aplicativo. Se não for solicitado, selecione File > Sync Project with Gradle Files no Android Studio ou na barra de ferramentas.

Etapa 5: execute o aplicativo e inspecione o código

Execute o aplicativo em um emulador ou dispositivo físico para garantir que seu ambiente seja configurado com êxito para iniciar o desenvolvimento.

Se for bem-sucedido, você verá a tela inicial exibir uma curiosidade sobre o Android e um botão de login no canto superior esquerdo. Tocar no botão de login ainda não faz nada.

Em um alto nível, este é um aplicativo de atividade única com vários fragmentos. O MainFragment contém toda a IU que você vê na tela abaixo. (Você trabalhará com o LoginFragment e o SettingsFragment em um tutorial de acompanhamento.)

Familiarize-se com o código. Em particular, observe o seguinte:

  1. FirebaseUserLiveData é a classe que você implementará para observar o usuário atual do Firebase associado ao aplicativo. Você usará a instância FirebaseAuth como um ponto de entrada para obter essas informações do usuário em uma etapa posterior.
  2. O MainFragment está vinculado ao LoginViewModel. LoginViewModel é a classe que você incluirá uma variável authenticationState do tipo FirebaseUserLiveData. MainFragment pode então observar o valor desta variável authenticationState para atualizar a IU de acordo.

Nesta etapa, você usará o Console do Firebase para configurar os métodos de autenticação que deseja que seu aplicativo suporte. Para este tutorial, você se concentrará em permitir que os usuários façam login com um endereço de e-mail fornecido por eles ou com sua conta do Google.

  1. Navegue até o Console do Firebase. (Observação: se você ainda estiver no fluxo de trabalho Adicionar Firebase, clique no X no canto superior esquerdo para retornar ao console.
  2. Selecione seu projeto, se ainda não estiver nele.
  3. Abra a navegação à esquerda e selecione Develop > Authentication.

  1. Selecione a guia Sign-in method na barra de navegação superior.

  1. Clique na linha Email/Password.
  2. No pop-up, alterne a chave Enabled. Deixe a opção Email link desativada.
  3. Clique em Save.
  4. De volta à guia Sign-in method da janela Authentication, clique na linha Google.
  5. Alterne a opção Enabled, insira um Project support email e clique em Save.

Nesta tarefa, você implementará o recurso de login para seus usuários.

  1. Abra MainFragment.kt. Observe que o objeto authBbutton não está configurado para tratar com nenhuma entrada do usuário.
  2. Em onViewCreated(), implemente setOnClickListener para authButton para chamar launchSignInFlow():

MainFragment.kt

binding.authButton.setOnClickListener { launchSignInFlow() }
  1. Procure o método launchSignInFlow() em MainFragment.kt. Atualmente contém um TODO.
  2. Conclua a função launchSignInFlow() conforme mostrado abaixo.

MainFragment.kt

private fun launchSignInFlow() {
   // Give users the option to sign in / register with their email or Google account.
   // If users choose to register with their email,
   // they will need to create a password as well.
   val providers = arrayListOf(
       AuthUI.IdpConfig.EmailBuilder().build(), AuthUI.IdpConfig.GoogleBuilder().build()

       // This is where you can provide more ways for users to register and 
       // sign in.
   )

   // Create and launch the sign-in intent.
   // We listen to the response of this activity with the
   // SIGN_IN_REQUEST_CODE.
   startActivityForResult(
       AuthUI.getInstance()
           .createSignInIntentBuilder()
           .setAvailableProviders(providers)
           .build(),
       SIGN_IN_REQUEST_CODE
   )
}

Isso permite que os usuários se cadastrem e façam login com seu endereço de e-mail ou conta do Google. Se o usuário optar por se registrar com seu endereço de e-mail, a combinação de e-mail e senha que ele criará será exclusiva para seu aplicativo. Isso significa que eles poderão fazer login em seu aplicativo usando essa combinação de endereço de e-mail e senha. No entanto, isso não significa que eles também podem fazer login em qualquer outro aplicativo compatível com o Firebase usando as mesmas credenciais.

  1. Em MainFragment.kt, você pode ouvir o resultado do processo de login implementando o método onActivityResult(), conforme mostrado abaixo. Desde que você iniciou o processo de login com SIGN_IN_REQUEST_CODE, você também pode ouvir o resultado do processo de login filtrando quando SIGN_IN_REQUEST_CODE é passado de volta para onActivityResult(). Comece por ter algumas declarações de registro para saber se o usuário fez login com sucesso:

MainFragment.kt

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
   super.onActivityResult(requestCode, resultCode, data)
   if (requestCode == SIGN_IN_REQUEST_CODE) {
       val response = IdpResponse.fromResultIntent(data)
       if (resultCode == Activity.RESULT_OK) {
           // User successfully signed in.
           Log.i(TAG, "Successfully signed in user ${FirebaseAuth.getInstance().currentUser?.displayName}!")
       } else {
           // Sign in failed. If response is null, the user canceled the
           // sign-in flow using the back button. Otherwise, check
           // the error code and handle the error.
           Log.i(TAG, "Sign in unsuccessful ${response?.error?.errorCode}")
       }
   }
}

Seu aplicativo agora deve ser capaz de registrar e fazer login de usuários!

  1. Execute o aplicativo e verifique se tocar no botão Login abre a tela de login.
  2. Agora você pode fazer login com seu endereço de e-mail e uma senha ou com sua conta do Google.
  3. Não haverá nenhuma mudança na IU após o login (você implementará a atualização da IU na próxima etapa), mas se tudo estiver funcionando corretamente, você deverá ver a mensagem de registro Usuário conectado com sucesso $ {seu nome} ! depois de passar pelo fluxo de registro.
  4. Você também pode verificar se seu aplicativo agora tem um usuário registrado no Console do Firebase. Navegue até Develop > Authentication e abra a guia Users.

Nesta tarefa, você implementará a lógica necessária para atualizar a IU com base no estado de autenticação. Quando o usuário está conectado, você pode personalizar sua tela inicial exibindo seu nome. Você também alterará o botão Login para ser um botão Logout quando o usuário estiver conectado.

  1. Abra a classe FirebaseUserLiveData.kt, que já foi criada para você. A primeira coisa que você precisa fazer é fornecer uma maneira para outras classes no aplicativo saberem quando um usuário efetuou login ou logout.
  2. Como você está usando a biblioteca FirebaseAuth, pode acompanhar as alterações do usuário conectado usando o retorno de chamada FirebaseUser.AuthStateListener que é implementado para você como parte do FirebaseUI. Esse retorno de chamada é acionado sempre que um usuário faz login ou sai do seu aplicativo.
  3. Observe que FirebaseUserLiveData.kt define a variável authStateListener. Você usará esta variável para armazenar o valor do LiveData. A variável authStateListener foi criada para que você possa iniciar e parar de ouvir corretamente as alterações no estado de autenticação com base no estado de seu aplicativo. Por exemplo, se o usuário colocar o aplicativo em segundo plano, ele deve parar de ouvir as alterações de estado de autenticação para evitar possíveis vazamentos de memória.
  4. Atualize authStateListener para que o valor de seu FirebaseUserLiveData corresponda ao usuário Firebase atual.

FirebaseUserLiveData.kt

private val authStateListener = FirebaseAuth.AuthStateListener { firebaseAuth ->
   value = firebaseAuth.currentUser
}
  1. Abra LoginViewModel.kt.
  2. Em LoginViewModel.kt, crie uma variável authenticationState baseada no objeto FirebaseUserLiveData que você acabou de implementar. Ao criar esta variável authenticationState, outras classes agora podem consultar se um usuário está conectado ou não por meio do LoginViewModel.

LoginViewModel.kt

val authenticationState = FirebaseUserLiveData().map { user ->
   if (user != null) {
       AuthenticationState.AUTHENTICATED
   } else {
       AuthenticationState.UNAUTHENTICATED
   }
}
  1. Abra MainFragment.kt.
  2. Em MainFragment.ktobserveAuthenticationState(), você pode usar a variável authenticationState que acabou de adicionar em LoginViewModel e altere a IU de acordo. Se houver um usuário conectado, authButton deve exibir Logout.

MainFragment.kt

private fun observeAuthenticationState() {
   val factToDisplay = viewModel.getFactToDisplay(requireContext())

   viewModel.authenticationState.observe(viewLifecycleOwner, Observer { authenticationState ->
       when (authenticationState) {
           LoginViewModel.AuthenticationState.AUTHENTICATED -> {
               binding.authButton.text = getString(R.string.logout_button_text)
               binding.authButton.setOnClickListener {
                   // TODO implement logging out user in next step
               }

                // TODO 2. If the user is logged in, 
                 // you can customize the welcome message they see by
                 // utilizing the getFactWithPersonalization() function provided

           }
           else -> {
               // TODO 3. Lastly, if there is no logged-in user, 
                // auth_button should display Login and
                //  launch the sign in screen when clicked.
           }
       }
   })
}
  1. Se o usuário estiver logado, você também pode personalizar a mensagem de boas-vindas que ele vê utilizando a função getFactWithPersonalization() fornecida em MainFragment.

MainFragment.kt

// TODO 2. If the user is logged in...
binding.welcomeText.text = getFactWithPersonalization(factToDisplay)
  1. Por último, se não houver um usuário conectado (quando authenticationState for qualquer coisa diferente de LoginViewModel.AuthenticationState.AUTHENTICATED), authButton deve exibir Login e inicie a tela de login quando clicado. Também não deve haver personalização da mensagem exibida.

MainFragment.kt

// TODO 3. Lastly, if there is no logged-in user...
binding.authButton.text = getString(R.string.login_button_text)
binding.authButton.setOnClickListener { launchSignInFlow() }
binding.welcomeText.text = factToDisplay

Com todas as etapas concluídas, seu método observeAuthenticationState() final deve ser semelhante ao código abaixo.

MainFragment.kt

private fun observeAuthenticationState() {
   val factToDisplay = viewModel.getFactToDisplay(requireContext())

   viewModel.authenticationState.observe(viewLifecycleOwner, Observer { authenticationState ->
        // TODO 1. Use the authenticationState variable you just added 
         // in LoginViewModel and change the UI accordingly.
       when (authenticationState) {
            // TODO 2.  If the user is logged in, 
             // you can customize the welcome message they see by
             // utilizing the getFactWithPersonalization() function provided
           LoginViewModel.AuthenticationState.AUTHENTICATED -> {
               binding.welcomeText.text = getFactWithPersonalization(factToDisplay)
               binding.authButton.text = getString(R.string.logout_button_text)
               binding.authButton.setOnClickListener {
                   // TODO implement logging out user in next step
               }
           }
           else -> {
                // TODO 3. Lastly, if there is no logged-in user, 
                 // auth_button should display Login and
                 // launch the sign in screen when clicked.
               binding.welcomeText.text = factToDisplay

               binding.authButton.text = getString(R.string.login_button_text)
               binding.authButton.setOnClickListener {
                   launchSignInFlow()
               }
           }
       }
   })
}
  1. Execute seu aplicativo. A IU deve ser atualizada de acordo com o fato de o usuário estar conectado ou não. Se tudo estiver funcionando corretamente e você estiver conectado, a tela inicial deverá saudá-lo pelo seu nome, além de exibir um fato do Android. O botão Login também deve exibir Logout.

Nesta tarefa, você implementará o recurso de logout.

Como o aplicativo permite que os usuários façam login, ele também deve fornecer a eles uma maneira de fazer o logout. Aqui está um exemplo de como desconectar um usuário com apenas uma linha de código:

AuthUI.getInstance().signOut(requireContext())
  1. Abra MainFragment.kt.
  2. Em MainFragment.ktobserveAuthenticationState(), adicione a lógica de logout para que o authButton funcione corretamente quando houver um usuário conectado. O resultado final do método se parece com o código abaixo.

MainFragment.kt

private fun observeAuthenticationState() {
   val factToDisplay = viewModel.getFactToDisplay(requireContext())

   viewModel.authenticationState.observe(viewLifecycleOwner, Observer { authenticationState ->
       when (authenticationState) {
           LoginViewModel.AuthenticationState.AUTHENTICATED -> {
               binding.welcomeText.text = getFactWithPersonalization(factToDisplay)

               binding.authButton.text = getString(R.string.logout_button_text)
               binding.authButton.setOnClickListener {
                   AuthUI.getInstance().signOut(requireContext())
               }
           }
           else -> {
               binding.welcomeText.text = factToDisplay

               binding.authButton.text = getString(R.string.login_button_text)
               binding.authButton.setOnClickListener {
                   launchSignInFlow()
               }
           }
       }
   })
}
  1. Execute o aplicativo.
  2. Toque no botão Logout e verifique se o usuário está desconectado e se o texto do botão muda para Login.

Você pode encontrar a versão final do aplicativo concluído no branch master do seguinte repositório: https://github.com/googletutoriais/android-kotlin-login.

Neste tutorial, você aprendeu:

Este tutorial abordou os fundamentos de como oferecer suporte ao login para um aplicativo Android.

Neste tutorial, você permitiu que os usuários se registrassem e fizessem login com seus endereços de e-mail. No entanto, com a biblioteca FirebaseUI, você também pode oferecer suporte a outros métodos de autenticação, como fazer login com um número de telefone. Para saber mais sobre os recursos da biblioteca FirebaseUI e como utilizar outras funcionalidades que ela oferece, verifique os seguintes recursos:

Para obter mais informações sobre as práticas recomendadas de login, verifique estes outros recursos:

Codelabs:

Documentação do desenvolvedor Android:

Vídeos:

Para obter links para outros tutoriais neste curso, consulte a página inicial de tutoriais do Android avançado em Kotlin.