segunda-feira, 30 de setembro de 2013

Autenticação usando API Google+

Introdução
No desenvolvimento mobile sempre existe a necessidade de trabalhar com usuários. Dessa forma, aumentamos as possibilidades de nossa App pois teremos o controle de dados específicos de cada usuário, podendo então, mostrar dados específicos de um usuário A e quando o usuário B for utilizar a App terá suas informações apresentadas. Além do mais, se mantermos esses dados online, podemos possibilitar ao usuário o acesso a essas informações em vários lugares.

Para se ter esse controle de usuário existem duas formas:
  • Fazer a manutenção do usuário, cadastrando o mesmo e criando toda uma infra específica para se trabalhar com o mesmo;
  • Usar uma API de autenticação de alguma rede social, seja ela Facebook, Twitter, Google+, etc.
Com as possibilidades dessas APIs de autenticação(que não só proporcionam a autenticação em si) não vemos muito a necessidade de usar esta primeira forma pois o custo para mante-la sería grande perto das facilidades das APIs do mercado hoje.

API Google+ Mobile
A Google criou o Google+ API Mobile onde podemos trabalhar com várias funcionalidades do Google+ como compartilhamento de informação, botão +1, iteração com seus círculos, entre outras coisas.

Entre estas outras coisas, está a autenticação, onde podemos fazer autenticação usando o usuário e senha do seu cadastro no Google sem que os dados fiquem expostos. Dessa forma podemos deixar o trabalho pesado para o Google e nos preocupamos em implementar as nossa App.

E é isso que iremos aprender a utilizar hoje. Vamos configurar nossa App para utilizar a Google+ API para realizar uma autenticação.

Configuração de Ambiente
Nos passos iniciais é necessário organizar a casa, criando a sua própria API no Console de APIs do Google e ativando a API do Google+ para poder utiliza-la. Então vamos seguir os passos abaixo:
  • Acesse o Console de APIs Google e crie seu projeto;
  • Selecione "Services" e procure por "Google+ API". Ative-o!
  • Agora vamos criar a nossa API de Acesso criando um ID para Client Mobile e, então, poder usar o OAuth 2.0 para autenticação.
    • Clique em "API Access" e depois em "Create an OAuth 2.0 client ID...";
    • Irá abrir uma janela solicitando algumas informações básicas sobre a App que você está trabalhando, para fins de estudo, vamos só escrever o "Product Name" e clicar em Next;
    • Irá aparecer os campos de configuração de Acesso. Marque a opção "Installed Application", depois a opção "Android";
    • Agora é necessário você informar o package da sua aplicação(atenção: É necessário que o package seja identico ao package da sua aplicação), também é necessário você colocar o SHA-1 da sua máquina por questões de segurança para acesso a API enquanto você está desenvolvendo;
      • Para criar o SHA-1 "keytool -exportcert -alias androiddebugkey -keystore <path-to-debug-or-production-keystore> -list -v" sendo que o eclipse, por padrão, utiliza o caminho "~/.android/debug.keystore" no Mac. Caso você crie em outro lugar, terá que alterar no Eclipse também.
    • Por fim, habilitar a opção Deep Link e clicar em "Create client ID".
Essa é a configuração inicial para trabalhar com a API do Google+. Agora estamos prontos para utilizar a estrutura disponibilizado pelo Google para autenticação entre outras funcionalidades.

Agora vamos para a criação e configuração do nosso projeto.

Criando e configurando a App Mobile

Primeiro temos que adicionar a biblioteca da API no nosso Workspace.
Essa biblioteca está disponível dentro do nosso SDK Android. Caso não encontra-lo em seu SDK, terá que baixá-lo através do "SDK Manager".
  • Com o Eclipse ADT aberto, vá em "File > Import > Existing Android Code Into Workspace > Browser";
  • Agora você irá selecionar o caminho "{caminho_sdk_android}/extras/google/google_play_services/libproject/google-play-services_lib" e depois clicar em Finish;
  • Com a biblioteca devidamente importada, agora você só precisa adiciona-la como uma biblioteca no projeto que você criou.

Obs: o único cuidado que você tem que tomar é que o seu projeto precisa, obrigatoriamente, trabalhar com o mesmo package que você informou lá na criação do ID Client para acesso a API.

Code is Live! o/
Vejamos um exemplo.
Neste exemplo, vamos fazer um Login e Logout usando a API. É algo simples porém de fácil entendimento para que o conceito seja aprendido.

Segue abaixo o código:

package br.com.guisj.signin;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks;
import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener;
import com.google.android.gms.plus.PlusClient;

public class MainActivity extends Activity implements ConnectionCallbacks,
  OnConnectionFailedListener {

 private static final String TAG = "MainActivity";
 private static final int REQUEST_CODE_RESOLVE_ERR = 9000;

 private ProgressDialog mConnectionProgressDialog;
 private PlusClient mPlusClient;
 private ConnectionResult mConnectionResult;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  // Iniciacao de comunicacao com a Google+ API
  mPlusClient = new PlusClient.Builder(this, this, this)
    .setVisibleActivities("http://schemas.google.com/AddActivity",
      "http://schemas.google.com/BuyActivity").build();

  mConnectionProgressDialog = new ProgressDialog(this);
  mConnectionProgressDialog.setMessage("Signin...");

  findViewById(R.id.sign_in_button).setOnClickListener(
    onClickSignInButton());
  findViewById(R.id.sign_out_button).setOnClickListener(
    onClickSignOutButton());
 }

 /**
  * Metodo responsavel por disconectar o usuario da App
  * 
  * @return
  */
 private OnClickListener onClickSignOutButton() {
  return new OnClickListener() {

   @Override
   public void onClick(View v) {
    if (mPlusClient.isConnected()) {
     mPlusClient.clearDefaultAccount();
     mPlusClient.disconnect();
     mPlusClient.connect();
    }
   }
  };
 }

 /**
  * Metodo responsevel por solicitar a conexao de um usuario a sua App. Caso
  * sua app esteja sendo aberta pela primeira vez e nao tenha nenhum usuario
  * vinculado, sera aberta uma janela para que seja selecionado um usuario e
  * depois feito a liberacao de acesso aos dados do mesmo
  * 
  * @return
  */
 private OnClickListener onClickSignInButton() {
  return new OnClickListener() {

   @Override
   public void onClick(View v) {
    if (!mPlusClient.isConnected()) {
     if (mConnectionResult == null) {
      mConnectionProgressDialog.show();
     } else {
      try {
       mConnectionResult
         .startResolutionForResult(
           MainActivity.this,
           REQUEST_CODE_RESOLVE_ERR);
      } catch (SendIntentException e) {
       mConnectionResult = null;
       mPlusClient.connect();
      }
     }
    }
   }
  };
 }

 @Override
 protected void onStart() {
  super.onStart();
  // Quando iniciar a aplicacao, conectar o usuario cadastrado
  mPlusClient.connect();
 }

 @Override
 protected void onStop() {
  super.onStop();
  // Quando finalizar a aplicacao, desconectar o usuario cadastrado
  mPlusClient.disconnect();
 }

 /**
  * Metodo responsavel por chamar novamente a solicitacao de conexao caso
  * aconteca algum problema de comunicacao entre a API
  */
 @Override
 public void onConnectionFailed(ConnectionResult result) {
  if (mConnectionProgressDialog.isShowing()) {
   if (result.hasResolution()) {
    try {
     result.startResolutionForResult(this,
       REQUEST_CODE_RESOLVE_ERR);
    } catch (SendIntentException e) {
     mPlusClient.connect();
    }
   }
  }

  mConnectionResult = result;
 }

 /**
  * Depois que a conexao for bem sucedida mostrar um Toast com o email do
  * usuario logado Obs: necessario acrescentar ao AndroidManifest.xml
  * uses-permission android:name="android.permission.GET_ACCOUNTS"
  */
 @Override
 public void onConnected(Bundle connectionHint) {
  mConnectionProgressDialog.dismiss();
  String accountName = mPlusClient.getAccountName();
  Toast.makeText(this, accountName + " is connected.", Toast.LENGTH_LONG)
    .show();
 }

 @Override
 public void onDisconnected() {
  Log.d(TAG, "disconnected");
 }

 /**
  * Retorno da solicitacao de conexao a API
  */
 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if (requestCode == REQUEST_CODE_RESOLVE_ERR && resultCode == RESULT_OK) {
   mConnectionResult = null;
   mPlusClient.connect();
  }
 }

}

Obs: foi acrescentado dois botões no layout, um para login e outro para logout, sendo que o para Login, foi usado o componente "com.google.android.gms.common.SignInButton" disponível pela própria Google+ API seguindo os padrões de UI da mesma. Também é necessário acrescentar a tag "<uses-permission android:name="android.permission.GET_ACCOUNTS" />" para ter acesso ao email do usuário.

Testando
Para você testar a sua aplicação. É necessário ter um device pois os emuladores padrões não tem a parte de configuração de Contas para que você possa configurar a sua conta Google. 

Porém, recentemente eu fiz um post sobre emuladores otimizados para testar suas Apps e, particularmente, o Genymotion emula um device, tendo a parte de configuração de contas. Dessa forma, é possível que você realize os seus testes utilizando este emulador, sem problemas.

Conclusão
Eu iria fazer uma explicação mais detalhada sobre a classe PlusClient porém o post já está bem grande. Posteriormente irei fazer mais posts sobre a biblioteca e as explicações irão aparecendo.

Bem, podemos ver que a API está ai, que não é difícil configura-la e muito menos utiliza-la.
Ela disponibiliza muitas outras funcionalidades, que se utilizadas da forma correta, irão acrescentar e muito qualidade a sua App auxiliando, até mesmo, a uma melhor colocação no Google Play.

Qualquer dúvida e sugestão, por favor, comente na parte de comentários.

Bons estudos.

[]~



Um comentário: