Erste Schritte mit dem Driver SDK für Android

Mit dem Driver SDK können Sie die Navigation und das Tracking für Ihre Fahrt- und Bestellfortschrittsanwendung verbessern. Das Driver SDK stellt aktuelle Informationen zu Fahrzeugstandorten und Aufgaben für die Fleet Engine der On-demand Rides and Deliveries-Lösung bereit.

Das Driver SDK informiert die Fleet Engine-Dienste und Ihre benutzerdefinierten Dienste über den Standort und Zustand des Fahrzeugs. Beispielsweise kann das Fahrzeug ONLINE oder OFFLINE sein und der Fahrzeugstandort ändert sich im Laufe der Fahrt.

Mindestsystemanforderungen

Auf dem Mobilgerät muss Android 6.0 (API-Level 23) oder höher installiert sein.

Build- und Abhängigkeiten-Konfiguration

Die Treiber-SDK-Versionen 4.99 und höher sind im Google Maven-Repository verfügbar.

Gradle

Füge deiner Datei build.gradle Folgendes hinzu:

repositories {
    ...
    google()
}

Maven

Füge deiner Datei pom.xml Folgendes hinzu:

<project>
  ...
  <repositories>
    <repository>
      <id>google-maven-repository</id>
      <url>https://maven.google.com</url>
    </repository>
  </repositories>
  ...
</project>

Projektkonfiguration

Damit Sie das Driver SDK verwenden können, muss Ihre App auf minSdkVersion 23 oder höher ausgerichtet sein.

Damit Sie eine mit dem Driver SDK erstellte App ausführen können, müssen auf dem Android-Gerät Google Play-Dienste installiert sein.

Entwicklungsprojekt einrichten

So richten Sie Ihr Entwicklungsprojekt ein und rufen in der Google Cloud Console einen API-Schlüssel für das Projekt ab:

  1. Erstellen Sie ein neues Google Cloud Console-Projekt oder wählen Sie ein vorhandenes Projekt zur Verwendung mit dem Driver SDK aus. Warten Sie einige Minuten, bis das neue Projekt in der Google Cloud Console angezeigt wird.

  2. Damit Sie die Demo-App ausführen können, muss Ihr Projekt Zugriff auf das Maps SDK for Android haben. Wählen Sie in der Google Cloud Console APIs und Dienste > Bibliothek aus. Suchen Sie dann nach dem Maps SDK for Android und aktivieren Sie es.

  3. Rufen Sie einen API-Schlüssel für das Projekt ab. Wählen Sie dazu APIs und Dienste > Anmeldedaten > Anmeldedaten erstellen > API-Schlüssel aus. Weitere Informationen zum Abrufen eines API-Schlüssels finden Sie unter API-Schlüssel anfordern.

Treiber-SDK zur App hinzufügen

Das Treiber-SDK ist im Google Maven-Repository verfügbar. Das Repository enthält die SDK-Dateien für das Project Object Model (.pom) und Javadocs. So fügen Sie Ihrer App das Driver SDK hinzu:

  1. Fügen Sie Ihrer Gradle- oder Maven-Konfiguration die folgende Abhängigkeit hinzu und ersetzen Sie den Platzhalter VERSION_NUMBER durch die gewünschte Version des Treiber-SDK.

    Gradle

    Fügen Sie zum build.gradle Folgendes hinzu:

    dependencies {
      ...
      implementation 'com.google.android.libraries.mapsplatform.transportation:transportation-driver:VERSION_NUMBER'
    }
    

    Maven

    Fügen Sie zum pom.xml Folgendes hinzu:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.mapsplatform.transportation</groupId>
        <artifactId>transportation-driver</artifactId>
        <version>VERSION_NUMBER</version>
      </dependency>
    </dependencies>
    
  2. Das Driver SDK hängt vom Navigation SDK ab. Diese Abhängigkeit ist so konfiguriert, dass bei Bedarf eine bestimmte Navigation SDK-Version in der Build-Konfigurationsdatei explizit definiert werden muss. Beispiel: Wenn der erwähnte Codeblock weggelassen wird, kann das Projekt immer die neueste Version des Navigation SDK in der Hauptversion herunterladen. Das gemeinsame Verhalten der aktuellen Versionen des Driver SDK und des Navigation SDK wurde vor ihrer Veröffentlichung strengen Tests unterzogen.

    Ordnen Sie die Abhängigkeitskonfiguration Ihrer Entwicklungs- und Releaseumgebungen entsprechend an.

    Gradle

    Fügen Sie zum build.gradle Folgendes hinzu:

    dependencies {
      ...
      implementation 'com.google.android.libraries.navigation:navigation:5.0.0'
    }
    

    Maven

    Fügen Sie zum pom.xml Folgendes hinzu:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.navigation</groupId>
        <artifactId>navigation</artifactId>
        <version>5.0.0</version>
      </dependency>
    </dependencies>
    

API-Schlüssel in die App einfügen

Nachdem Sie Ihrer App das Driver SDK hinzugefügt haben, fügen Sie den API-Schlüssel zu Ihrer App hinzu. Sie müssen den Projekt-API-Schlüssel verwenden, den Sie beim Einrichten Ihres Entwicklungsprojekts erhalten haben.

In diesem Abschnitt wird beschrieben, wie Sie Ihren API-Schlüssel speichern, damit er von Ihrer App sicherer referenziert werden kann. Sie sollten ihn nicht in Ihrem Versionsverwaltungssystem einchecken. Sie sollte in der Datei local.properties gespeichert werden, die sich im Stammverzeichnis Ihres Projekts befindet. Weitere Informationen zur Datei local.properties finden Sie unter Gradle properties files.

Sie können das Secrets Gradle Plugin for Android verwenden, um diese Aufgabe zu optimieren.

So installieren Sie das Plug-in und speichern Ihren API-Schlüssel:

  1. Öffnen Sie die Datei build.gradle auf Stammebene und fügen Sie den folgenden Code in das Element dependencies unter buildscript ein.

    Groovy

    buildscript {
        dependencies {
            // ...
            classpath "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.0"
        }
    }
    

    Kotlin

    buildscript {
        dependencies {
            // ...
            classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.0")
        }
    }
    
  2. Öffne die Datei build.gradle auf App-Ebene und füge dem plugins-Element den folgenden Code hinzu.

    Groovy

    id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
    

    Kotlin

    id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
    
  3. Wenn Sie Android Studio verwenden, synchronisieren Sie Ihr Projekt mit Gradle.

  4. Öffnen Sie local.properties in Ihrem Verzeichnis auf Projektebene und fügen Sie den folgenden Code ein. Ersetzen Sie dabei YOUR_API_KEY durch Ihren eigenen API-Schlüssel.

    MAPS_API_KEY=YOUR_API_KEY
    
  5. Gehen Sie in der Datei AndroidManifest.xml zu com.google.android.geo.API_KEY und aktualisieren Sie das Attribut android:value so:

    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="${MAPS_API_KEY}" />
    

Das folgende Beispiel zeigt ein vollständiges Manifest für eine Beispiel-App:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.driverapidemo">
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/_AppTheme">

        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="${MAPS_API_KEY}" />

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Fügen Sie Ihrer App die erforderlichen Quellenangaben hinzu.

Wenn Sie das Driver SDK in Ihrer App verwenden, müssen Sie Quellenangaben und Open-Source-Lizenzen in den Abschnitt mit den rechtlichen Hinweisen für Ihre App aufnehmen. Die Quellenangaben sollten am besten als eigenständigen Menüpunkt oder als Teil des Menüpunkts Info eingebunden werden.

Die Lizenzinformationen befinden sich in der wieder aktivierten AAR-Datei in der Datei „third_party_Licenses.txt“.

Informationen zum Einbinden von Open-Source-Hinweisen finden Sie unter https://developers.google.com/android/guides/opensource.

Abhängigkeiten

Wenn Sie Ihre Builds mit ProGuard optimieren, müssen Sie Ihrer ProGuard-Konfigurationsdatei möglicherweise die folgenden Zeilen hinzufügen:

-dontwarn com.google.**
-dontwarn okio.**

Das Mindest-API-Level, das unterstützt wird, ist 23.

SDK initialisieren

Zum Initialisieren des DriverContext-Objekts ist eine Anbieter-ID (in der Regel die Google Cloud-Projekt-ID) erforderlich. Weitere Informationen zum Einrichten des Google Cloud-Projekts finden Sie unter Authentifizierung und Autorisierung.

Bevor Sie das Driver SDK verwenden können, müssen Sie zuerst das Navigation SDK initialisieren. So initialisieren Sie das SDK:

  1. Rufen Sie ein Navigator-Objekt aus NavigationApi ab.

    Java

    NavigationApi.getNavigator(
        this, // Activity
        new NavigationApi.NavigatorListener() {
          @Override
          public void onNavigatorReady(Navigator navigator) {
            // Keep a reference to the Navigator (used to configure and start nav)
            this.navigator = navigator;
          }
        }
    );
    

    Kotlin

    NavigationApi.getNavigator(
      this, // Activity
      object : NavigatorListener() {
        override fun onNavigatorReady(navigator: Navigator) {
          // Keep a reference to the Navigator (used to configure and start nav)
          this@myActivity.navigator = navigator
        }
      },
    )
    
  2. Erstellen Sie ein DriverContext-Objekt und füllen Sie die Pflichtfelder aus.

    Java

    DriverContext driverContext = DriverContext.builder(application)
        .setProviderId(providerId)
        .setVehicleId(vehicleId)
        .setAuthTokenFactory(authTokenFactory)
        .setNavigator(navigator)
        .setRoadSnappedLocationProvider(
            NavigationApi.getRoadSnappedLocationProvider(application))
        .build();
    

    Kotlin

    val driverContext =
      DriverContext.builder(application)
        .setProviderId(providerId)
        .setVehicleId(vehicleId)
        .setAuthTokenFactory(authTokenFactory)
        .setNavigator(navigator)
        .setRoadSnappedLocationProvider(NavigationApi.getRoadSnappedLocationProvider(application))
        .build()
    
  3. Verwenden Sie das DriverContext-Objekt, um *DriverApi zu initialisieren.

    Java

    RidesharingDriverApi ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext);
    

    Kotlin

    val ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext)
    
  4. Rufen Sie die RidesharingVehicleReporter aus dem API-Objekt ab. (*VehicleReporter erweitert NavigationVehicleReporter.)

    Java

    RidesharingVehicleReporter vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter();
    

    Kotlin

    val vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter()
    

Mit AuthTokenFactory authentifizieren

Wenn das Treiber SDK Standortaktualisierungen generiert, muss es diese Aktualisierungen an den Fleet Engine-Server senden. Zum Authentifizieren dieser Anfragen ruft das Driver SDK eine vom Aufrufer bereitgestellte Instanz von AuthTokenFactory auf. Die Factory ist für das Generieren von Authentifizierungstokens zum Zeitpunkt der Standortaktualisierung verantwortlich.

Wie genau Token generiert werden, hängt von der Situation des jeweiligen Entwicklers ab. Die Implementierung muss jedoch in der Regel folgende Anforderungen erfüllen:

  • Authentifizierungstoken, möglicherweise im JSON-Format, von einem HTTPS-Server abrufen
  • Token analysieren und im Cache speichern
  • Aktualisieren Sie das Token, wenn es abläuft.

Weitere Informationen zu den vom Fleet Engine-Server erwarteten Tokens finden Sie unter JSON Web Token (JWT) zur Autorisierung erstellen.

Hier ist die grundlegende Implementierung einer AuthTokenFactory:

Java

class JsonAuthTokenFactory implements AuthTokenFactory {
  private String token;  // initially null
  private long expiryTimeMs = 0;

  // This method is called on a thread whose only responsibility is to send
  // location updates. Blocking is OK, but just know that no location updates
  // can occur until this method returns.
  @Override
  public String getToken(AuthTokenContext authTokenContext) {
    if (System.currentTimeMillis() > expiryTimeMs) {
      // The token has expired, go get a new one.
      fetchNewToken(authTokenContext.getVehicleId());
    }
    return token;
  }

  private void fetchNewToken(String vehicleId) {
    String url =
        new Uri.Builder()
            .scheme("https")
            .authority("yourauthserver.example")
            .appendPath("token")
            .appendQueryParameter("vehicleId", vehicleId)
            .build()
            .toString();

    try (Reader r = new InputStreamReader(new URL(url).openStream())) {
      com.google.gson.JsonObject obj
          = com.google.gson.JsonParser.parseReader(r).getAsJsonObject();
      token = obj.get("Token").getAsString();
      expiryTimeMs = obj.get("TokenExpiryMs").getAsLong();

      // The expiry time could be an hour from now, but just to try and avoid
      // passing expired tokens, we subtract 10 minutes from that time.
      expiryTimeMs -= 10 * 60 * 1000;
    } catch (IOException e) {
      // It's OK to throw exceptions here. The StatusListener you passed to
      // create the DriverContext class will be notified and passed along the failed
      // update warning.
      throw new RuntimeException("Could not get auth token", e);
    }
  }
}

Kotlin

class JsonAuthTokenFactory : AuthTokenFactory() {

  private var token: String = ""
  private var expiryTimeMs: Long = 0

  // This method is called on a thread whose only responsibility is to send
  // location updates. Blocking is OK, but just know that no location updates
  // can occur until this method returns.
  override fun getToken(context: AuthTokenContext): String {
    if (System.currentTimeMillis() > expiryTimeMs) {
      // The token has expired, go get a new one.
      fetchNewToken(authTokenContext.getVehicleId())
    }
     return token
  }

  fun fetchNewToken(vehicleId: String) {
    val url =
      Uri.Builder()
        .scheme("https")
        .authority("yourauthserver.example")
        .appendPath("token")
        .appendQueryParameter("vehicleId", vehicleId)
        .build()
        .toString()

    try {
      val reader = InputStreamReader(URL(url).openStream())

      reader.use {
        val obj = com.google.gson.JsonParser.parseReader(r).getAsJsonObject()

        token = obj.get("ServiceToken").getAsString()
        expiryTimeMs = obj.get("TokenExpiryMs").getAsLong()

        // The expiry time could be an hour from now, but just to try and avoid
        // passing expired tokens, we subtract 10 minutes from that time.
        expiryTimeMs -= 10 * 60 * 1000
      }
    } catch (e: IOException) {
      // It's OK to throw exceptions here. The StatusListener you passed to
      // create the DriverContext class will be notified and passed along the failed
      // update warning.
      throw RuntimeException("Could not get auth token", e)
    }
  }
}

Diese spezielle Implementierung verwendet den integrierten Java-HTTP-Client, um ein Token im JSON-Format vom Authentifizierungsserver des Entwicklers abzurufen. Das Token wird für die Wiederverwendung gespeichert. Das Token wird noch einmal abgerufen, wenn das alte Token innerhalb von 10 Minuten seine Ablaufzeit erreicht.

Ihre Implementierung kann andere Dinge tun, z. B. die Verwendung eines Hintergrundthreads zum Aktualisieren von Tokens.

Ausnahmen in AuthTokenFactory werden als vorübergehend behandelt, es sei denn, sie treten wiederholt auf. Nach mehreren Versuchen geht das Driver SDK davon aus, dass der Fehler dauerhaft ist, und versucht nicht mehr, Aktualisierungen zu senden.

Status- und Error Reporting mit StatusListener

Da das Driver SDK im Hintergrund Aktionen ausführt, sollten Sie mit StatusListener Benachrichtigungen auslösen, wenn bestimmte Ereignisse auftreten, z. B. Fehler, Warnungen oder Debug-Meldungen. Fehler können vorübergehend sein (z. B. BACKEND_CONNECTIVITY_ERROR) oder dazu führen, dass Standortaktualisierungen dauerhaft beendet werden (z. B. VEHICLE_NOT_FOUND, was auf einen Konfigurationsfehler hindeutet).

Sie stellen eine optionale StatusListener-Implementierung wie die folgende bereit:

Java

class MyStatusListener implements StatusListener {
  /** Called when background status is updated, during actions such as location reporting. */
  @Override
  public void updateStatus(
      StatusLevel statusLevel, StatusCode statusCode, String statusMsg) {
    // Status handling stuff goes here.
    // StatusLevel may be DEBUG, INFO, WARNING, or ERROR.
    // StatusCode may be DEFAULT, UNKNOWN_ERROR, VEHICLE_NOT_FOUND,
    // BACKEND_CONNECTIVITY_ERROR, or PERMISSION_DENIED.
  }
}

Kotlin

class MyStatusListener : StatusListener() {
  /** Called when background status is updated, during actions such as location reporting. */
  override fun updateStatus(statusLevel: StatusLevel, statusCode: StatusCode, statusMsg: String) {
    // Status handling stuff goes here.
    // StatusLevel may be DEBUG, INFO, WARNING, or ERROR.
    // StatusCode may be DEFAULT, UNKNOWN_ERROR, VEHICLE_NOT_FOUND,
    // BACKEND_CONNECTIVITY_ERROR, or PERMISSION_DENIED.
  }
}

Hinweise zu SSL/TLS

Intern verwendet die Driver SDK-Implementierung SSL/TLS, um sicher mit dem Fleet Engine-Server zu kommunizieren. Für ältere Versionen von Android (API-Version 19 oder niedriger) ist möglicherweise ein SecurityProvider-Patch erforderlich, um mit dem Server kommunizieren zu können. Weitere Informationen zur Arbeit mit SSL unter Android finden Sie in diesem Artikel. Der Artikel enthält außerdem Codebeispiele zum Patchen des Sicherheitsanbieters.

Standortaktualisierungen aktivieren

Sobald Sie eine *VehicleReporter-Instanz haben, ist das Aktivieren von Standortupdates ganz einfach:

Java

RidesharingVehicleReporter reporter = ...;

reporter.enableLocationTracking();

Kotlin

val reporter = ...

reporter.enableLocationTracking()

Standortaktualisierungen werden in regelmäßigen Abständen gesendet, wenn der Fahrzeugstatus ONLINE ist. Durch das Aufrufen von reporter.enableLocationTracking() wird der Fahrzeugstatus nicht automatisch auf ONLINE gesetzt. Sie müssen den Fahrzeugstatus explizit festlegen.

Standardmäßig beträgt das Berichtsintervall 10 Sekunden. Das Berichtsintervall kann mit reporter.setLocationReportingInterval(long, TimeUnit) geändert werden. Das unterstützte Mindestaktualisierungsintervall beträgt 5 Sekunden. Häufigere Aktualisierungen können zu langsameren Anfragen und Fehlern führen.

Standortupdates deaktivieren

Wenn die Schicht des Fahrers beendet ist, können Standortaktualisierungen angehalten und das Fahrzeug durch Aufrufen von DeliveryVehicleReporter.disableLocationTracking oder RidesharingVehicleReporter.disableLocationTracking als offline markiert werden.

Durch diesen Aufruf wird eine letzte Aktualisierung zur sofortigen Auslieferung geplant, die angibt, dass das Fahrzeug offline ist. Das Update enthält nicht den Standort des Nutzers.

Fahrzeugstatus festlegen

Wenn Standortupdates aktiviert sind und der Fahrzeugstatus auf ONLINE gesetzt ist, wird das Fahrzeug für SearchVehicles-Anfragen zur Verfügung gestellt. Wenn Sie ein Fahrzeug als OFFLINE markieren, wird es ebenfalls als nicht verfügbar markiert.

Du kannst den Fahrzeugstatus serverseitig (siehe Fahrzeug aktualisieren) oder direkt im Driver SDK festlegen:

Java

RidesharingVehicleReporter reporter = ...;

reporter.enableLocationTracking();
reporter.setVehicleState(VehicleState.ONLINE);

Kotlin

val reporter = ...

reporter.enableLocationTracking()
reporter.setVehicleState(VehicleState.ONLINE)

Wenn Standortaktualisierungen aktiviert sind, wird beim nächsten Standortupdate ein Aufruf von setVehicleState ausgelöst.

Wenn ein Fahrzeug als ONLINE gekennzeichnet wird, wenn die Standortermittlung nicht aktiviert ist, wird ein IllegalStateException zurückgegeben. Ein Fahrzeug kann als OFFLINE gekennzeichnet werden, wenn die Standortermittlung noch nicht aktiviert oder explizit deaktiviert ist. Dies führt zu einer sofortigen Aktualisierung. Durch einen Aufruf von RidesharingVehicleReporter.disableLocationTracking() wird der Fahrzeugstatus auf OFFLINE gesetzt.

setVehicleState wird sofort zurückgegeben und der Thread zur Standortaktualisierung wird aktualisiert. Ähnlich wie bei der Fehlerbehandlung bei Standortaktualisierungen werden Fehler beim Aktualisieren des Fahrzeugstatus mithilfe des optional bereitgestellten StatusListener, der in der DriverContext festgelegt ist, weitergegeben.