Xamarin Forms - Login usando Firebase e MVVM - I
 Neste artigo veremos como criar uma página de Login com MVVM e usar a base de dados Firebase para armazenar as credenciais do usuário.

O Firebase é mais um dos serviços do Google e ele possui muitas funcionalidades, e, a que iremos usar neste artigo será a funcionalidade Databases.

Criando a conta e o configurando o Firebase

A primeira coisa a fazer é criar uma conta no Firebase acessando o Firebase Console.

Se você tiver uma conta ou após você se registrar e fazer o login será a apresentada a tela abaixo onde podemos adicionar um novo projeto clicando em : Adicionar projeto

A seguir informe o nome do projeto e clique em Continuar:

A seguir desative o Google Analytics e clique no botão para criar o projeto:

Se houver qualquer dúvida consulta a documentação aqui : https://firebase.google.com/docs?authuser=0

Ao final seu projeto será criado e você pode clicar em Continuar:

Vamos agora incluir o Firebase em nosso projeto. Para isso clique em Database:

A seguir clique em : Criar banco de dados

Agora selecione a opção :  iniciar no modo de teste e cliqem no botão : Próxima:

Observe que neste modo qualquer pessoa que possua a referência ao nosso banco de dados vai poder visualizar, editar e deletar todos os dados do banco de dados.

Para concluir defina a localização de armazenamento aceitando o valor padrão e clicando em Concluido:

Seu banco de dados já esta pronto para ser usado. A seguir vamos clicar em - Cloud Firestore:

Vamos selecionar a opção Realtime Database

Pronto. Seu banco agora possui um link de referência - https://xamarinfirestore-bc526.firebaseio.com/ -  que será usado para fazer o acesso.

Obs: O seu link deverá ser diferente do mostrado aqui.

Temos que alterar as regras de acesso aos dados pois por padrão a leitura e a escrita estão definidos como false e assim não será possível ler nem escrever dados.

Clique em Regras e altera a regra de acesso conforme mostra a figura:

Após clicar em Publicar seu banco Firebase estará pronto para ser acessado e você poderá ler e escrever dados.

Assim a parte de configuração do Firebase esta concluída e podemos continuar com o Xamarin Forms.

Recursos usados:

Criando o projeto Xamarin Forms

Vamos criar um novo projeto Xamarin Forms no VS 2019 Community com o nome XF_LancheApp.

Nota: Verifique se você precisa atualizar as versões do Xamarin Forms e do Xamarin.Essentials

Você pode ver como criar um projeto no Xamarin Forms neste link: Criar Projeto Xamarin Forms

A seguir vamos incluir os seguintes pacotes no projeto criado:

  1. FirebaseDatabase.net

   

  1. Xamarin.Forms.PancakeView

   

  1. Xamarin.Forms.Visual.Material

   

A seguir vamos criar as seguintes pastas no projeto compartilhado que iremos usar em nossa aplicação:

  1. Models
  2. Services
  3. ViewModels
  4. Views
  5. Helpers

No projeto Android, na pasta Resources/drawable vamos incluir o arquivo logorede1.jpg que iremos usar na página de Login.

Na pasta Models crie a classe User que representa um usuário que vai acessar nossa aplicação e que possui um nome e uma senha:

    public class User
    {
        public string Username { get; set; }
        public string Password { get; set; }
    }

Agora vamos criar a classe UserService onde vamos implementar a funcionalidades para acessar nossa base de dados Firebase e verificar se o usuário existe, fazer o login e o registro de um novo usuário.

Aqui vamos usar o link de referência ao nosso banco de dados Firebase que para a minha conta tem o seguinte valor:
https://xamarinfirestore-bc526.firebaseio.com/.

Iremos usar também a referência à biblioteca Firebase.Database e Firebase.DatabaseQuery onde vamos usar classe FirebaseClient e definir os métodos:

  1. IsUserExists(string name)
  2. RegisterUser(string name, string passwd)
  3. LoginUser(string name, string passwd)

Para isso crie a classe UserService na pasta Services:

using Firebase.Database;
using Firebase.Database.Query;
using System.Linq;
using System.Threading.Tasks;
using XF_LancheApp.Models;
namespace XF_LancheApp.Services
{
    public class UserService
    {
        FirebaseClient client;

        public UserService()
        {
            client = 
                new FirebaseClient("https://xamarinfirestore-bc526.firebaseio.com/");
        }

        public async Task<bool> IsUserExists(string name)
        {
            var user = (await client.Child("Users")
                .OnceAsync<User>())
                .Where(u => u.Object.Username == name)
                .FirstOrDefault();
            return (user != null);
        }

        public async Task<bool> RegisterUser(string name, string passwd)
        {
            if (await IsUserExists(name) == false)
            {
                await client.Child("Users")
                    .PostAsync(new User()
                    {
                        Username = name,
                        Password = passwd
                    });
                return true;
            }
            else
            {
                return false;
            }
        }
        public async Task<bool> LoginUser(string name, string passwd)
        {
            var user = (await client.Child("Users")
                .OnceAsync<User>())
                .Where(u => u.Object.Username == name)
                .Where(u => u.Object.Password == passwd)
                .FirstOrDefault();
            return (user != null);
        }
    }
}

Assim temos nosso serviço pronto para acessar o Firebase, realizar o login e fazer o registro de um novo usuário.

No código acima será criada a coleção Users e as propriedades Username e Password no Firebase.

Como vamos usar a abordagem MVVM vamos criar agora a view model relacionada com a classe User e com a view LoginView que iremos criar a seguir.

Para isso teremos que criar a view model LoginViewModel que implementa a interface INotifyPropertyChanged assim vamos criar uma classe BaseViewModel onde teremos a implementação desta interface e a seguir todas as demais view models poderão herdar desta classe base e assim otimizamos nosso código.

Na pasta ViewModels crie a classe BaseViewModel:

using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace XF_LancheApp.ViewModels
{
    public class BaseViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged([CallerMemberName] string name = "") => 
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));       
    }
}

Ainda na pasta ViewModels vamos criar agora a view model LoginViewModel que herda de BaseViewModel:

using System;
using System.Threading.Tasks;
using Xamarin.Essentials;
using Xamarin.Forms;
using XF_LancheApp.Services;
using XF_LancheApp.Views;
namespace XF_LancheApp.ViewModels
{
    public class LoginViewModel : BaseViewModel
    {
        private string _Username;
        public string Username
        {
            set
            {
                this._Username = value;
                OnPropertyChanged();
            }
            get
            {
                return this._Username;
            }
        }
        private string _Password;
        public string Password
        {
            set
            {
                this._Password = value;
                OnPropertyChanged();
            }
            get
            {
                return this._Password;
            }
        }
        private bool _Result;
        public bool Result
        {
            set
            {
                this._IsBusy = value;
                OnPropertyChanged();
            }
            get
            {
                return this._IsBusy;
            }
        }
        private bool _IsBusy;
        public bool IsBusy
        {
            set
            {
                this._Result = value;
                OnPropertyChanged();
            }
            get
            {
                return this._Result;
            }
        }
        public Command LoginCommand { get; set; }
        public Command RegisterCommand { get; set; }
        public LoginViewModel()
        {
            LoginCommand = new Command(async () => await LoginCommandAsync());
            RegisterCommand = new Command(async () => await RegisterCommandAsync());
        }
        private async Task RegisterCommandAsync()
        {
            if (IsBusy)
                return;
            try
            {
                IsBusy = true;
                var userService = new UserService();
                Result = await userService.RegisterUser(Username, Password);
                if (Result)
                    await Application.Current.MainPage.DisplayAlert("Sucesso", "Usuário Registrado", "Ok");
                else
                    await Application.Current.MainPage.DisplayAlert("Erro", "Falha ao registrar usuário", "Ok");
            }
            catch (Exception ex)
            {
                await Application.Current.MainPage.DisplayAlert("Erro", ex.Message, "Ok");
            }
            finally
            {
                IsBusy = false;
            }
        }
        private async Task LoginCommandAsync()
        {
            if (IsBusy)
                return;
            try
            {
                IsBusy = true;
                var userService = new UserService();
                Result = await userService.LoginUser(Username, Password);
                if (Result)
                {
                    Preferences.Set("Username", Username);
                    await Application.Current.MainPage.Navigation.PushAsync(new ProdutosView());
                }
                else
                {
                    await Application.Current.MainPage.DisplayAlert("Erro", "Usuário/Senha inválido(s)", "Ok");
                }
            }
            catch (Exception ex)
            {
                await Application.Current.MainPage.DisplayAlert("Erro", ex.Message, "Ok");
            }
            finally
            {
                IsBusy = false;
            }
        }
    }
}

No código acima estamos definindo as propriedades e os comandos usados para realizar o login e o registro do usuário e estamos usando o serviço UserServive e os métodos LoginUser e RegisterUser para realizar esta tarefa.

Temos assim tudo pronto e já podemos criar a nossa view LoginView e a view ProdutosView para a qual iremos navegar quando o login for realizado com sucesso.

Faremos isso na próxima parte do artigo. Aguarde...

"Mas, não vos alegreis porque se vos sujeitem os espíritos; alegrai-vos antes por estarem os vossos nomes escritos nos céus."
Lucas 10:20

Referências:


José Carlos Macoratti