Chiamata delle API di backend da un client Android

Questa pagina descrive in che modo un client Android chiama un'API di backend creata con Cloud Endpoints Frameworks per App Engine.

Generazione della libreria client in corso...

Il client Android richiede la libreria client generata dall'API di backend utilizzata dal client. Se non hai ancora la libreria client, consulta Generazione di una libreria client per i dettagli. In questo documento sono presenti passaggi che spiegano come aggiungere la libreria client al progetto client Android.

Configurazione del progetto

In queste istruzioni, utilizzi Android Studio. Se non l'hai ancora fatto, devi configurare Android Studio per supportare un client che utilizza i framework.

Configurazione del progetto

In Android Studio, il progetto utilizza il file build.gradle per le dipendenze e altre impostazioni. Per impostazione predefinita, Android Studio crea un file build.gradle a livello di progetto principale e un file specifico per l'app Android nel modulo Android. Queste istruzioni si riferiscono al criterio build.gradle specifico per l'app nel modulo Android.

Per configurare build.gradle:

  1. Fai doppio clic sull'icona build.gradle per aprirla.

  2. Modifica questo file in modo che contenga le seguenti righe:

    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')
    }
    
    

    Sostituisci com.mycompany.myapp con i tuoi valori.

  3. Fai clic su File > Salva tutto, quindi esci da Android Studio e riavvialo.

Aggiunta della libreria client al progetto

Per aggiungere la libreria client al progetto Android:

  1. Aggiungi una directory /libs al progetto, se non ne ha già una. È un peer della directory /src.

  2. Copia la libreria client generata dall'API di backend in /libs.

  3. Fai clic con il pulsante destro del mouse sulla libreria appena aggiunta, quindi seleziona Aggiungi come libreria al tuo progetto.

Creazione dell'oggetto di servizio

Nel codice del progetto devi utilizzare un oggetto di servizio per effettuare richieste all'API di backend. Per le richieste unauthenticated, costruisci l'oggetto di servizio come segue:

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

Sostituisci BACKEND_API_NAME con il nome della tua API di backend.

Chiamata all'API di backend

Nel progetto, chiama l'API utilizzando l'oggetto di servizio. Ad esempio:

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

In questo snippet, richiedi un elenco di tutti gli oggetti Score sul server. Se list richiede parametri o il corpo di una richiesta, devi fornirli nel comando. Android Studio fornisce il completamento del codice per le chiamate ai metodi disponibili per l'identità e i relativi parametri richiesti.

È importante notare che, poiché le chiamate API generano richieste sulla rete, devi effettuare le richieste nel proprio thread. (Questo requisito è stato aggiunto alle versioni recenti di Android, ma è una best practice anche nelle versioni precedenti.) A questo scopo, utilizza un Thread o AsyncTask. Ad esempio:

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.
  }
}

Effettuare chiamate autenticate

Queste istruzioni riguardano solo la codifica del client che devi aggiungere. Presumono che tu abbia già aggiunto il supporto di Endpoints Frameworks per l'autenticazione, come descritto in Autenticazione degli utenti.

Se il tuo client Android effettua chiamate a un endpoint che richiede l'autenticazione, devi:

  • Configura il client Android in modo che fornisca le credenziali all'oggetto di servizio.
  • Utilizza il selettore di account per supportare la scelta degli account di accesso da parte dell'utente.

Nelle sezioni che seguono vengono forniti dettagli.

Configurazione del client Android per fornire le credenziali

Per supportare le richieste a un'API di backend che richiede l'autenticazione, il client Android deve ottenere le credenziali utente e passarle all'oggetto di servizio.

Per ottenere le credenziali utente e utilizzare il selettore di account, sono necessarie le seguenti autorizzazioni Android:

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

Per ottenere le credenziali utente, chiama GoogleAccountCredential.usingAudience come segue:

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

Dove il secondo parametro della chiamata è il prefisso server:client_id anteposto all'ID client web dell'API di backend.

Codice di esempio: recupero delle credenziali per l'oggetto di servizio

Il codice seguente mostra come ottenere le credenziali e passarle all'oggetto di servizio:

// 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;
}

Il codice campione precedente cerca eventuali preferenze condivise archiviate dall'app per Android e tenta di trovare il nome dell'account che l'utente vuole utilizzare per autenticarsi nella tua applicazione. In caso di esito positivo, il codice crea un oggetto credenziali e lo passa all'oggetto di servizio. Queste credenziali consentono all'app Android di passare il token appropriato al backend.

Tieni presente che l'esempio di codice controlla se l'app per Android sa già quale account utilizzare. In caso affermativo, il flusso logico può continuare ed eseguire l'app per Android. Se l'app non sa quale account utilizzare, mostra una schermata di accesso o chiede all'utente di scegliere un account.

Infine, l'esempio crea un oggetto credenziali e lo passa all'oggetto di servizio. Queste credenziali consentono all'app Android di passare il token appropriato all'app web App Engine.

Utilizzare il selettore di account

Android fornisce un intent per selezionare un account utente. Puoi richiamarlo nel seguente modo:

static final int REQUEST_ACCOUNT_PICKER = 2;

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

Un gestore per l'interpretazione del risultato di questo intent è mostrato qui:

@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;
  }
}

Test di un client Android rispetto a un server di sviluppo locale

Puoi testare il tuo client rispetto a un'API di backend in esecuzione nell'App Engine di produzione in qualsiasi momento senza apportare alcuna modifica. Tuttavia, se vuoi testare il tuo client rispetto a un'API di backend in esecuzione sul server di sviluppo locale, devi cambiare la riga di codice del client in modo che rimandi all'indirizzo IP della macchina che esegue il server di sviluppo locale.

Per apportare le modifiche necessarie ed eseguire il test utilizzando il server di sviluppo locale:

  1. Prendi nota dell'indirizzo IP della macchina che esegue il server di sviluppo locale, perché ti serve quando aggiungi codice al client Android.

  2. Avvia il server di sviluppo locale, come descritto in Test di un'API in locale.

  3. Nel progetto client di Android Studio, individua il codice che ottiene l'handle al servizio API di backend. In genere, questo codice utilizza un Builder per configurare la richiesta API.

  4. Esegui l'override dell'URL principale nell'oggetto Builder (questo è l'URL a cui si connette il client Android nella chiamata API di backend) aggiungendo la riga:

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

    Ad esempio:

    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();
    }
    

    Sostituisci YOUR_MACHINE_IP_ADDRESS con l'indirizzo IP del tuo sistema.

  5. Ricrea il progetto client Android.

  6. Se vuoi eseguire l'app client in un emulatore AVD:

    1. In Android Studio, vai a Strumenti > Android > Gestione AVD e avvia una durata di visualizzazione media, se ne hai una, altrimenti creane una e poi avviala.
    2. Vai a Esegui > Debug YOUR_PROJECT_NAME, dove YOUR_PROJECT_NAME rappresenta il nome del tuo progetto Google Cloud.
    3. Quando ti viene chiesto di scegliere un dispositivo, seleziona la durata di visualizzazione media.
    4. Testa il tuo cliente.
  7. Se vuoi eseguire l'app client su un dispositivo Android fisico:

    1. Assicurati che il tuo dispositivo Android sia abilitato per il debug.
    2. In Android Studio, vai a Esegui > Debug YOUR_PROJECT_NAME.
    3. Quando ti viene chiesto di scegliere un dispositivo, seleziona il tuo dispositivo Android fisico.
    4. Testa il tuo cliente.

Esempio di codice sorgente del client

Per codice campione, vedi l'esempio di Android Cloud Endpoints v2.0.