La soluzione on demand Ride and Deliveres è attualmente disponibile solo per partner selezionati.

Guida introduttiva all'SDK di Drive per Android

Puoi utilizzare l'SDK Driver per fornire monitoraggio e navigazione avanzati alla tua applicazione Trip and Order Progress. L'SDK di Driver fornisce aggiornamenti sulla posizione e sulle attività del veicolo al parco risorse Solution Rides and Deliveries.

L'SDK Driver mantiene i servizi Fleet Engine e i tuoi servizi personalizzati a conoscenza della posizione e dello stato del veicolo. Ad esempio, il veicolo può essere ONLINE o OFFLINE e la posizione del veicolo cambia con il procedere.

Requisiti minimi di sistema

Sul dispositivo mobile deve essere installato Android 5.0 (livello API 21) o versioni successive.

Prerequisiti

Gli SDK Android per i trasporti e la logistica vengono pubblicati in un repository Maven di Artifact Registry. Il repository include i file Project Object Model (.pom) dell'SDK e i documenti Java offline.

Accedi

Se sei un cliente Google Workspace, crea un gruppo Workspace, ad esempio google-maps-platform-sdk-users@workspacedomain.com, durante l'onboarding e fornisci il nome a Google. Questo è l'approccio consigliato. Il tuo gruppo di Workspace verrà quindi aggiunto a una lista consentita che concede l'accesso al repository Maven gmp-artifacts/transportation. Conferma che l'elenco delle email degli utenti e degli account di servizio che richiedono l'accesso sia incluso.

Se la tua organizzazione non può creare gruppi Workspace, invia a Google un elenco di indirizzi email degli account utente e di servizio che devono accedere a questi elementi.

Sviluppo locale

Per lo sviluppo locale, è sufficiente accedere con Cloud SDK.

gcloud

gcloud auth login

L'indirizzo email utilizzato per l'accesso deve essere un membro del gruppo Workspace.

Automazione (sistemi build o integrazione continua)

Configura gli host di automazione in base alle best practice:

  • Se il tuo processo viene eseguito in un ambiente Google Cloud, utilizza il rilevamento automatico delle credenziali.

  • Altrimenti, archivia il file della chiave dell'account di servizio in una posizione sicura nel file system dell'host e imposta la variabile di ambiente GOOGLE_APPLICATION_CREDENTIALS in modo appropriato.

L'indirizzo email dell'account di servizio associato alle credenziali deve essere membro del gruppo Workspace.

Configurazione

Configura Maven o Gradle per rilevare automaticamente le credenziali dell'utente o del servizio.

Gradle

Aggiungi quanto segue al file build.gradle del modulo della tua app, non al file build.gradle del modulo principale del progetto:

  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

Aggiungi il seguente codice al tuo 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>

Per informazioni sulla verifica dell'accesso, consulta Gestione dei pacchetti Java.

Configurazione progetto

Per utilizzare l'SDK Driver, la tua app deve avere come target minSdkVersion 21 o versioni successive.

Per eseguire un'app creata con l'SDK Driver, sul dispositivo Android deve essere installato Google Play Services.

Configura il progetto di sviluppo

Per configurare il progetto di sviluppo e ricevere una chiave API per il progetto in Google Cloud Console:

  1. Creare un nuovo progetto della console Google Cloud o selezionare un progetto esistente da utilizzare con l'SDK Driver. Attendi qualche minuto finché il nuovo progetto non sarà visibile nella console Google Cloud.

  2. Per eseguire l'app demo, il tuo progetto deve avere accesso all'SDK di Maps per Android. In Google Cloud Console, seleziona API e servizi > Libreria, quindi cerca e attiva l'SDK Maps per Android.

  3. Per ottenere una chiave API per il progetto, seleziona API e servizi > Credenziali > Crea credenziali > Chiave API. Per scoprire di più su come ottenere una chiave API, consulta Ottenere una chiave API.

Aggiungi l'SDK Driver alla tua app

L'SDK del driver è disponibile tramite un Repository Maven privato. Il repository include i file Project Object Model (.pom) dell'SDK e i documenti Java. Per aggiungere l'SDK Driver alla tua app:

  1. Configura l'ambiente per accedere al repository Maven dell'host come descritto in Ottenere l'accesso.
  2. Aggiungi la seguente dipendenza alla configurazione Gradle o Maven, sostituendo il segnaposto VERSION_NUMBER con la versione desiderata dell'SDK Driver.

    Gradle

    Aggiungi il seguente codice al tuo build.gradle:

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

    Maven

    Aggiungi il seguente codice al tuo pom.xml:

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

Aggiungi la chiave API alla tua app

Dopo aver aggiunto l'SDK Driver all'app, aggiungi la chiave API alla tua app. Devi utilizzare la chiave API del progetto che hai ottenuto durante la configurazione del progetto di sviluppo.

Questa sezione descrive come archiviare la chiave API in modo che possa essere fatto riferimento in modo più sicuro dall'app. Non dovresti controllare la chiave API nel sistema di controllo della versione. Deve essere archiviato nel file local.properties, che si trova nella directory principale del tuo progetto. Per ulteriori informazioni sul file local.properties, consulta File delle proprietà Gradle.

Per semplificare questa attività, puoi utilizzare il plug-in Secrets Gradle per Android.

Per installare il plug-in e archiviare la chiave API:

  1. Apri il file build.gradle a livello principale e aggiungi il codice seguente all'elemento dependencies in buildscript.

    Trendy

    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. Apri il file build.gradle a livello di app e aggiungi il seguente codice all'elemento plugins.

    Trendy

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

    Kotlin

    id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
    
  3. Se utilizzi Android Studio, sincronizza il progetto con Gradle.

  4. Apri local.properties nella directory a livello di progetto e aggiungi il codice seguente. Sostituisci YOUR_API_KEY con la tua chiave API.

    MAPS_API_KEY=YOUR_API_KEY
    
  5. Nel file AndroidManifest.xml, vai alla pagina com.google.android.geo.API_KEY e aggiorna l'attributo android:value nel seguente modo:

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

L'esempio seguente mostra un manifest completo per un'app di esempio.

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

Includi le attribuzioni richieste nella tua app

Se nella tua app utilizzi l'SDK Driver, devi includere il testo di attribuzione e le licenze open source nella sezione delle note legali della tua app. È meglio includere le attribuzioni come voce di menu indipendente o come parte di una voce di menu Informazioni.

Puoi trovare il testo di attribuzione richiesto e le licenze open source nel file ZIP dell'SDK Driver:

  • NOTICE.txt
  • LICENSES.txt

Dipendenze

Se utilizzi ProGuard per ottimizzare le build, potrebbe essere necessario aggiungere le seguenti righe al file di configurazione di ProGuard:

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

Il livello minimo di API supportato è 21.

Inizializzazione dell'SDK

Per inizializzare l'oggetto DriverContext è necessario un ID provider (di solito l'ID progetto Google Cloud). Per ulteriori dettagli sulla configurazione del progetto Google Cloud, consulta Autenticazione e autorizzazione.

Prima di utilizzare l'SDK Driver, devi inizializzare l'SDK per la navigazione. Per inizializzare l'SDK:

  1. Ottieni un oggetto Navigator da 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. Crea un oggetto DriverContext, compilando i campi obbligatori.

    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. Utilizza l'oggetto DriverContext per inizializzare *DriverApi.

    Java

    RidesharingDriverApi ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext);
    

    Kotlin

    val ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext)
    
  4. Recupera RidesharingVehicleReporter dall'oggetto API. (*VehicleReporter estende NavigationVehicleReporter).

    Java

    RidesharingVehicleReporter vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter();
    

    Kotlin

    val vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter()
    

Autenticazione con AuthTokenFactory

Quando l'SDK Driver genera aggiornamenti della posizione, deve inviarli al server Fleet Engine. Per autenticare queste richieste, l'SDK Driver richiama un'istanza fornita dal chiamante di AuthTokenFactory. La fabbrica è responsabile della generazione dei token di autenticazione al momento dell'aggiornamento della posizione.

Il modo esatto in cui vengono generati i token sarà specifico per la situazione di ogni sviluppatore. Tuttavia, l'implementazione dovrà probabilmente:

  • Recupera un token di autenticazione, probabilmente in formato JSON, da un server HTTPS
  • Analizzare e memorizzare nella cache il token
  • aggiorna il token alla scadenza

Per informazioni dettagliate sui token previsti dal server Fleet Engine, consulta Creazione di un token web JSON (JWT) per l'autorizzazione.

Ecco un'implementazione di uno scheletro di un 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)
    }
  }
}

Questa particolare implementazione utilizza il client HTTP Java integrato per recuperare un token in formato JSON dal server di autenticazione dello sviluppatore. Il token viene salvato per il riutilizzo. Il token viene recuperato di nuovo se entro 10 minuti dalla scadenza.

L'implementazione può eseguire operazioni diverse, ad esempio utilizzare un thread in background per aggiornare i token.

Le eccezioni in AuthTokenFactory verranno trattate come temporanee, a meno che si verifichino ripetutamente. Dopo diversi tentativi, l'SDK Driver presumerà che l'errore sia definitivo e smetterà di provare a inviare aggiornamenti.

Stato ed errori con StatusListener

Poiché l'SDK Driver esegue azioni in background, utilizza StatusListener per attivare le notifiche quando si verificano determinati eventi, ad esempio errori, avvisi o messaggi di debug. Gli errori possono essere di natura temporanea (come BACKEND_CONNECTIVITY_ERROR) oppure possono causare l'interruzione definitiva degli aggiornamenti di posizione (ad esempio VEHICLE_NOT_FOUND, che indica un errore di configurazione).

Puoi fornire un'implementazione StatusListener facoltativa come la seguente:

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

Note su SSL/TLS

Internamente, l'implementazione dell'SDK Driver utilizza SSL/TLS per comunicare in modo sicuro con il server Fleet Engine. Le versioni precedenti di Android (versioni API 19 o precedenti) potrebbero richiedere una patch SecurityProvider per poter comunicare con il server. Consulta questo articolo per ulteriori informazioni sull'utilizzo di SSL in Android. L'articolo contiene anche esempi di codice per l'applicazione di patch al provider di sicurezza.

Attivazione degli aggiornamenti di posizione

Quando hai un'istanza *VehicleReporter, l'attivazione degli aggiornamenti della posizione è semplice:

Java

RidesharingVehicleReporter reporter = ...;

reporter.enableLocationTracking();

Kotlin

val reporter = ...

reporter.enableLocationTracking()

Gli aggiornamenti della posizione vengono inviati a intervalli regolari quando lo stato del veicolo è ONLINE. Tieni presente che quando chiami reporter.enableLocationTracking(), lo stato del veicolo non viene impostato automaticamente su ONLINE. Devi impostare lo stato del veicolo in modo esplicito.

Per impostazione predefinita, l'intervallo per i report è di 10 secondi. L'intervallo del report può essere modificato con reporter.setLocationReportingInterval(long, TimeUnit). L'intervallo minimo di aggiornamento supportato è 5 secondi. Aggiornamenti più frequenti potrebbero comportare una riduzione delle richieste e degli errori.

Disattivazione degli aggiornamenti di posizione

Al termine del turno del conducente, gli aggiornamenti sulla posizione possono essere interrotti e il veicolo contrassegnato offline può chiamare DeliveryVehicleReporter.disableLocationTracking o RidesharingVehicleReporter.disableLocationTracking.

Questa chiamata causerà la pianificazione della consegna immediata di un aggiornamento finale, che indica che il veicolo è offline. Questo aggiornamento non conterrà la località dell'utente.

Impostare lo stato del veicolo

Se attivi gli aggiornamenti della posizione, impostando lo stato del veicolo su ONLINE il veicolo verrà reso disponibile per SearchVehicles query; in modo simile, se contrassegni un veicolo come OFFLINE, il veicolo verrà contrassegnato come non disponibile.

Puoi impostare lo stato del veicolo sul lato server (vedi Aggiornare un veicolo) o direttamente nell'SDK Driver:

Java

RidesharingVehicleReporter reporter = ...;

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

Kotlin

val reporter = ...

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

Quando gli aggiornamenti della posizione sono attivi, una chiamata al numero setVehicleState verrà propagata al successivo aggiornamento della posizione.

Se contrassegni un veicolo come ONLINE quando il monitoraggio della posizione non è attivo, verrà generato un IllegalStateException. Un veicolo può essere contrassegnato come OFFLINE quando il monitoraggio della posizione non è ancora abilitato o disabilitato esplicitamente. Questo comporterà un aggiornamento immediato. Una chiamata al numero RidesharingVehicleReporter.disableLocationTracking() imposterà lo stato del veicolo su OFFLINE.

Tieni presente che setVehicleState restituisce immediatamente l'invito e gli aggiornamenti vengono effettuati sul thread di aggiornamento della località. Analogamente alla gestione degli errori degli aggiornamenti delle posizioni, gli errori durante l'aggiornamento dello stato del veicolo vengono propagati utilizzando il valore StatusListener fornito facoltativamente impostato in DriverContext.