Chiamate alle API di backend da un client Android

Questa pagina descrive come un client Android chiama un'API di backend creata con i framework Cloud Endpoints per App Engine.

Generazione della libreria client

Il client Android richiede la libreria client generata dall'API di backend utilizzata dal client. Se non hai ancora la libreria client, consulta la sezione Generazione di una libreria client per maggiori dettagli. Questo documento illustra i passaggi per aggiungere la libreria client al progetto client Android.

Configurazione del progetto

In queste istruzioni utilizzerai Android Studio. Se non l'hai ancora fatto, devi configurare Android Studio in modo da supportare un client che utilizzi 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 di primo livello del progetto e un file specifico per l'app Android nel modulo Android. Queste istruzioni riguardano il build.gradle specifico dell'app nel modulo Android.

Per configurare build.gradle:

  1. Fai doppio clic su build.gradle per aprirlo.

  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 esiste già una. È un peer della directory /src.

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

  3. Fai clic con il tasto destro del mouse sulla libreria che hai appena aggiunto e seleziona Aggiungi come libreria per il progetto.

Creazione dell'oggetto del servizio

Nel codice del progetto, devi utilizzare un oggetto di servizio per effettuare richieste all'API di backend. Per le richieste non autenticate, crea l'oggetto 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 dell'API di backend.

Chiamata all'API di backend

Nel tuo progetto, chiama l'API utilizzando l'oggetto service. Ad esempio:

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

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

È importante notare che, poiché le chiamate API generano richieste sulla rete, devi effettuare le richieste in un thread a parte. Questo requisito è stato aggiunto alle versioni recenti di Android, ma è una best practice anche nelle versioni precedenti. Per farlo, utilizza un Thread o un 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 da aggiungere. Si presume che tu abbia già aggiunto il supporto dei framework di endpoint per l'autenticazione come descritto in Autenticazione degli utenti.

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

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

Le sezioni seguenti forniscono i dettagli.

Configurare il client Android in modo che fornisca le credenziali

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

Per ottenere le credenziali utente e utilizzare il selettore di account, devi disporre delle 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 preposto all'ID client web dell'API di backend.

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

Il codice seguente mostra come ottenere le credenziali e passarle all'oggetto 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 le preferenze condivise memorizzate dall'app 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 credentials e lo passa all'oggetto service. Queste credenziali consentono alla tua app Android di passare il token appropriato al tuo backend.

Tieni presente che il esempio di codice controlla se l'app per Android sa già quale account utilizzare. In questo caso, 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 servizio. Queste credenziali consentono alla tua app per Android di trasmettere il token appropriato alla tua app web App Engine.

Utilizzo del selettore di account

Android fornisce un'intent per selezionare un account utente. Puoi invocarlo come segue:

static final int REQUEST_ACCOUNT_PICKER = 2;

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

Di seguito è riportato un gestore per l'interpretazione del risultato di questo intento:

@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 su un server di sviluppo locale

Puoi testare il client con un'API di backend in esecuzione in produzione su App Engine in qualsiasi momento senza apportare modifiche. Tuttavia, se vuoi testare il client con un'API di backend in esecuzione sul server di sviluppo locale, devi modificare la riga di codice nel client in modo che indichi l'indirizzo IP della macchina su cui è in esecuzione il server di sviluppo locale.

Per apportare le modifiche necessarie e testare il server di sviluppo locale:

  1. Prendi nota dell'indirizzo IP della macchina su cui è in esecuzione il server di sviluppo locale, perché ti servirà quando aggiungi codice al client Android.

  2. Avvia il server di sviluppo locale, come descritto in Eseguire e testare i backend API localmente.

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

  4. Sostituisci l'URL principale nell'oggetto Builder (l'URL a cui si connette il client Android nella chiamata all'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. Ricostruisci il progetto client Android.

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

    1. In Android Studio, vai a Strumenti > Android > Gestore AVD e avvia un AVD esistente, se ne hai uno, altrimenti creane uno e avvialo.
    2. Vai a Esegui > Esegui il debug di 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 l'AVD.
    4. Testa il tuo client.
  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 client.

Codice sorgente del client di esempio

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