Google Sign In for Android-Recebendo utilizadores sem fricção

Standard

Ao desenvolver apps, normalmente temos 2 objectivos na cabeça em que o primeiro é fazer uma app resolva um problema e segundo fazer com os utilizadores a utilizem constantemente,possam customizar e  ter a mesma experiência com amigos.

Infelizmente atingir o segundo objectivo torna-se muito complicado e um processo que normalmente consome muito tempo pois criar um sistema de login do zero, apesar de ser uma ideia tentadora pois podemos sempre ter a liberdade de colocar os campos que queremos e aumentar o nosso ego como programadores é uma péssima ideia pelos seguintes motivos:

  • Os utilizadores ja tem outros serviços com diferentes contas e aumentar mais um username e password a lista de coisas a memorizar é algo que não lhes interessa(Foram feitos alguns estudos que provam isto)
  • Se o objectivo e apenas criar uma app super cool, com todos os detalhes de encriptação e segurança que serão necessários para que possamos garantir que os dados do utilizador estão seguros, não será possível desenvolver um sistema de login em TEMPO (recurso bastante precisos) útil.

Este e outros problemas podem ser facilmente resolvidos utilizando a API Sign in for android da Google(Antigamente conhecida como Google+ Sign in API) e iremos utilizar este post para falar um pouco sobre o seu funcionamento e como implementar.

Esta API utiliza um protocolo chamado Oauth que de forma simples é definido no site oficial como “Um protocolo que oferece um padrão para autorização segura na web,mobile ou aplicações desktops de forma simples”(Veja este video do Google IO 2012 sobre Oauth).

Indo directo para o ponto do nosso post, para começar a integrar o login utilizando a Google Sign in for android API temos de seguir os seguintes  3 passos:

1.Obter o ficheiro de Configuração

O primeiro passo consiste, na obtenção de um ficheiro de configuração por parte do Google que contem informação como o oauth client id que será utilizado para identificar a nossa app instalada em qualquer dispositivo como um dispositivo autorizado para interagir com esta API.

Para obter este ficheiro basta que simplesmente ir para este LINK e preencher os campos App Name que é o nome do projecto que será criado no google developers console ou se ja tiver um pode seleccionar da lista e  o Package name onde devemos colocar o nome do pacote da aplicação como está no ficheiro androidManifest.xml .

Como dizia acima, o Google tem  varias APIs e como mostra a figura abaixo, desta forma é possível ter o mesmo ficheiro na  mesma app com a configuracao de outras  APIs como a do Google Cloud Messaging(Vira um Post ja ja) e Analytics.

Como para este post queremos só utilizar o Google Sign in, devemos clicar sobre o icon do Google Sign in que nos pede a inserir  o certificado SHA-1 que é gerado pela chave utilizada para certificar a aplicação.(Se estiver só a testar a app o ficheiro de keystore estará na pasta .android->android-debug.keystore e caso estejam para fazer o release final ou actualizar uma app no playstore, utilizem o ficheiro *.keystore que só vocês sabe onde está. Para verficar o SHA-1 utilize o comando keytool no command prompt keytool -list -v -keystore keystore.jks onde o “keystroke.jks” é o caminho relativo ou absoluto ao ficheiro dependendo de onde ir a querer executar este comando.)

Isto porque como disse anteriormente, a Google precisa de formas para identificar o cliente que esta a fazer os pedidos e porque uma aplicação no playstore só pode ter um id único que é o package name e um certificado SHA-1 da chave único utilizado ao gerar o APK estes dois elementos formam a combinação perfeita e única.

Após preencher os campos de seguida devemos clicar no botão no fim da página que diz Generate configuration files e na página que abre de seguida clicar no Download google-services.json.

2.Copiar o ficheiro para o projecto e configurar o projecto

Após baixar o ficheiro de configuração só precisamos de seguida copiar este ficheiro e colocar dentro da raiz do modulo “app” do nosso projecto (No mesmo nível que o ficheiro build.gradle).

Com o ficheiro já no projecto, o próximo passo é primeiro configurar o plugin do Google Play Services e as dependências necessárias no gradle.

Dentro do projecto, existem 2 ficheiros build.gradle em que um encontra-se na raiz do projecto que é o ficheiro de configurações globais do projecto e o segundo dentro do modulo “app” que é o ficheiro de configuração especifica para a android app. (Caso se crie um novo modulo com um projecto do app engine, este também terá o seu build.gradle com as suas configuração especificas)

Devemos definir o plugin do Google Play Services no ficheiro build.gradle a nível do projecto especificando a linha  classpath ‘com.google.gms:google-services:2.0.0-beta7’  dentro da secção dependencies do  ficheiro assim:
dependencies {
classpath ‘com.android.tools.build:gradle:2.0.0-beta7’
classpath ‘com.google.gms:google-services:2.0.0-beta7’

}
}

Notem que a versão, ir a sempre mudar e ir a pedir que altere a medida que novas actualizações do gradle plugin e do android studio vão sendo lançados por isso certifiquem-se de que na altura que estiverem a ler a este post, a versão do gradle plugin como do google play services é igual a esta e caso não seja modifiquem para a versão em utilização no momento.

Depois de definir o plugin, temos de ir ao ficheiro build.gradle do modulo e definir o plugin assim como as bibliotecas que serão necessárias para utilizar a API  Sign in for Android. Para definir o plugin basta simplesmente colocar esta linha apply plugin: ‘com.google.gms.google-services’.

A primeira vez que testei esta nova forma de configuração, levei horas pois foi intuitivo para mim aplicar o plugin no ficheiro logo por baixo da linha que aplica o plugin com.android.application  e tive vários erros. Fui tentando e a solução que encontrei testando e em varias respostas no stack foi que simplesmente esta linha deveria ser a última no ficheiro sem nenhuma explicação aparente.

Porque o Google Sign in for android assim como muitas outras e algumas das APIs mencionadas neste post fazem parte do Google Play Services, e para utilizar qualquer uma delas temos de definir estas bibliotecas no nosso projecto assim como é feito com a design support library e outras. Para definir o Google Play Services nas dependências, podemos fazer de 2 formas em que a primeira nós importamos todas estas APIs para o nosso projecto especificando apenas compile ‘com.google.android.gms:play-services:8.4.0’
e a segunda especificando de forma exacta a API a utilizar, neste caso Auth assim: compile ‘com.google.android.gms:play-services-auth:8.4.0’

A segunda forma é a mais aconselhável pois se utilizamos muitas outras bibliotecas, corremos o risco de adicionar todos os métodos das diferentes APIs dentro do Google Play Services e iremos atingir o limite dos métodos  de 65K  definido pelo DEX  que ir a gerar um erro e não conseguiremos compilar o projecto. Para referência, veja a lista com descrição de outras APIs AQUI.

O último passo na configuração é ir ao ficheior androidManifes.xml e definir as permissões <uses-permission android:name=”android.permission.GET_ACCOUNTS” /> para que a nossa app possa ter permissão para aceder as contas configuradas e disponíveis no dispositivo.

3.Implementar o Google Sign in for Android

Finalmente temos a configuração toda feita e podemos passar para a parte interessante da implementação.
Vamos começar por desenhar uma interface gráfica,  e até para isso esta API facilitou-nos o trabalho ao oferecer um botão todo customizado que vem já com a mensagem “iniciar sessão com o Googe” que é  automaticamente traduzida para qualquer linguagem que esteja o dispositivo como mostra a imagem abaixo.

Screenshot_20160321-202549 (1)

Definir este botão pode ser feito simplesmente da seguinte forma:

<com.google.android.gms.common.SignInButton
    android:id="@+id/sign_in_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|center"
    android:layout_marginBottom="?actionBarSize"
    />

e como podem ver no codigo acima, podemos definir todos atributos que achamos necessários como margens, posicionamento e o id que será utilizado ao criar uma instância deste botão em código para que possamos fazer coisas como definir um listener.

Com o botão colocado na interface gráfica, o próximo passo e fazer com ao clicar realmente comecemos como o processo de login utilizando a API.

Para fazer o login utilizando o Google Sign in é indispensável que utilizemos as classes GoogleApiClient e GoogleSignInOptions em que primeira é  utilizada para conectar ao Google Play Services(Utilizarão esta classe sempre que quiserem utilizar a maioria das APIs dentro do Google Play Services ) e a segunda e utilizada para definir as opções a utilizar com o GOOGLE_SIGN_IN.

Dentro do método onCreate da activity ou fragment ou dentro de um método de conveniência que será invocado no onCreate, vamos cometar por configurar estas duas classes como mostra o código abaixo:

public void setUpGoogleApiClient(){
    
    //GoogleSignInOptions
    gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .requestId()
            .build();


    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .enableAutoManage(this, this /* OnConnectionFailedListener */)
            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
            .build();
}

Começando pelo GoogleSignInOptions, simplesmente utilizamos o Builder para constuir um objecto com as configurações que nós precisamos.

Passar só a variável estática GoogleSignInOptions.DEFAULT_SIGN_IN ao construtor do builder, teremos uma configuração básica que nos ira retornar alguns campos básicos, mas a medida que vamos precisando de mais informação podemos explicitamente invocar os métodos com o prefixo request como o requesScopes  que permite que possamos aceder a diferentes escopos para a conta do utilizador como ficheiros autorizados no Google drive etc.

Logo de seguida configuramos o GoogleApiClient em que passamos o context ao constructor do Builder, definimos que o ciclo de vida será automaticamente gerido passando ao método enableAutoManage o fragment ou activity em que estamos a trabalhar e o listener OnConnectionFailedListener que nos obriga a implementar o método onConnectionFailed para permitir que possamos capturar capturar o momento que o GoogleApiClient falha por algum motivo.

Por fim adicionar uma Api, neste caso definindo que é a API do Google Sign In e passar o objecto GoogleSignInObject criado anteriormente.

Com tudo isto pronto, podemos criar um método signIn() que será invocado ao clicar o botão e dentro dele iniciar o processo de login, criando uma nova Intent onde passamos a Intent de sign in gerada pelo método Auth.GoogleSignInApi.getSignInIntent que recebe o objecto GoogleApiClient que criamos e por fim passar esta mesma Intent ao  invocar o método startActivityForResult sem esquecer de passar um codigo  que sera utilizado para identificar o request no momento de receber a resposta

private void signIn() {
    Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
    startActivityForResult(signInIntent, RC_SIGN_IN);
}

Até  aqui já é possível ver a API em funcionamento para dispositivos correndo versões do android pré Marshmallow mas teremos o azar de não ver a funcionar para as versões iguais ou posteriores.

Isto porque no Marshmallow foi introduzido um novo modelo de permissões em que o utilizador deve garantir que a app utilize uma certa permissão em tempo de execução dependendo do grau de sensibilidade em relação ao acesso a dados privados do utilizador.

Para este exemplo, criei dois métodos de conveniência para verificar se a permissão foi garantida ou não e o outro para fazer mostrar uma caixa de dialogo ao utilizador a pedir que garanta esta permissão. Este assunto ja tem um post especifico escrito no medium e podem ver mais AQUI.

public boolean isGetAccountsAllowed(){
    return ActivityCompat.checkSelfPermission(this,
            android.Manifest.permission.GET_ACCOUNTS) == PackageManager.PERMISSION_GRANTED;
}

public void requestGetAccountPermission(){
    ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.GET_ACCOUNTS}, PERM_RC);
}

Utilizamos o primeiro método para verificar se a permissão ja foi garantida ao clicar o botão de sign in e fazer o login caso sim ou fazer ao pedido ao utilizador caso não utilizando o segundo método  e depois continuar com o login invocando o metodo signIn(). Assumindo que temos tudo a funcionar bem teremos algo assim:

Screenshot_20160331-044551

Porque acima nos criamos esta caixa dialogo ao invocar o método startActivityForResult, ao seleccionar uma conta, será enviada uma resposta para activity/fragment  e para que possamos capturar devemos implementar o método de callback onActivityResult.

Com estaresposta, utilizando as classes GoogleSignInResult e GoogleSignInAccount, podemos pegar toda informação sobre esta conta que for interessante e que pedimos nas opções GoogleSignInObject que mencionamos mais acima. Este é também o local para mandar o utilizador para uma nova activity que ele só terá acesso depois de fazer o login ou alguma outra acção específica a app em desenvolvimento.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == RC_SIGN_IN) {
        GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
        GoogleSignInAccount signInAccount = result.getSignInAccount();
        String email = signInAccount.getEmail();
    }
}

Sendo assim em apenas alguns passo foi possível implementar o login utilizando a API Google Sign In for Android.

Notem que este post foram omitidos vários aspectos da implementação completa de uma app em produção como verificar em um servidor próprio se um utilizador com por exemplo um e-mail idêntico ja existe, pedir que ele se registe entre outras coisas pois isso pode variar dependendo do caso especifico de cada aplicação e a imaginação de cada desenvolvedor.

Espero que mais uma vez tenha tido uma bom momento lendo este pequeno guia e caso tenham alguma duvida ou sugestão, não hesitem em deixar um comentário para que possamos criar uma conversa em volta do assunto.

Até a próxima!

DM 🙂

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s