Erste Schritte mit dem Consumer SDK für Android

Du kannst das Consumer SDK verwenden, um eine einfache Nutzer-App zu erstellen und auszuführen, die in die Back-End-Dienste der On-Demand-Lösung „Rides and Deliveries“ eingebunden ist. Sie können eine Fahrt- und Bestellfortschritts-App erstellen, die eine aktive Fahrt anzeigen, auf Fahrtaktualisierungen reagieren und Fahrtfehler beheben kann.

Da das Consumer SDK eine modulare Architektur hat, können Sie die Teile der API, die Sie für Ihre Anwendung verwenden möchten, verwenden und in Ihre eigenen APIs, von Fleet Engine bereitgestellte Back-End-Dienste und zusätzliche APIs der Google Maps Platform einbinden.

Mindestsystemanforderungen

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

Build- und Abhängigkeiten-Konfiguration

Die Consumer SDK-Versionen 1.99.0 und höher sind über das Google Maven-Repository verfügbar. Der zuvor verwendete Kanal für das private Repository wurde eingestellt.

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

Wenn Sie das Consumer SDK for Android verwenden möchten, muss Ihre App auf minSdkVersion 23 oder höher ausgerichtet sein.

Damit eine App ausgeführt werden kann, die mit dem Consumer SDK erstellt wurde, 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 Consumer 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.

Consumer SDK zur App hinzufügen

Das Consumer SDK ist über ein privates 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 Consumer SDK hinzu:

  1. Richten Sie Ihre Umgebung so ein, dass sie wie im vorherigen Abschnitt beschrieben auf das Maven-Repository des Hosts zugreift.

    Wenn Sie in settings.gradle eine Konfiguration für die zentrale Abhängigkeitsverwaltung deklariert haben, deaktivieren Sie sie so.

    • Entfernen Sie den folgenden Codeblock in settings.gradle:

      import org.gradle.api.initialization.resolve.RepositoriesMode
      dependencyResolutionManagement {
          repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
          repositories {
              google()
              mavenCentral()
          }
      }
      
  2. 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 Consumer SDK.

    Gradle

    Fügen Sie zum build.gradle Folgendes hinzu:

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

    Maven

    Fügen Sie zum pom.xml Folgendes hinzu:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.mapsplatform.transportation</groupId>
        <artifactId>transportation-consumer</artifactId>
        <version>VERSION_NUMBER</version>
      </dependency>
    </dependencies>
    
  3. Das Consumer SDK hängt vom Maps SDK ab. Diese Abhängigkeit ist so konfiguriert, dass das Consumer SDK bei der Veröffentlichung einer neuen Version weiterhin die erforderliche Mindestversion des Maps SDK verwendet, wenn die Version des Maps SDK in der Build-Konfigurationsdatei nicht explizit definiert ist.

    Gradle

    Fügen Sie zum build.gradle Folgendes hinzu:

    dependencies {
      ...
      implementation 'com.google.android.gms:play-services-maps:18.1.0'
    }
    

    Maven

    Fügen Sie zum pom.xml Folgendes hinzu:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.gms</groupId>
        <artifactId>play-services-maps</artifactId>
        <version>18.1.0</version>
      </dependency>
    </dependencies>
    

API-Schlüssel in die App einfügen

Nachdem Sie Ihrer App das Consumer 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.consumerapidemo">
    <uses-permission android:name="android.permission.ACCESS_FINE_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 Consumer 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.

SDK-Authentifizierung für Verbraucher

Das Consumer SDK ermöglicht die Authentifizierung mithilfe von JSON Web Tokens. Ein JSON Web Token (JWT) ist ein Zugriffstoken auf JSON-Basis, das eine oder mehrere Anforderungen für einen Dienst bereitstellt. Beispielsweise könnte ein Server ein Token generieren, bei dem die Anforderung "als Administrator angemeldet" ist, und es einem Client zur Verfügung stellen. Der Client könnte dann dieses Token verwenden, um nachzuweisen, dass er als Administrator angemeldet ist.

Das Consumer SDK verwendet das von der Anwendung bereitgestellte JSON Web Token, um mit Fleet Engine zu kommunizieren. Weitere Informationen finden Sie unter Fleet Engine-Authentifizierung und -Autorisierung.

Das Autorisierungstoken muss im authorization-Header des Tokens die Anforderung tripid:TRIP_ID enthalten, wobei TRIP_ID die Fahrt-ID ist. Dadurch erhält das Consumer SDK Zugriff auf Fahrtdetails wie Fahrzeugposition, Route und voraussichtliche Ankunftszeit.

JSON Web Token-Callbacks

Das Consumer SDK registriert während der Initialisierung einen Rückruf für ein Autorisierungstoken bei der Anwendung. Das SDK ruft die Anwendung auf, um ein Token für alle Netzwerkanfragen abzurufen, die eine Autorisierung erfordern.

Wir empfehlen dringend, die Autorisierungstokens Ihrer Callback-Implementierung im Cache zu speichern und erst zu aktualisieren, wenn die expiry-Zeit abgelaufen ist. Tokens sollten mit einer Ablaufzeit von einer Stunde ausgestellt werden.

Der Callback für das Autorisierungstoken gibt an, welches Diensttoken für den Dienst TripService erforderlich ist. Außerdem wird die erforderliche tripId für den Kontext angegeben.

Das folgende Codebeispiel zeigt, wie ein Autorisierungstoken-Callback implementiert wird.

Java

class JsonAuthTokenFactory implements AuthTokenFactory {

  private static final String TOKEN_URL =
      "https://yourauthserver.example/token";

  private static class CachedToken {
    String tokenValue;
    long expiryTimeMs;
    String tripId;
  }

  private CachedToken token;

  /*
  * This method is called on a background thread. Blocking is OK. However, be
  * aware that no information can be obtained from Fleet Engine until this
  * method returns.
  */
  @Override
  public String getToken(AuthTokenContext context) {
    // If there is no existing token or token has expired, go get a new one.
    String tripId = context.getTripId();
    if (tripId == null) {
      throw new RuntimeException("Trip ID is missing from AuthTokenContext");
    }
    if (token == null || System.currentTimeMillis() > token.expiryTimeMs ||
        !tripId.equals(token.tripId)) {
      token = fetchNewToken(tripId);
    }
    return token.tokenValue;
  }

  private static CachedToken fetchNewToken(String tripId) {
    String url = TOKEN_URL + "/" + tripId;
    CachedToken token = new CachedToken();

    try (Reader r = new InputStreamReader(new URL(url).openStream())) {
      com.google.gson.JsonObject obj
          = com.google.gson.JsonParser.parseReader(r).getAsJsonObject();

      token.tokenValue = obj.get("ServiceToken").getAsString();
      token.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 5 minutes from that time.
      */
      token.expiryTimeMs -= 5 * 60 * 1000;
    } catch (IOException e) {
      /*
      * It's OK to throw exceptions here. The error listeners will receive the
      * error thrown here.
      */
      throw new RuntimeException("Could not get auth token", e);
    }
    token.tripId = tripId;

    return token;
  }
}

Kotlin

class JsonAuthTokenFactory : AuthTokenFactory() {

  private var token: CachedToken? = null

  /*
  * This method is called on a background thread. Blocking is OK. However, be
  * aware that no information can be obtained from Fleet Engine until this
  * method returns.
  */
  override fun getToken(context: AuthTokenContext): String {
    // If there is no existing token or token has expired, go get a new one.
    val tripId = 
      context.getTripId() ?: 
        throw RuntimeException("Trip ID is missing from AuthTokenContext")

    if (token == null || System.currentTimeMillis() > token.expiryTimeMs ||
        tripId != token.tripId) {
      token = fetchNewToken(tripId)
    }

    return token.tokenValue
  }

  class CachedToken(
    var tokenValue: String? = "", 
    var expiryTimeMs: Long = 0,
    var tripId: String? = "",
  )

  private companion object {
    const val TOKEN_URL = "https://yourauthserver.example/token"

    fun fetchNewToken(tripId: String) {
      val url = "$TOKEN_URL/$tripId"
      val token = CachedToken()

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

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

          token.tokenValue = obj.get("ServiceToken").getAsString()
          token.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 5 minutes from that time.
          */
          token.expiryTimeMs -= 5 * 60 * 1000
        }
      } catch (e: IOException) {
        /*
        * It's OK to throw exceptions here. The error listeners will receive the
        * error thrown here.
        */
        throw RuntimeException("Could not get auth token", e)
      }

      token.tripId = tripId

      return token
    }
  }
}

API initialisieren

Bevor Sie diese Schritte ausführen, wird davon ausgegangen, dass Sie die entsprechenden Dienste und das Consumer SDK aktiviert haben.

ConsumerApi-Instanz abrufen

Damit du das Consumer SDK verwenden kannst, muss ConsumerApi in deiner App asynchron initialisiert werden. Die API ist ein Singleton-Element. Die Initialisierungsmethode verwendet eine AuthTokenFactory. Die Factory generiert bei Bedarf neue JWT-Tokens für den Nutzer.

providerId ist die Projekt-ID Ihres Google Cloud-Projekts. Weitere Informationen zum Erstellen des Projekts finden Sie im Nutzerhandbuch zu Fleet Engine.

Deine App sollte die AuthTokenFactory implementieren, wie unter Authentifizierung für das Consumer SDK beschrieben.

Java

Task<ConsumerApi> consumerApiTask = ConsumerApi.initialize(
    this, "myProviderId", authTokenFactory);

consumerApiTask.addOnSuccessListener(
  consumerApi -> this.consumerApi = consumerApi);

Kotlin

val consumerApiTask =
  ConsumerApi.initialize(this, "myProviderId", authTokenFactory)

consumerApiTask?.addOnSuccessListener { consumerApi: ConsumerApi ->
  this@YourActivity.consumerApi = consumerApi
}

Maps SDK und Karten-Renderer

Consumer SDK 2.x.x unterstützt das Maps SDK for Android 18.1.0 und höher. In der folgenden Tabelle sind der Standard-Renderer nach Maps SDK-Version und die Unterstützung beider Renderer zusammengefasst. Wir empfehlen, den neuesten Renderer zu verwenden. Wenn Sie jedoch den alten Renderer verwenden müssen, können Sie ihn explizit mit MapsInitializer.initialize() angeben.

Maps SDK-Version Unterstützt den neuesten Renderer Unterstützt den alten Renderer Standard-Renderer
V18.1.0 und niedriger Ja Ja Alt*
V18.2.0 Ja Ja Neueste

* Mit der Einführung des neuen Maps Renderer wird standardmäßig der neueste Renderer verwendet.

Maps SDK als Abhängigkeit hinzufügen

Gradle

Fügen Sie zum build.gradle Folgendes hinzu:

dependencies {
  //...
  implementation "com.google.android.gms:play-services-maps:VERSION_NUMBER"
}

Maven

Fügen Sie zum pom.xml Folgendes hinzu:

 <dependencies>
   ...
   <dependency>
     <groupId>com.google.android.gms</groupId>
     <artifactId>play-services-maps</artifactId>
     <version>18.1.0</version>
   </dependency>
 </dependencies>

Initialisieren Sie das Maps SDK, bevor Sie das Consumer SDK initialisieren

Rufen Sie in der Application- oder Start-Activity-Klasse MapsInitializer.initialize() auf und warten Sie auf das Ergebnis der Renderer-Anfrage, bevor Sie das Consumer SDK initialisieren.

java

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  initViews();

  MapsInitializer.initialize(getApplicationContext(), Renderer.LATEST,
      new OnMapsSdkInitializedCallback() {
        @Override
        public void onMapsSdkInitialized(Renderer renderer) {
          switch (renderer) {
            case LATEST:
              Log.i("maps_renderer", "LATEST renderer");
              break;
            case LEGACY:
              Log.i("maps_renderer", "LEGACY renderer");
              break;
          }

          initializeConsumerSdk();
        }
      });
}

Kotlin

fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  setContentView(R.layout.main)
  initViews()

  MapsInitializer.initialize(
    getApplicationContext(), Renderer.LATEST,
    object : OnMapsSdkInitializedCallback() {
      fun onMapsSdkInitialized(renderer: Renderer?) {
        when (renderer) {
          LATEST -> Log.i("maps_renderer", "LATEST renderer")
          LEGACY -> Log.i("maps_renderer", "LEGACY renderer")
        }
        initializeConsumerSdk()
      }
    })
  }

Benutzeroberfläche erstellen

Sie können entweder ConsumerMapFragment oder ConsumerMapView verwenden, um die Benutzeroberfläche für Ihre Anwendung zu erstellen. Mit ConsumerMapFragment können Sie Ihre Karte mit einem Fragment definieren, während Sie mit ConsumerMapView einen View verwenden können. Die Funktion des Mitfahrdienstes ist in ConsumerMapView und ConsumerMapFragment identisch. Sie können also eine davon auswählen, ob View oder Fragment für Ihre Anwendung besser geeignet ist.

Unterstützung für API 19 (KitKat) und Vektor-Drawables hinzufügen

Wenn dein App-Design Unterstützung für API 19-Geräte (KitKat) und Vektor-Drawables erfordert, füge deiner Aktivität den folgenden Code hinzu. Mit diesem Code wird AppCompatActivity auf die Verwendung von Vektor-Drawables im Consumer SDK erweitert.

Java

// ...
import android.support.v7.app.AppCompatActivity;

// ...

public class ConsumerTestActivity extends AppCompatActivity {
  // ...
}

Kotlin

// ...
import android.support.v7.app.AppCompatActivity

// ...

class ConsumerTestActivity : AppCompatActivity() {
  // ...
}

Kartenfragment oder -ansicht hinzufügen

Sie erstellen die Karte, um die Fahrtfreigabe in einem Android-Fragment oder einer Ansicht darzustellen, die Sie in der XML-Datei für das App-Layout (unter /res/layout) definieren. Das Fragment (oder die Ansicht) bietet dann Zugriff auf die Karte, auf die Ihre App zugreifen und die sie ändern kann. Die Karte enthält auch einen Handle für ConsumerController, mit dem deine App die Freigabe der Fahrt steuern und anpassen kann.

Karte und Controller teilen

Sie definieren die gemeinsame Karte entweder als Fragment (mit ConsumerMapFragment) oder als Ansicht (mit ConsumerMapView), wie im folgenden Codebeispiel gezeigt. Die Methode onCreate() sollte dann getConsumerGoogleMapAsync(callback) aufrufen, wodurch das ConsumerGoogleMap asynchron im Callback zurückgegeben wird. Anschließend verwenden Sie ConsumerGoogleMap, um sich die Fahrtfreigabe anzeigen zu lassen. Diese kann von Ihrer App nach Bedarf aktualisiert werden.

ConsumerMapFragment

Sie definieren das Fragment in Ihrer Anwendungslayout-XML-Datei, wie im folgenden Codebeispiel gezeigt.

<fragment
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:name="com.google.android.libraries.mapsplatform.transportation.consumer.view.ConsumerMapFragment"
    android:id="@+id/consumer_map_fragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Der Aufruf von getConsumerGoogleMapAsync() sollte über die Methode onCreate() erfolgen.

Java

public class SampleAppActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {

    // Find the ConsumerMapFragment.
    ConsumerMapFragment consumerMapFragment =
        (ConsumerMapFragment) fragmentManager.findFragmentById(R.id.consumer_map_fragment);

    // Initiate the callback that returns the map.
    if (consumerMapFragment != null) {
      consumerMapFragment.getConsumerGoogleMapAsync(
          new ConsumerMapReadyCallback() {
            // The map returned in the callback is used to access the ConsumerController.
            @Override
            public void onConsumerMapReady(@NonNull ConsumerGoogleMap consumerGoogleMap) {
              ConsumerController consumerController = consumerGoogleMap.getConsumerController();
            }
          });
    }
  }

}

Kotlin

class SampleAppActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    // Find the ConsumerMapFragment.
    val consumerMapFragment =
      fragmentManager.findFragmentById(R.id.consumer_map_fragment) as ConsumerMapFragment

    consumerMapFragment.getConsumerGoogleMapAsync(
      object : ConsumerMapReadyCallback() {
        override fun onConsumerMapReady(consumerGoogleMap: ConsumerGoogleMap) {
          val consumerController = consumerGoogleMap.getConsumerController()!!
        }
      }
    )
  }
}
ConsumerMapView

Die Ansicht kann entweder in einem Fragment oder in einer Aktivität verwendet werden, wie in Ihrer XML-Datei definiert.

<com.google.android.libraries.mapsplatform.transportation.consumer.view.ConsumerMapView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/consumer_map_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Der Aufruf von getConsumerGoogleMapAsync() sollte von onCreate() stammen. Zusätzlich zum Callback-Parameter sind die enthaltene Aktivität oder das Fragment sowie die GoogleMapOptions (die null sein kann) mit Konfigurationsattributen für die MapView erforderlich. Die Aktivität oder die Fragment-Basisklasse muss entweder eine FragmentActivity- oder eine unterstützende Fragment sein, da sie Zugriff auf ihren Lebenszyklus bieten.

Java

public class SampleAppActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    ConsumerMapView mapView = findViewById(R.id.consumer_map_view);

    if (mapView != null) {
      mapView.getConsumerGoogleMapAsync(
          new ConsumerMapReadyCallback() {
            // The map returned in the callback is used to access the ConsumerController.
            @Override
            public void onConsumerMapReady(@NonNull ConsumerGoogleMap consumerGoogleMap) {
              ConsumerController consumerController = consumerGoogleMap.getConsumerController();
            }
          }, this, null);
    }
  }

}

Kotlin

class SampleAppActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    val mapView = findViewById(R.id.consumer_map_view) as ConsumerMapView

    mapView.getConsumerGoogleMapAsync(
      object : ConsumerMapReadyCallback() {
        // The map returned in the callback is used to access the ConsumerController.
        override fun onConsumerMapReady(consumerGoogleMap: ConsumerGoogleMap) {
          val consumerController = consumerGoogleMap.getConsumerController()!!
        }
      },
      /* fragmentActivity= */ this,
      /* googleMapOptions= */ null,
    )
  }
}

Ein MapView in einem Fragment ist dasselbe wie im obigen Beispiel für MapView in einer Aktivität, mit der Ausnahme, dass das Fragment das Layout, das MapView in der Methode onCreateView() des Fragments enthält, aufgebläht.

Java

public class MapViewInFragment extends Fragment {

  @Override
  public View onCreateView(
      @NonNull LayoutInflater layoutInflater,
      @Nullable ViewGroup viewGroup,
      @Nullable Bundle bundle) {
    return layoutInflater.inflate(R.layout.consumer_map_view, viewGroup, false);
  }

}

Kotlin

class MapViewInFragment : Fragment() {
  override fun onCreateView(
    layoutInflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?,
  ): View {
    return layoutInflater.inflate(R.layout.consumer_map_view, viewGroup, false)
  }
}

Den Kamerazoom so anpassen, dass er sich auf eine Reise fokussiert

Mit der standardmäßigen Schaltfläche „Mein Standort“ im Maps SDK wird die Kamera auf den Gerätestandort zentriert.

Wenn gerade eine Fahrt geteilt wird, sollten Sie die Kamera so zentrieren, dass die Fahrt statt des Gerätestandorts im Mittelpunkt steht.

Consumer SDK for Android – integrierte Android-Lösung: AutoCamera

Damit Sie sich auf die Reise statt auf den Gerätestandort konzentrieren können, bietet das Consumer SDK eine AutoCamera-Funktion, die standardmäßig aktiviert ist. Die Kamera zoomt, um die Route und den nächsten Wegpunkt zu fokussieren.

AutoCamera

Kameraverhalten anpassen

Wenn Sie das Kameraverhalten genauer steuern möchten, können Sie die automatische Kamera mit ConsumerController.setAutoCameraEnabled() deaktivieren oder aktivieren.

ConsumerController.getCameraUpdate() gibt zu diesem Zeitpunkt die empfohlenen Kameragrenzen zurück. Anschließend können Sie diese CameraUpdate als Argument für GoogleMap.moveCamera() oder GoogleMap.animateCamera() angeben.

Auf Mitfahrdienste und Karten zugreifen

Sie benötigen Zugriff auf ConsumerGoogleMap und ConsumerController, um Mitfahrdienste und Karteninteraktionen in Ihrer App zu unterstützen. ConsumerMapFragment und ConsumerMapView geben beide asynchron ConsumerGoogleMap in ConsumerMapReadyCallback zurück. ConsumerGoogleMap gibt ConsumerController von getConsumerController() zurück. So können Sie auf ConsumerGoogleMap und ConsumerController zugreifen:

Java

private ConsumerGoogleMap consumerGoogleMap;
private ConsumerController consumerController;
private ConsumerMapView consumerMapView;

consumerMapView.getConsumerGoogleMapAsync(
    new ConsumerMapReadyCallback() {
      @Override
      public void onConsumerMapReady(@NonNull ConsumerGoogleMap consumerMap) {
        consumerGoogleMap = consumerMap;
        consumerController = consumerMap.getConsumerController();
      }
    },
    this, null);

Kotlin

var consumerGoogleMap: ConsumerGoogleMap
var consumerController: ConsumerController
val consumerMapView = findViewById(R.id.consumer_map_view) as ConsumerMapView

consumerMapView.getConsumerGoogleMapAsync(
  object : ConsumerMapReadyCallback() {
    override fun onConsumerMapReady(consumerMap: ConsumerGoogleMap) {
      consumerGoogleMap = consumerMap
      consumerController = consumerMap.getConsumerController()
    },
    /* fragmentActivity= */ this,
    /* googleMapOptions= */ null,
  }
)

ConsumerGoogleMap

ConsumerGoogleMap ist eine Wrapper-Klasse für die Klasse GoogleMap. Ihre App kann dann über eine API, die GoogleMap entspricht, mit der Karte interagieren. Wenn Sie eine Nutzerkarte verwenden, können Ihre App und Ihr Mitfahrdienst nahtlos mit derselben zugrunde liegenden GoogleMap interagieren. GoogleMap lässt beispielsweise nur eine einzelne Callback-Registrierung zu, ConsumerGoogleMap unterstützt aber doppelt registrierte Callbacks. Über diese Callbacks können deine App und deine Mitfahrgelegenheit Callbacks registrieren, die nacheinander aufgerufen werden.

ConsumerController

ConsumerController bietet Zugriff auf Mitfahrdienste, z. B. um Fahrten zu überwachen, den Fahrtstatus zu steuern und Orte festzulegen.

Teilen der Reise einrichten

Nachdem das Back-End einen Nutzer mit einem Fahrzeug abgeglichen hat, verwenden Sie JourneySharingSession, um die Benutzeroberfläche zur Freigabe des Kaufprozesses zu starten. „Mit der Fahrt teilen“ wird der übereinstimmende Fahrzeugstandort und die zugehörige Route angezeigt. Nachdem Sie das SDK in Ihrer App implementiert haben, können Sie die Funktion zum Überwachen von Fahrten, zum Warten auf Updates und zum Beheben von Fehlern hinzufügen. Bei den folgenden Verfahren wird davon ausgegangen, dass die Back-End-Dienste vorhanden sind und Ihre Dienste zum Abgleichen von Nutzern mit Fahrzeugen betriebsbereit sind.

  1. Registrieren Sie einen Listener für ein TripModel-Objekt, um Details zur Fahrt zu erhalten, z. B. die voraussichtliche Ankunftszeit und die Strecke, die das Fahrzeug vor der Ankunft zurücklegen muss.

    Java

    // Create a TripModel instance for listening to updates to the trip specified by this trip name.
    String tripName = ...;
    TripModelManager tripModelManager = consumerApi.getTripModelManager();
    TripModel tripModel = tripModelManager.getTripModel(tripName);
    
    // Create a JourneySharingSession instance based on the TripModel.
    JourneySharingSession session = JourneySharingSession.createInstance(tripModel);
    
    // Add the JourneySharingSession instance on the map for updating the UI.
    consumerController.showSession(session);
    
    // Register for trip update events.
    tripModel.registerTripCallback(new TripModelCallback() {
      @Override
      public void onTripETAToNextWaypointUpdated(
          TripInfo tripInfo, @Nullable Long timestampMillis) {
        // ...
      }
    
      @Override
      public void onTripActiveRouteRemainingDistanceUpdated(
          TripInfo tripInfo, @Nullable Integer distanceMeters) {
        // ...
      }
    
      // ...
    });
    

    Kotlin

    // Create a TripModel instance for listening to updates to the trip specified by this trip name.
    val tripName = "tripName"
    val tripModelManager = consumerApi.getTripModelManager()
    val tripModel = tripModelManager.getTripModel(tripName)
    
    // Create a JourneySharingSession instance based on the TripModel.
    val session = JourneySharingSession.createInstance(tripModel)
    
    // Add the JourneySharingSession instance on the map for updating the UI.
    consumerController.showSession(session)
    
    // Register for trip update events.
    tripModel.registerTripCallback(
      object : TripModelCallback() {
        override fun onTripETAToNextWaypointUpdated(
          tripInfo: TripInfo,
          timestampMillis: Long?,
        ) {
          // ...
        }
    
        override fun onTripActiveRouteRemainingDistanceUpdated(
          tripInfo: TripInfo,
          distanceMeters: Int?,
        ) {
          // ...
        }
    
      // ...
    })
    
  2. Konfiguriere deine Fahrt mit TripModelOptions.

    Java

    // Set refresh interval to 2 seconds.
    TripModelOptions tripOptions =
        TripModelOptions.builder().setRefreshIntervalMillis(2000).build();
    tripModel.setTripModelOptions(tripOptions);
    

    Kotlin

    // Set refresh interval to 2 seconds.
    val tripOptions = TripModelOptions.builder().setRefreshIntervalMillis(2000).build()
    tripModel.setTripModelOptions(tripOptions)
    

Teilen der Reise beenden

Deaktivieren Sie die Freigabe von Reiseplänen, wenn sie nicht mehr benötigt werden, z. B. wenn die Hostaktivität gelöscht wird. Dadurch werden auch Netzwerkanfragen an Fleet Engine gestoppt und Speicherlecks verhindert.

Der folgende Beispielcode zeigt, wie Sie die Freigabe von Kaufprozessen beenden.

Java

public class MainActivity extends AppCompatActivity
    implements ConsumerViewModel.JourneySharingListener  {

  // Class implementation

  @Override
  protected void onDestroy() {
    super.onDestroy();

    if (journeySharingSession != null) {
      journeySharingSession.stop();
    }
  }
}

Kotlin

class SampleAppActivity : AppCompatActivity(), ConsumerViewModel.JourneySharingListener {

  // Class implementation

  override fun onDestroy() {
    super.onDestroy()

    journeySharingSession?.stop()
  }
}

Fehler bei Fahrten verarbeiten

Die Methode onTripRefreshError zeigt Fehler an, die während der Fahrtüberwachung auftreten. Die Zuordnung von Consumer SDK-Fehlern folgt denselben HTTP/RPC-Richtlinien wie für die Google Cloud Platform. Häufige Fehler, die bei der Fahrtüberwachung auftreten:

HTTP RPC Beschreibung
400 INVALID_ARGUMENT Der Kunde hat einen ungültigen Reisenamen angegeben. Der Name der Fahrt muss das Format providers/{provider_id}/trips/{trip_id} haben. Die provider_id muss die ID des Cloud-Projekts des Dienstanbieters sein.
401 NICHT AUTHENTIFIZIERT Die Anfrage wurde aufgrund eines ungültigen JWT-Tokens nicht authentifiziert. Dieser Fehler tritt auf, wenn das JWT-Token ohne Fahrt-ID signiert wurde oder das JWT-Token abgelaufen ist.
403 PERMISSION_DENIED Der Client hat nicht die erforderliche Berechtigung. Dieser Fehler tritt auf, wenn das JWT-Token ungültig ist, der Client keine Berechtigung hat oder die API nicht für das Clientprojekt aktiviert ist. Möglicherweise fehlt das JWT oder das Token ist mit einer Fahrt-ID signiert, die nicht mit der angeforderten Fahrt-ID übereinstimmt.
429 RESOURCE_EXHAUSTED Das Ressourcenkontingent beträgt null oder die Traffic-Rate überschreitet das Limit.
503 UNAVAILABLE Dienst nicht verfügbar: In der Regel ist der Server ausgefallen.
504 DEADLINE_EXCEEDED Die Frist der Anfrage wurde überschritten. Dies geschieht nur, wenn der Aufrufer eine Frist festlegt, die kürzer als die Standardfrist der Methode ist (d.h. die angeforderte Frist reicht nicht aus, damit der Server die Anfrage verarbeiten kann) und die Anfrage nicht innerhalb der Frist abgeschlossen wurde.

Weitere Informationen findest du unter Fehlerbehandlung beim Consumer SDK.