Como chamar APIs de back-end de um cliente Android

Nesta página, descrevemos como um cliente Android chama uma API de back-end criada com o Cloud Endpoints Frameworks para App Engine.

Como gerar a biblioteca de cliente

O cliente Android requer a biblioteca de cliente gerada da API de back-end usada por ele. Se você ainda não tiver a biblioteca de cliente, consulte Como gerar uma biblioteca de cliente para mais detalhes. Há etapas neste documento que explicam como adicionar a biblioteca de cliente ao projeto do cliente Android.

Como configurar o projeto

Nestas instruções, você usa o Android Studio. Se você ainda não fez isso, precisará configurar o Android Studio para oferecer suporte a um cliente que use os frameworks.

Configurar o projeto

No Android Studio, seu projeto usa o arquivo build.gradle para dependências e outras configurações. Por padrão, o Android Studio cria um arquivo build.gradle pai para envolvidos no projeto e um arquivo específico do app no módulo do Android. Estas instruções são específicas para o aplicativo build.gradle no módulo do Android.

Para configurar build.gradle:

  1. Clique duas vezes em build.gradle para abrir o arquivo.

  2. Edite esse arquivo para que contenha as seguintes linhas:

    buildscript {
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:1.0.0'
        }
    }
    apply plugin: 'com.android.application'
    
    repositories {
        mavenCentral()
        mavenLocal()
    }
    
    android {
        compileSdkVersion 26
    
        defaultConfig {
            applicationId "com.mycompany.myapp"
            minSdkVersion 17
            targetSdkVersion 26
            versionCode 1
            versionName "1.0"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
        packagingOptions {
            exclude 'META-INF/DEPENDENCIES'
        }
    }
    
    dependencies {
        implementation 'com.android.support:appcompat-v7:26.1.0'
        implementation 'com.android.support.constraint:constraint-layout:1.1.3'
        // BEGIN Google APIs
        // Play Services will validate the application prior to allowing OAuth2 access.
        implementation 'com.google.android.gms:play-services-auth:16.0.0'
        implementation 'com.google.android.gms:play-services-identity:16.0.0'
        // The following lines implement maven imports as defined at:
        // https://github.com/googleapis/google-api-java-client/wiki/Setup-Instructions
        // Add the Google API client library.
        implementation('com.google.api-client:google-api-client:1.28.0') {
            // Exclude artifacts that the Android SDK/Runtime provides.
            exclude(group: 'xpp3', module: 'xpp3')
            exclude(group: 'org.apache.httpcomponents', module: 'httpclient')
            exclude(group: 'junit', module: 'junit')
            exclude(group: 'com.google.android', module: 'android')
        }
        // Add the Android extensions for the Google API client library.
        // This will automatically include play services as long as you have download that library
        // from the Android SDK manager.
        // Add the Android extensions for the Google API client library.
        implementation(group: 'com.google.api-client', name: 'google-api-client-android', version: '1.25.0') {
                   // Exclude play services, since we're not using this yet.
                  exclude(group: 'com.google.android.gms:play-services', module: 'google-play-services')
        }
        // END Google APIs
        // The following client libraries make HTTP/JSON on Android easier.
        // Android extensions for Google HTTP Client.
        implementation('com.google.http-client:google-http-client-android:1.21.0') {
            exclude(group: 'com.google.android', module: 'android')
        }
        implementation 'com.google.http-client:google-http-client-gson:1.21.0'
        // This is used by the Google HTTP client library.
        implementation 'com.google.guava:guava:18.0+'
        implementation files('libs/echo-v1-1.25.0-SNAPSHOT.jar')
    }
    
    

    Substitua com.mycompany.myapp por seus próprios valores.

  3. Clique em Arquivo > Salvar tudo, saia do Android Studio e o reinicie.

Adicionar a biblioteca de cliente ao projeto

Para adicionar a biblioteca de cliente ao projeto do Android:

  1. Adicione um diretório /libs ao seu projeto, se ele ainda não tiver um. É um par para o diretório /src.

  2. Copie a biblioteca de cliente gerada da API de back-end para /libs.

  3. Clique com o botão direito na biblioteca que você acabou de adicionar e selecione Adicionar como biblioteca no seu projeto.

Criar o objeto de serviço

No código do projeto, use um objeto de serviço para fazer solicitações à API de back-end. Para as solicitações não autenticadas, crie o objeto de serviço como indicado a seguir:

BACKEND_API_NAME.Builder builder = new BACKEND_API_NAME.Builder(
    NetHttpTransport(), new GsonFactory(), null);
service = builder.build();

Substitua BACKEND_API_NAME pelo nome da sua API de back-end.

Como chamar a API de back-end

Em seu projeto, chame a API usando o objeto de serviço. Por exemplo:

ScoreCollection scores = service.scores().list().execute();

Neste snippet, você está solicitando uma lista de todos os objetos Score no servidor. Se list exigir parâmetros ou um corpo de solicitação, forneça-os no comando. O Android Studio fornece preenchimento de código para chamadas de método com identidade disponível e os devidos parâmetros delas.

É importante observar que, pelo fato das chamadas de API gerarem solicitações na rede, é preciso fazer solicitações na linha de execução delas. Esse requisito foi adicionado a versões recentes do Android, mas é uma prática recomendada mesmo nas versões mais antigas. Para fazer isso, use uma Thread ou AsyncTask. Por exemplo:

private class QueryScoresTask extends AsyncTask<Void, Void, ScoreCollection>{
  Context context;

  public QueryScoresTask(Context context) {
    this.context = context;
  }

  protected Scores doInBackground(Void... unused) {
    ScoreCollection scores = null;
    try {
      scores = service.scores().list().execute();
    } catch (IOException e) {
      Log.d("TicTacToe", e.getMessage(), e);
    }
    return scores;
  }

  protected void onPostExecute(ScoreCollection scores) {
    // Do something with the result.
  }
}

Fazer chamadas autenticadas

Estas instruções incluem apenas a codificação do cliente que é preciso adicionar. As instruções assumem que você já adicionou o suporte a Endpoints Frameworks para autenticação, conforme descrito em Como autenticar usuários.

Se seu cliente Android faz chamadas a um endpoint que requer autenticação, realize as ações a seguir:

  • Configure o cliente Android para fornecer as credenciais do objeto de serviço.
  • Use o seletor de conta para dar suporte à escolha do usuário de contas de login.

As seções a seguir dão detalhes.

Como configurar o cliente Android para fornecer credenciais

Para aceitar solicitações para uma API de back-end que exija autenticação, o cliente Android precisa receber credenciais de usuário e passá-las para o objeto de serviço.

Para solicitar credenciais de usuário e usar o seletor de conta, você precisa ter as seguintes permissões do Android:

<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />

Para obter as credenciais do usuário, chame GoogleAccountCredential.usingAudience da seguinte maneira:

// Inside your Activity class onCreate method
settings = getSharedPreferences(
    "TicTacToeSample", 0);
credential = GoogleAccountCredential.usingAudience(this,
    "server:client_id:1-web-app.apps.googleusercontent.com");

Onde o segundo parâmetro para a chamada é o prefixo server:client_id, anexado ao ID do cliente da web da API de back-end.

Código de exemplo: solicitar credenciais para o objeto de serviço

Veja no código a seguir como solicitar credenciais e transmiti-las ao objeto de serviço:

// Inside your Activity class onCreate method
settings = getSharedPreferences("TicTacToeSample", 0);
credential = GoogleAccountCredential.usingAudience(this,
    "server:client_id:1-web-app.apps.googleusercontent.com");
setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null));

Tictactoe.Builder builder = new Tictactoe.Builder(
    NetHttpTransport(), new GsonFactory(),
    credential);
service = builder.build();

if (credential.getSelectedAccountName() != null) {
  // Already signed in, begin app!
} else {
  // Not signed in, show login window or request an account.
}

// setSelectedAccountName definition
private void setSelectedAccountName(String accountName) {
  SharedPreferences.Editor editor = settings.edit();
  editor.putString(PREF_ACCOUNT_NAME, accountName);
  editor.commit();
  credential.setSelectedAccountName(accountName);
  this.accountName = accountName;
}

O código de exemplo anterior procura as preferências compartilhadas armazenadas pelo app Android e tenta encontrar o nome da conta que o usuário quer usar para se autenticar no seu aplicativo. Em caso de êxito, o código cria um objeto de credenciais e o transmite para o objeto de serviço. Essas credenciais permitem que seu app Android transmita o token apropriado para seu back-end.

O código de exemplo verifica se o app Android já sabe ou não qual conta usar. Se isso acontecer, o fluxo lógico poderá continuar e executar o aplicativo para Android. Se o aplicativo não souber qual conta usar, o aplicativo exibirá uma tela de login ou solicitará que o usuário escolha uma conta.

Por fim, o exemplo cria um objeto de credencias e o transmite para o objeto de serviço. Essas credenciais permitem que seu app Android transmita o token adequado para seu aplicativo da Web do Google App Engine.

Como usar o seletor de conta

O Android fornece um intent para selecionar uma conta de usuário. Para chamá-lo, faça o seguinte:

static final int REQUEST_ACCOUNT_PICKER = 2;

void chooseAccount() {
  startActivityForResult(credential.newChooseAccountIntent(),
      REQUEST_ACCOUNT_PICKER);
}

Este é um gerenciador para interpretar o resultado do intent:

@Override
protected void onActivityResult(int requestCode, int resultCode,
   Intent data) {
 super.onActivityResult(requestCode, resultCode, data);
 switch (requestCode) {
   case REQUEST_ACCOUNT_PICKER:
     if (data != null && data.getExtras() != null) {
       String accountName =
           data.getExtras().getString(
               AccountManager.KEY_ACCOUNT_NAME);
       if (accountName != null) {
         setSelectedAccountName(accountName);
         SharedPreferences.Editor editor = settings.edit();
         editor.putString(PREF_ACCOUNT_NAME, accountName);
         editor.commit();
         // User is authorized.
       }
     }
     break;
  }
}

Como testar um cliente Android em um servidor de desenvolvimento local

É possível testar o cliente em uma API de back-end em execução no App Engine de produção a qualquer momento, sem fazer qualquer alteração. No entanto, se você quiser testar seu cliente em uma API de back-end em execução no servidor de desenvolvimento local, será necessário alterar a linha de código no cliente para que aponte para o endereço IP da máquina que executa o servidor de desenvolvimento local.

Para fazer as alterações necessárias e o teste usando o servidor de desenvolvimento local, siga estes passos:

  1. Anote o endereço IP da máquina que está executando o servidor de desenvolvimento local. Ele será necessário ao adicionar o código ao cliente Android.

  2. Inicie o servidor de desenvolvimento local, conforme descrito em Como testar uma API localmente.

  3. No projeto de cliente do Android Studio, localize o código que recebe o identificador para o serviço de API de back-end. Normalmente, esse código usa um Builder para configurar a solicitação de API.

  4. Substitua o URL raiz no objeto Builder (este é o URL ao qual o cliente Android se conecta na chamada da API de back-end) adicionando a linha:

    yourBuilderObject.setRootUrl("http://YOUR_MACHINE_IP_ADDRESS:8080/_ah/api");
    

    Por exemplo:

    public static Helloworld getApiServiceHandle(@Nullable GoogleAccountCredential credential) {
      // Use a builder to help formulate the API request.
      Helloworld.Builder helloWorld = new Helloworld.Builder(AppConstants.HTTP_TRANSPORT,
          AppConstants.JSON_FACTORY,credential);
    
      helloWorld.setRootUrl("http://YOUR_MACHINE_IP_ADDRESS:8080/_ah/api");
      return helloWorld.build();
    }
    

    Substitua YOUR_MACHINE_IP_ADDRESS pelo endereço IP do seu sistema.

  5. Recompile o projeto do cliente Android.

  6. Para executar o app cliente em um emulador AVD, faça o seguinte

    1. No Android Studio, acesse Ferramentas > Android > Gerenciador de AVD e inicie um AVD atual, se você tiver um. Caso contrário, crie um e, em seguida, inicie-o.
    2. Acesse Executar > Depurar YOUR_PROJECT_NAME, em que YOUR_PROJECT_NAME representa o nome do seu projeto do Google Cloud.
    3. Quando a escolha de um dispositivo for solicitada, selecione seu AVD.
    4. Teste seu cliente.
  7. Para executar o app cliente em um dispositivo físico Android, siga estes passos:

    1. Verifique se o dispositivo Android está ativado para depuração.
    2. No Android Studio, acesse Executar > Depurar YOUR_PROJECT_NAME.
    3. Quando a escolha de um dispositivo for solicitada, selecione seu dispositivo Android físico.
    4. Teste seu cliente.

Amostra de código-fonte do cliente

Para ver uma amostra do código, consulte Exemplo do Cloud Endpoints v2.0 para Android (em inglês).