APIs e Microsserviços

20 dez, 2017

Passando pelo GoogleApiClient

Rafael

Tem 3 artigos publicados com 900 visualizações desde 2012

Rafael
Publicidade

Artigo de Sam Stern, publicado originalmente pelo Android Developers Blog. A tradução foi feita pela Redação iMasters com autorização.

***

O lançamento da versão 11.6.0 do SDK do Google Play Services move uma série de APIs populares para um novo paradigma para acessar as APIs do Google no Android. Reformulamos as APIs para reduzir o boilerplate, melhorar a UX e simplificar a autenticação e a autorização.

A principal mudança nessa versão é a introdução de novas APIs baseadas em Task e GoogleApi para substituir o padrão de acesso do GoogleApiClient.

As seguintes APIs foram atualizadas recentemente para eliminar o uso do GoogleApiClient:

  • Auth: atualizou as APIs Google Sign In e Credentials.
  • Drive: atualizou as APIs Drive e Drive Resource.
  • Fitness: atualizou as APIs Ble, Config, Goals, History, Recording, Sensors e Sessions.
  • Games: atualizou as APIs Achievements, Events, Games, Games Metadata, Invitations, Leaderboards. Notifications, Player Stats, Players, Realtime Multiplayer, Snapshots, Turn Based Multiplayer e Videos.
  • Nearby: atualizou as APIs Connections e Messages.

Essas APIs se juntam a outras que fizeram a troca em versões anteriores, como as APIs Awareness, Cast, Places, Location e Wallet.

O passado: usando GoogleApiClient

Aqui está uma simples Activity que demonstra como alguém poderia acessar a API Google Drive usando o GoogleApiClient com uma versão anterior do SDK do Play services:

public class MyActivity extends AppCompatActivity implements
        GoogleApiClient.OnConnectionFailedListener,
        GoogleApiClient.ConnectionCallbacks {

    private static final int RC_SIGN_IN = 9001;

    private GoogleApiClient mGoogleApiClient;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        GoogleSignInOptions options =
               new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                        .requestScopes(Drive.SCOPE_FILE)
                        .build();

        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .enableAutoManage(this, this)
                .addConnectionCallbacks(this)
                .addApi(Auth.GOOGLE_SIGN_IN_API, options)
                .addApi(Drive.API)
                .build();
    }

    // ...
    // Not shown: code to handle sign in flow
    // ...

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        // GoogleApiClient connection failed, most API calls will not work...
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        // GoogleApiClient is connected, API calls should succeed...
    }

    @Override
    public void onConnectionSuspended(int i) {
        // ...
    }

    private void createDriveFile() {
        // If this method is called before "onConnected" then the app will crash,
        // so the developer has to manage multiple callbacks to make this simple
        // Drive API call.
        Drive.DriveApi.newDriveContents(mGoogleApiClient)
            .setResultCallback(new ResultCallback<DriveApi.DriveContentsResult>() {
                // ...
            });
    }
}

O código é dominado pelo conceito de conexão, apesar de usar o recurso simplificado de “automação”. Um GoogleApiClient só está conectado quando todas as APIs estão disponíveis e o usuário se logou (quando as APIs exigem).

Esse modelo tem uma série de armadilhas:

  • Qualquer falha de conexão impede o uso de qualquer uma das APIs solicitadas, mas o uso de múltiplos objetos do GoogleApiClient é difícil.
  • O conceito de uma “conexão” está incorretamente sobrecarregado. As falhas de conexão podem ser resultado de falta de serviços do Google Play ou de problemas de autenticação.
  • O desenvolvedor deve rastrear o estado da conexão, porque fazer algumas chamadas antes do onConnected ser chamado, resultará em uma falha.
  • Fazer uma chamada de API simples pode significar a espera de duas callbacks. Uma para esperar até que o GoogleApiClient esteja conectado, e outra para a chamada de API.

O futuro: usando o GoogleApi

Ao longo dos anos, a necessidade de substituir o GoogleApiClient se tornou aparente, então nós definimos abstrair completamente o processo de “conexão” e facilitar o acesso a APIs individuais do Google sem boilerplate.

Ao invés de abordar múltiplas APIs em um único cliente de API, cada API agora possui uma classe de objeto de cliente construída especificamente que estende o GoogleApi. Ao contrário do GoogleApiClient, não há custo de desempenho para criar muitos objetos de cliente. Cada um desses objetos do cliente abstrai a lógica de conexão, as conexões são gerenciadas automaticamente pelo SDK de forma a maximizar a velocidade e a eficiência.

Autenticando com o GoogleSignInClient

Ao usar o GoogleApiClient, a autenticação fazia parte do fluxo de “conexão”. Agora que você não precisa mais gerenciar conexões, você deve usar a nova classe GoogleSignInClient para iniciar a autenticação:

public class MyNewActivity extends AppCompatActivity {

    private static final int RC_SIGN_IN = 9001;

    private GoogleSignInClient mSignInClient;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        GoogleSignInOptions options =
               new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                        .requestScopes(Drive.SCOPE_FILE)
                        .build();

        mSignInClient = GoogleSignIn.getClient(this, options);
    }

    private void signIn() {
        // Launches the sign in flow, the result is returned in onActivityResult
        Intent intent = mSignInClient.getSignInIntent();
        startActivityForResult(intent, RC_SIGN_IN);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == RC_SIGN_IN) {
            Task<GoogleSignInAccount> task = 
                    GoogleSignIn.getSignedInAccountFromIntent(data);
            if (task.isSuccessful()) {
                // Sign in succeeded, proceed with account
                GoogleSignInAccount acct = task.getResult();
            } else {
                // Sign in failed, handle failure and update UI
                // ...
            }
        }
    }
}

Antes de fazer a chamada da API, adicionamos uma verificação inline para garantir que fizemos o login e que o processo de login concedeu os escopos de que precisamos.

A chamada para createContents() é simples, mas é realmente para cuidar de um comportamento complexo. Se a conexão ao Play Services ainda não tiver sido estabelecida, a chamada é enfileirada até que haja uma conexão. Isso contrasta com o comportamento antigo, em que as chamadas falhariam ou travariam se feitas antes da conexão.

Em geral, as novas APIs baseadas no GoogleApi têm os seguintes benefícios:

  • Nenhuma lógica de conexão, as chamadas que exigem uma conexão estão em fila até que uma conexão esteja disponível. As conexões são agrupadas quando apropriado e derrubadas quando não estão em uso, economizando bateria e evitando vazamentos de memória.
  • O login está completamente separado das APIs que consomem o GoogleSignInAccount, o que facilita o uso de APIs autenticadas em seu aplicativo.
  • As chamadas de API assíncronas usam a nova API Task em vez de PendingResult, o que permite um gerenciamento e um encadeamento mais fáceis.

Essas novas APIs melhorarão seu processo de desenvolvimento e permitirão que você faça melhores aplicativos.

Próximos passos

Pronto para começar com o novo SDK do Google Google Play services?

***

Este artigo é do Android Developers Blog. Ele foi escrito por Sam Stern. A tradução foi feita pela Redação iMasters com autorização. Você pode acessar o original em: https://android-developers.googleblog.com/2017/11/moving-past-googleapiclient_21.html