Rozwiązanie na żądanie dotyczące przejazdów i dostaw jest obecnie dostępne tylko dla wybranych partnerów.

Pierwsze kroki z pakietem SDK Driver na Androida

Za pomocą pakietu SDK Driver możesz usprawnić nawigację i śledzenie postępów w aplikacji Podróże i zamówienia. Pakiet Driver SDK zapewnia aktualne informacje o lokalizacji i zadaniach floty silnikówje i dostarcza rozwiązanie na żądanie.

SDK Driver sprawi, że usługi Fleet Engine i usługi niestandardowe będą znać lokalizację i stan pojazdu. Na przykład pojazd może mieć wartość ONLINE lub OFFLINE, a jego lokalizacja zmienia się w miarę postępów podróży.

Minimalne wymagania systemowe

Na urządzeniu mobilnym musi być zainstalowany Android 5.0 (poziom API 21) lub nowszy.

Wymagania wstępne

Pakiety SDK Transportu i Logistyki na Androida są publikowane w repozytorium Artifact Registry Maven. Repozytorium obejmuje pliki Project Object Model (.pom) pakietu SDK i pliki Java w trybie offline.

Uzyskaj dostęp

Jeśli korzystasz z Google Workspace, utwórz grupę Workspace, na przykład google-maps-platform-sdk-users@workspacedomain.com, podczas rejestracji i podaj jej nazwę Google. Jest to zalecane. Twoja grupa Workspace zostanie dodana do listy dozwolonych, która przyznaje dostęp do repozytorium Maven gmp-artifacts/transportation. Sprawdź, czy na liście znajdują się adresy e-mail użytkowników i konta usługi, które muszą mieć dostęp.

Jeśli Twoja organizacja nie może tworzyć grup Workspace, wyślij do Google listę adresów e-mail użytkowników i kont usługi, które potrzebują dostępu do tych artefaktów.

Programowanie lokalne

W przypadku programowania lokalnego wystarczy zalogować się za pomocą pakietu SDK Cloud.

gcloud

gcloud auth login

Adres e-mail używany do logowania musi należeć do grupy Workspace.

Automatyzacja (systemy kompilacji lub tryb ciągłej integracji)

Skonfiguruj hosty automatyzacji zgodnie ze sprawdzonymi metodami:

  • Jeśli proces działa w środowisku Google Cloud, skorzystaj z automatycznego wykrywania danych logowania.

  • W przeciwnym razie zapisz plik klucza konta usługi w bezpiecznej lokalizacji w systemie plików hosta i ustaw odpowiednio zmienną środowiskową GOOGLE_APPLICATION_CREDENTIALS.

Adres e-mail konta usługi powiązany z danymi logowania musi być członkiem grupy Workspace.

Konfiguracja

Skonfiguruj Maven lub Gradle, aby automatycznie wykrywać dane logowania użytkowników lub usług.

Gradle

Dodaj do pliku build.gradle modułu aplikacji ten kod, a nie plik build.gradle modułu głównego projektu:

  plugins {
    id "com.google.cloud.artifactregistry.gradle-plugin" version "2.1.5"
  }
  repositories {
    maven {
      url "artifactregistry://us-west2-maven.pkg.dev/gmp-artifacts/transportation"
    }
  }

Maven

Dodaj do pom.xml:

  <repositories>
    <repository>
      <id>gmp-artifacts</id>
      <url>artifactregistry://us-west2-maven.pkg.dev/gmp-artifacts/transportation</url>
      <releases>
        <enabled>true</enabled>
      </releases>
    </repository>
  </repositories>
  <build>
    <extensions>
      <extension>
        <groupId>com.google.cloud.artifactregistry</groupId>
        <artifactId>artifactregistry-maven-wagon</artifactId>
        <version>2.1.0</version>
      </extension>
    </extensions>
  </build>

Więcej informacji o weryfikowaniu dostępu znajdziesz w artykule Zarządzanie pakietami Java.

Konfiguracja projektu

Aby korzystać z pakietu SDK Driver, Twoja aplikacja musi być kierowana na minSdkVersion w wersji 21 lub nowszej.

Aby uruchomić aplikację stworzoną za pomocą pakietu SDK Driver, na urządzeniu z Androidem muszą być zainstalowane Usługi Google Play.

Konfigurowanie projektu programistycznego

Aby skonfigurować projekt deweloperski i uzyskać klucz interfejsu API dla projektu w Google Cloud Console:

  1. Utwórz nowy projekt Google Cloud Console lub wybierz istniejący, który będzie używany z pakietem SDK Driver. Zaczekaj kilka minut, aż nowy projekt pojawi się w konsoli Google Cloud.

  2. Aby uruchomić aplikację w wersji demonstracyjnej, Twój projekt musi mieć dostęp do pakietu SDK Maps na Androida. W konsoli Google Cloud wybierz Interfejsy API i usługi > Biblioteka, a potem wyszukaj i włącz pakiet SDK Map na Androida.

  3. Aby uzyskać klucz interfejsu API projektu, wybierz Interfejsy API i usługi > Dane logowania > Utwórz dane logowania > Klucz interfejsu API. Więcej informacji o uzyskiwaniu klucza interfejsu API znajdziesz w artykule Pobieranie klucza interfejsu API.

Dodaj do aplikacji pakiet SDK Driver

Pakiet SDK Driver jest dostępny w prywatnym repozytorium Maven. Repozytorium zawiera pliki Project Object Model (.pom) pakietu SDK i pliki Javadocs. Aby dodać pakiet SDK Driver do aplikacji:

  1. Skonfiguruj środowisko, aby uzyskać dostęp do repozytorium Maven w sposób opisany w sekcji Uzyskiwanie dostępu.
  2. Dodaj zależność do konfiguracji Gradle lub Maven, zastępując zmienną VERSION_NUMBER odpowiednią wersją pakietu SDK sterownika.

    Gradle

    Dodaj do build.gradle:

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

    Maven

    Dodaj do pom.xml:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.mapsplatform.transportation</groupId>
        <artifactId>transportation-driver</artifactId>
        <version>VERSION_NUMBER</version>
      </dependency>
    </dependencies>
    

Dodawanie klucza interfejsu API do aplikacji

Po dodaniu pakietu SDK sterownika do aplikacji dodaj do niej klucz interfejsu API. Musisz użyć klucza interfejsu API projektu uzyskanego podczas konfigurowania projektu programistycznego.

W tej sekcji opisano, jak przechowywać klucz interfejsu API, tak by można było bezpieczniej odwoływać się do niego w aplikacji. Nie należy sprawdzać klucza interfejsu API w systemie kontroli wersji. Powinien być zapisany w pliku local.properties, który znajduje się w katalogu głównym projektu. Więcej informacji o pliku local.properties znajdziesz w artykule Pliki właściwości Gradle.

Aby uprościć to zadanie, możesz użyć wtyczki Gradle obiektów tajnych na Androida.

Aby zainstalować wtyczkę i zapisać klucz interfejsu API:

  1. Otwórz plik build.gradle na poziomie katalogu głównego i dodaj ten kod do elementu dependencies w sekcji buildscript.

    Zakręcony

    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. Otwórz plik build.gradle na poziomie aplikacji i dodaj do elementu plugins ten kod.

    Zakręcony

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

    Kotlin

    id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
    
  3. Jeśli używasz Android Studio, zsynchronizuj projekt z Gradle.

  4. Otwórz local.properties w katalogu na poziomie projektu i dodaj ten kod. Zastąp YOUR_API_KEY swoim kluczem interfejsu API.

    MAPS_API_KEY=YOUR_API_KEY
    
  5. W pliku AndroidManifest.xml przejdź do com.google.android.geo.API_KEY i zaktualizuj atrybut android:value w następujący sposób:

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

Poniższy przykład zawiera pełny plik manifestu przykładowej aplikacji:

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

Uwzględnij wymagane atrybucje w aplikacji

Jeśli używasz w aplikacji pakietu SDK Dysku Google, w sekcji informacji prawnych o aplikacji musisz uwzględnić tekst atrybucji i licencje open source. Atrybucja powinna znajdować się jako niezależna pozycja w menu lub jako część menu.

Wymagany tekst atrybucji i licencje open source znajdziesz w pliku ZIP z pakietem SDK Driver:

  • NOTICE.txt
  • LICENSES.txt

Zależności

Jeśli optymalizujesz kompilacje za pomocą ProGuard, może być konieczne dodanie do pliku konfiguracji ProGuard tych wierszy:

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

Minimalny obsługiwany poziom interfejsu API to 21.

Inicjowanie pakietu SDK

Do zainicjowania obiektu DriverContext wymagany jest identyfikator dostawcy (zwykle identyfikator projektu Google Cloud). Więcej informacji o konfigurowaniu projektu Google Cloud znajdziesz w artykule Uwierzytelnianie i autoryzacja.

Zanim zaczniesz korzystać z pakietu SDK Driver, musisz najpierw zainicjować pakiet SDK Nawigacji. Aby zainicjować pakiet SDK:

  1. Uzyskaj obiekt Navigator z NavigationApi.

    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. Utwórz obiekt DriverContext, wypełniając wymagane pola.

    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. Użyj obiektu DriverContext, aby zainicjować plik *DriverApi.

    Java

    RidesharingDriverApi ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext);
    

    Kotlin

    val ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext)
    
  4. Uzyskaj RidesharingVehicleReporter z obiektu API. (*VehicleReporter obejmuje rozszerzenie NavigationVehicleReporter).

    Java

    RidesharingVehicleReporter vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter();
    

    Kotlin

    val vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter()
    

Uwierzytelnianie w AuthTokenFactory

Gdy pakiet SDK kierowcy generuje aktualizacje lokalizacji, musi je wysyłać do serwera Fleet Engine. Aby uwierzytelnić te żądania, pakiet SDK kierowcy wywoła wywołanie API zawierające element wywołujący element AuthTokenFactory. Fabryka odpowiada za generowanie tokenów uwierzytelniania w czasie aktualizowania lokalizacji.

Sposób generowania tokenów zależy od sytuacji danego dewelopera. Wdrożenie prawdopodobnie będzie jednak wymagać:

  • pobieranie tokena uwierzytelniania, prawdopodobnie w formacie JSON, z serwera HTTPS
  • analiza i buforowanie tokena
  • odśwież token po wygaśnięciu

Szczegółowe informacje o tokenach oczekiwanych przez serwer Fleet Engine znajdziesz w artykule Tworzenie tokena internetowego JSON (JWT) do autoryzacji.

Oto szkielet implementacji obiektu 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)
    }
  }
}

W tej konkretnej implementacji pobierany jest token w formacie JSON z wbudowanego klienta HTTP Java z serwera uwierzytelniania programisty. Token został zapisany do ponownego użycia. Token zostanie ponownie pobrany, jeśli do wygaśnięcia dojdzie w ciągu 10 minut.

Implementacja może wyglądać inaczej, na przykład użyć wątku w tle, aby odświeżyć tokeny.

Wyjątki w AuthTokenFactory będą traktowane jako przejściowe, chyba że się to powtarzają. Po kilku próbach pakiet SDK kierowcy uzna, że błąd jest trwały, i przestanie wysyłać aktualizacje.

Raportowanie stanu i błędów w StatusListener

Ponieważ pakiet SDK sterownika wykonuje działania w tle, StatusListener umożliwia wywoływanie powiadomień o wystąpieniach niektórych zdarzeń, takich jak błędy, ostrzeżenia czy komunikaty debugowania. Błędy mogą mieć charakter tymczasowy (np. BACKEND_CONNECTIVITY_ERROR) albo powodować trwałe zatrzymywanie aktualizacji lokalizacji (np. VEHICLE_NOT_FOUND, co wskazuje na błąd konfiguracji).

Opcjonujesz opcjonalną implementację StatusListener w ten sposób:

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

Uwagi dotyczące SSL/TLS

Wewnętrzna implementacja pakietu Driver SDK używa SSL/TLS do bezpiecznej komunikacji z serwerem Fleet Engine. Starsze wersje Androida (interfejs API w wersji 19 lub starszej) mogą wymagać zainstalowania poprawki SecurityProvider na potrzeby komunikacji z serwerem. Więcej informacji o korzystaniu z protokołu SSL w Androidzie znajdziesz w tym artykule. Artykuł zawiera też przykładowe fragmenty kodu do zastosowania poprawki dostawcy zabezpieczeń.

Włączam aktualizacje lokalizacji

Gdy masz instancję *VehicleReporter, włączenie aktualizacji lokalizacji jest następujące:

Java

RidesharingVehicleReporter reporter = ...;

reporter.enableLocationTracking();

Kotlin

val reporter = ...

reporter.enableLocationTracking()

Informacje o lokalizacji są wysyłane w regularnych odstępach, gdy stan pojazdu to ONLINE. Pamiętaj, że wywołanie reporter.enableLocationTracking() nie ustawia automatycznie stanu pojazdu na ONLINE. Musisz ustawić stan pojazdu.

Domyślnie interwał raportowania wynosi 10 sekund. Interwał raportowania można zmienić za pomocą reporter.setLocationReportingInterval(long, TimeUnit). Minimalny odstęp czasu aktualizacji wynosi 5 sekund. Częstsze aktualizacje mogą skutkować wolniejszymi żądaniami i błędami.

Wyłączanie aktualizacji lokalizacji

Po zakończeniu zmiany kierowcy można wyłączyć aktualizacje lokalizacji, a pojazd jest oznaczony jako offline przez wywołanie DeliveryVehicleReporter.disableLocationTracking lub RidesharingVehicleReporter.disableLocationTracking.

To wywołanie spowoduje zaplanowanie natychmiastowej ostatniej aktualizacji, która wskazuje, że pojazd jest offline. Ta aktualizacja nie będzie zawierać lokalizacji użytkownika.

Ustawianie stanu pojazdu

Po włączeniu aktualizacji lokalizacji ustawienie pojazdu na ONLINE spowoduje udostępnienie pojazdu w zapytaniach SearchVehicles. Analogicznie oznaczenie pojazdu jako OFFLINE spowoduje oznaczenie go jako niedostępnego.

Stan pojazdu możesz ustawić po stronie serwera (patrz Aktualizacja pojazdu) lub bezpośrednio w pakiecie SDK kierowcy:

Java

RidesharingVehicleReporter reporter = ...;

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

Kotlin

val reporter = ...

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

Gdy aktualizacje lokalizacji są włączone, przy następnej aktualizacji lokalizacji zostanie wywołane wywołanie setVehicleState.

Jeśli nie włączysz śledzenia lokalizacji, oznaczenie pojazdu jako ONLINE spowoduje IllegalStateException. Jeśli nie masz włączonego lub wyraźnie wyłączonego śledzenia lokalizacji, pojazd może być oznaczony jako OFFLINE. Spowoduje to natychmiastową aktualizację. Wywołanie RidesharingVehicleReporter.disableLocationTracking() spowoduje ustawienie stanu pojazdu na OFFLINE.

Zwróć uwagę, że wartość setVehicleState zwraca się natychmiast, a aktualizacje są przeprowadzane w wątku aktualizacji lokalizacji. Podobnie jak w przypadku obsługi błędów w aktualizacjach lokalizacji błędy aktualizacji stanu pojazdu są rozpowszechniane za pomocą opcjonalnej wartości StatusListener ustawionej w polu DriverContext.