Android

5 jul, 2017

Reduzir atritos com as novas APIs de localização do Google Play

Publicidade

Artigo de Aaron Stacy, publicado originalmente pelo Android Security Team. A tradução foi feita pela Redação iMasters com autorização.

 

O lançamento da versão 11.0.0 do SDK de serviços do Google Play inclui uma nova maneira de acessar a LocationServices. A nova API não exige que seu aplicativo gerencie manualmente uma conexão com os serviços do Google Play através de um GoogleApiClient. Isso reduz o tamanho dos códigos e as armadilhas comuns em seu aplicativo.

Leia mais abaixo, ou vá direto para o diretório dos exemplos atualizados no GitHub.

Por que não utilizar o GoogleApiClient?

A API LocationServices permite que você acesse a localização do aparelho, configure georreferências, solicite ao usuário que habilite a localização do aparelho, entre outras coisas. Para acessar esses serviços, o aplicativo deve se conectar aos serviços do Google Play, o que pode envolver uma probabilidade de falhas na conexão lógica. Por exemplo, você consegue encontrar o problema no aplicativo abaixo?

Nota: vamos considerar que seu aplicativo possui a permissão ACCESS_FINE_LOCATION, que é exigida para obter a localização exata do usuário utilizando os APIs LocationServices.

public class MainActivity extends AppCompatActivity implements
        GoogleApiClient.OnConnectionFailedListener {

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

    GoogleApiClient client = new GoogleApiClient.Builder(this)
        .enableAutoManage(this, this)
        .addApi(LocationServices.API)
        .build();
    client.connect();

    PendingResult result = 
         LocationServices.FusedLocationApi.requestLocationUpdates(
                 client, LocationRequest.create(), pendingIntent);

    result.setResultCallback(new ResultCallback() {
      @Override
      public void onResult(@NonNull Status status) {
        Log.d(TAG, "Result: " + status.getStatusMessage());
      }
    });
  }

  // ...
}

Se você apontou para a chamada requestLocationUpdates(), você está certo! Essa chamada lança um IllegalStateException, pois o GoogleApiClient ainda não está conectado. A chamada para fazer um connect() é assíncrona.

O código acima parece que deveria funcionar, mas falta um argumento ConnectionCallbacks para o constructor GoogleApiClient. A chamada para requisição das atualizações de localização deveria ser feita somente após o retorno de onConnected ser disparado:

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

  private GoogleApiClient client;

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

    client = new GoogleApiClient.Builder(this)
        .enableAutoManage(this, this)
        .addApi(LocationServices.API)
        .addConnectionCallbacks(this)
        .build();

    client.connect();
  }

  @Override
  public void onConnected(@Nullable Bundle bundle) {
    PendingResult result = 
            LocationServices.FusedLocationApi.requestLocationUpdates(
                    client, LocationRequest.create(), pendingIntent);
    
    result.setResultCallback(new ResultCallback() {
      @Override
      public void onResult(@NonNull Status status) {
        Log.d(TAG, "Result: " + status.getStatusMessage());
      }
    });
  }

  // ...
}

Agora o código funciona, mas não é o ideal por algumas razões:

  • Seria difícil refatorar em classes compartilhadas se, por exemplo, você quisesse acessar LocationServices em múltiplas atividades;
  • O aplicativo se conecta a onCreate mesmo se os serviços de localização não forem necessários no momento (por exemplo, após o usuário realizar entrada de dados);
  • Ele não trata os casos onde o aplicativo falha em se conectar aos serviços do Google Play;
  • Existe muito código padrão para conexão lógica antes de iniciar com as atualizações de localização;

Uma melhor experiência para o desenvolvedor

As novas APIs LocationServices são muito mais simples e tornarão seu código menos sujeito a erros. A conexão lógica é tratada automaticamente, e você só precisa anexar um simples ouvinte de conclusão:

public class MainActivity extends AppCompatActivity {

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

    FusedLocationProviderClient client =
            LocationServices.getFusedLocationProviderClient(this);

    client.requestLocationUpdates(LocationRequest.create(), pendingIntent)
        .addOnCompleteListener(new OnCompleteListener() {
          @Override
          public void onComplete(@NonNull Task task) {
            Log.d("MainActivity", "Result: " + task.getResult());
          }
        });
  }
}

A nova API melhora imediatamente o código de algumas maneiras:

  • As chamadas da API esperam automaticamente a conexão com os serviços ser estabelecida, o que elimina a necessidade de aguardar pelo onConnected antes de realizar as solicitações;
  • Ela utiliza a API Task que facilita a composição de operações assíncronas;
  • O código é autocontido e poderia facilmente ser alterado para uma classe de utilidade compartilhada ou similar;
  • Você não precisa entender o processo de conexão antes de começar a codar;

O que aconteceu com todos os retornos?

A nova API vai resolver automaticamente algumas falhas de conexão para você, então não será preciso escrever códigos para coisas como solicitar ao usuário para atualizar os serviços do Google Play. Ao invés de expor as falhas de conexão globalmente no método onConnectionFailed, os problemas de conexão vão falhar com um ApiException:

[cód]

Teste você mesmo

Teste as novas APIs LocationServices você mesmo em seu aplicativo ou acesse o diretório de exemplos do Android Play Location no GitHub e veja mais exemplos de como os novos clientes reduzem os códigos e simplificam a lógica.

 

***

Este artigo é do Android Security Team. Ele foi escrito por Aaron Stacy. A tradução foi feita pela Redação iMasters com autorização. Você pode acessar o original em:  https://android-developers.googleblog.com/2017/06/reduce-friction-with-new-location-apis.html