Back-End APIs von einem Android-Client aufrufen

Auf dieser Seite wird beschrieben, wie ein Android-Client eine mit Cloud Endpoints Frameworks für App Engine erstellte Backend API aufruft.

Clientbibliothek generieren

Ihr Android-Client benötigt die Clientbibliothek, die von der Back-End API, die Ihr Client verwendet, generiert wird. Wenn Sie noch keine Clientbibliothek generiert haben, lesen Sie die Informationen unter Clientbibliothek generieren. Dieses Dokument enthält die Schritte, mit denen Sie die Clientbibliothek zum Android-Clientprojekt hinzufügen.

Projekt einrichten

In dieser Anleitung verwenden Sie Android Studio. Falls noch nicht geschehen, müssen Sie Android Studio so einrichten, dass ein Client unterstützt wird, der die Frameworks verwendet.

Projekt konfigurieren

In Android Studio verwendet Ihr Projekt die build.gradle-Datei für Abhängigkeiten und andere Einstellungen. Standardmäßig erstellt Android Studio eine build.gradle-Datei auf der Ebene des übergeordneten Projekts und eine gleichnamige Datei speziell für die Android-Anwendung im Android-Modul. Diese Anleitung bezieht sich auf die anwendungsspezifische build.gradle im Android-Modul.

Zum Konfigurieren von build.gradle:

  1. Klicken Sie doppelt auf build.gradle, um die Datei zu öffnen.

  2. Bearbeiten Sie die Datei, sodass sie die folgenden Zeilen enthält:

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

    Ersetzen Sie com.mycompany.myapp mit Ihren eigenen Werten.

  3. Klicken Sie auf File > Save All (Datei > Alle speichern), verlassen Sie Android Studio und starten Sie das Programm neu.

Clientbibliothek zum Projekt hinzufügen

So fügen Sie die Clientbibliothek dem Android-Projekt hinzu.

  1. Fügen Sie Ihrem Projekt ein /libs-Verzeichnis hinzu, sofern noch keines vorhanden ist. Es ist ein Peer zum Verzeichnis /src.

  2. Kopieren Sie die Clientbibliothek, die von der Back-End API generiert wurde, in /libs.

  3. Klicken Sie mit der rechten Maustaste auf die soeben hinzugefügte Bibliothek und wählen Sie Als Bibliothek hinzufügen für Ihr Projekt aus.

Dienstobjekt erstellen

Im Code Ihres Projekts müssen Sie ein Dienstobjekt verwenden, um Anfragen an die Back-End-API zu senden. Erstellen Sie für unauthenticated Anfragen das Dienstobjekt so:

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

Ersetzen Sie BACKEND_API_NAME durch den Namen Ihrer Backend API.

Back-End API aufrufen

Rufen Sie in Ihrem Projekt mit dem Dienstobjekt die API auf. Beispiel:

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

In diesem Snippet fragen Sie eine Liste aller Score-Objekte auf dem Server an. Wenn für list Parameter oder ein Anfragetext erforderlich waren, geben Sie diese im Befehl an. Android Studio bietet Codebeispiele, um verfügbare Methodenaufrufe und ihre benötigten Parameter zu identifizieren.

Wichtig: Es ist notwendig, dass Sie Anfragen in ihrem eigenen Thread senden, weil API-Aufrufe dazu führen, dass Anfragen über das Netzwerk gesendet werden. (Diese Voraussetzung wurde zu den neuesten Versionen von Android hinzugefügt, ist aber auch in älteren Versionen eine bewährte Methode.) Verwenden Sie dazu Thread oder AsyncTask. Beispiel:

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

Authentifizierte Aufrufe ausführen

Diese Anleitung deckt nur den Clientcode ab, den Sie einfügen müssen. Sie setzt voraus, dass Sie die Endpoints Frameworks-Unterstützung für die Authentifizierung bereits hinzugefügt haben, wie unter Nutzer authentifizieren beschrieben.

Wenn Ihr Android-Client Aufrufe an einen Endpunkt sendet, der eine Authentifizierung erfordert, müssen Sie:

  • Ihren Android-Client so konfigurieren, dass er dem Dienstobjekt Anmeldedaten zur Verfügung stellt;
  • Den Konto-Wähler verwenden, um die Auswahl der Anmeldekonten durch Nutzer zu unterstützen.

In den folgenden Abschnitten finden Sie weitere Details.

Android-Client konfigurieren, um Anmeldedaten zur Verfügung zu stellen

Damit Anfragen an eine Back-End API, die eine Authentifizierung benötigen, unterstützt werden, muss Ihr Android-Client Nutzeranmeldedaten beziehen und an das Dienstobjekt weitergeben.

Sie benötigen folgende Android-Berechtigungen, um Nutzeranmeldedaten abzurufen und den Konto-Wähler zu verwenden:

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

Zum Abrufen der Nutzeranmeldedaten rufen Sie GoogleAccountCredential.usingAudience so auf:

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

Der zweite Parameter für den Aufruf ist dabei das Präfix server:client_id, das der Webclient-ID der Back-End API vorangestellt ist.

Beispielcode: Anmeldedaten für das Dienstobjekt beziehen

Der folgende Code zeigt, wie Anmeldedaten abgerufen und an das Dienstobjekt übergeben werden:

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

Der vorstehende Beispielcode durchsucht alle von der Android-App gespeicherten geteilten Einstellungen und versucht, den Namen des Kontos zu ermitteln, das der Nutzer zur Authentifizierung bei Ihrer Anwendung verwenden möchte. Bei Erfolg erstellt der Code ein Anmeldedatenobjekt und gibt es an Ihr Dienstobjekt weiter. Mit diesen Anmeldedaten kann Ihre Android-App das entsprechende Token an Ihr Back-End weiterleiten.

Beachten Sie, dass bei diesem Codebeispiel geprüft wird, ob die Android-Anwendung bereits weiß, welches Konto zu verwenden ist. Ist dies der Fall, kann der logische Ablauf fortgesetzt werden und die Android-Anwendung ausführen. Wenn der Anwendung nicht bekannt ist, welches Konto sie verwenden soll, zeigt sie einen Anmeldebildschirm an oder fordert den Nutzer auf, ein Konto auszuwählen.

Schließlich erstellt das Beispiel ein Anmeldeobjekt und gibt es an das Dienstobjekt weiter. Mit diesen Anmeldedaten kann Ihre Android-App das entsprechende Token an Ihre App Engine-Webanwendung übergeben.

Konto-Wähler verwenden

Android bietet einen Intent, um ein Nutzerkonto auszuwählen. Sie können diesen folgendermaßen aufrufen:

static final int REQUEST_ACCOUNT_PICKER = 2;

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

Einen Handler, mit dem die Ergebnisse des Intents interpretiert werden, können Sie hier sehen:

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

Android-Client auf lokalem Entwicklungsserver testen

Sie können Ihren Client jederzeit und ohne vorheriges Ändern an einer Back-End API testen, die in einer App Engine-Produktionsinstanz ausgeführt wird. Wenn Sie Ihren Client hingegen an einer Back-End API testen möchten, die auf dem lokalen Entwicklungsserver ausgeführt wird, müssen Sie die Codezeile im Client so ändern, dass sie auf die IP-Adresse der Maschine mit dem lokalen Entwicklungsserver verweist.

Die notwendigen Änderungen und den Test mit dem lokalen Entwicklungsserver nehmen Sie so vor:

  1. Notieren Sie sich die IP-Adresse der Maschine, die den lokalen Entwicklungsserver ausführt. Sie benötigen sie, wenn Sie dem Android-Client Code hinzufügen.

  2. Starten Sie den lokalen Entwicklungsserver wie unter API Back-Ends lokal ausführen und testen beschrieben.

  3. Suchen Sie in Ihrem Clientprojekt in Android Studio den Code, der das Handle für den Back-End API-Dienst abruft. In der Regel verwendet dieser Code einen Builder, um die API-Anfrage einzurichten.

  4. Überschreiben Sie die Stamm-URL im Builder-Objekt (dies ist die URL, mit der sich der Android-Client im Back-End-API-Aufruf verbindet). Fügen Sie dazu die folgende Zeile hinzu:

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

    Beispiel:

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

    Ersetzen Sie YOUR_MACHINE_IP_ADDRESS durch die IP-Adresse Ihres Systems.

  5. Erstellen Sie Ihr Android-Clientprojekt neu.

  6. Falls Sie Ihre Clientanwendung auf einem AVD-Emulator ausführen wollen:

    1. Rufen Sie in Android Studio Tools > Android > AVD-Manager auf. Starten Sie entweder eine vorhandene AVD oder erstellen Sie eine, die Sie dann starten.
    2. Öffnen Sie Run > Debug YOUR_PROJECT_NAME (Ausführen > Fehlerbehebung für YOUR_PROJECT_NAME), wobei YOUR_PROJECT_NAME der Name Ihres Google Cloud-Projekts ist.
    3. Wenn Sie zur Wahl eines Geräts aufgefordert werden, wählen Sie Ihr AVD aus.
    4. Testen Sie Ihren Client.
  7. Falls Sie Ihre Clientanwendung auf einem physischen Android-Gerät ausführen wollen:

    1. Achten Sie darauf, dass auf Ihrem Android-Gerät die Fehlerbehebung aktiviert ist.
    2. Rufen Sie in Android Studio Ausführen > Fehlerbehebung in YOUR_PROJECT_NAME auf.
    3. Wenn Sie zur Wahl eines Geräts aufgefordert werden, wählen Sie Ihr physisches Android-Gerät aus.
    4. Testen Sie Ihren Client.

Beispiel für Clientquellcode

Beispielcode finden Sie unter Android Cloud Endpoints v2.0 – Beispiel.