Introduzione all'SDK Consumer per Android

Puoi utilizzare l'SDK consumer per creare ed eseguire un'app consumer di base integrata con i servizi di backend On-demand Rides and Deliveries Solution. Puoi creare un'app di avanzamento dei viaggi e degli ordini che può visualizzare una corsa attiva, rispondere agli aggiornamenti della corsa e gestire gli errori.

Poiché l'SDK consumer ha un'architettura modulare, puoi utilizzare le parti dell'API che vuoi utilizzare per la tua app specifica e integrarle con le tue API, i servizi di backend forniti da Fleet Engine e API aggiuntive di Google Maps Platform.

Requisiti minimi di sistema

Sul dispositivo mobile deve essere installato Android 6.0 (livello API 23) o versioni successive.

Configurazione della build e delle dipendenze

Le versioni dell'SDK consumer 1.99.0 e successive sono disponibili utilizzando il repository Google Maven. Il canale del repository privato utilizzato in precedenza è stato ritirato.

Gradle

Aggiungi quanto segue al tuo file build.gradle:

repositories {
    ...
    google()
}

Maven

Aggiungi quanto segue al tuo file pom.xml:

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

Configurazione progetto

Per utilizzare l'SDK consumer per Android, la tua app deve avere come target minSdkVersion 23 o versioni successive.

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

Configura il progetto di sviluppo

Per configurare il progetto di sviluppo e ottenere una chiave API per il progetto nella console Google Cloud:

  1. Crea un nuovo progetto della console Google Cloud o selezionane uno esistente da utilizzare con l'SDK consumer. Attendi qualche minuto finché il nuovo progetto non è visibile nella console Google Cloud.

  2. Per eseguire l'app demo, il progetto deve avere accesso a Maps SDK per Android. Nella console Google Cloud, seleziona API e servizi > Libreria, poi cerca e attiva Maps SDK per Android.

  3. Ottieni una chiave API per il progetto selezionando API e servizi > Credenziali > Crea credenziali > Chiave API. Per ulteriori informazioni su come ottenere una chiave API, consulta Ottenere una chiave API.

Aggiungi l'SDK consumer alla tua app

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

  1. Configura il tuo ambiente per accedere al repository Maven host come descritto nella sezione precedente.

    Se hai dichiarato una configurazione per la gestione delle dipendenze centralizzata in settings.gradle, disabilitala come segue.

    • Rimuovi il seguente blocco di codice in settings.gradle:

      import org.gradle.api.initialization.resolve.RepositoriesMode
      dependencyResolutionManagement {
          repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
          repositories {
              google()
              mavenCentral()
          }
      }
      
  2. Aggiungi la seguente dipendenza alla configurazione Gradle o Maven, sostituendo il segnaposto VERSION_NUMBER con la versione desiderata dell'SDK consumer.

    Gradle

    Aggiungi il seguente codice a build.gradle:

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

    Maven

    Aggiungi il seguente codice a pom.xml:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.mapsplatform.transportation</groupId>
        <artifactId>transportation-consumer</artifactId>
        <version>VERSION_NUMBER</version>
      </dependency>
    </dependencies>
    
  3. L'SDK consumer dipende dall'SDK Maps. Questa dipendenza è configurata in modo tale che se la versione dell'SDK Maps non è esplicitamente definita nel file di configurazione della build come la seguente, quando viene rilasciata una nuova versione dell'SDK Maps, l'SDK consumer continua a utilizzare la versione minima supportata dell'SDK Maps richiesta.

    Gradle

    Aggiungi il seguente codice a build.gradle:

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

    Maven

    Aggiungi il seguente codice a pom.xml:

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

Aggiungi la chiave API all'app

Dopo aver aggiunto l'SDK consumer all'app, aggiungi la chiave API all'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 l'app possa fare riferimento in modo più sicuro. Non devi controllare la chiave API nel sistema di controllo della versione. Dovrebbe essere archiviato nel file local.properties, che si trova nella directory radice del progetto. Per ulteriori informazioni sul file local.properties, consulta la pagina relativa ai file delle proprietà di Gradle.

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

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

  1. Apri il file build.gradle a livello di directory principale e aggiungi il seguente codice 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 usi Android Studio, sincronizza il progetto con Gradle.

  4. Apri local.properties nella directory a livello di progetto, quindi 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 a com.google.android.geo.API_KEY e aggiorna l'attributo android:value come segue:

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

Includi le attribuzioni richieste nella tua app

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

Le informazioni sulle licenze sono disponibili nel file "third_party_licenses.txt" del file AAR non archiviato.

Per informazioni su come includere notifiche open source, consulta la pagina https://developers.google.com/android/guides/opensource.

Autenticazione SDK consumer

L'SDK consumer fornisce l'autenticazione mediante token web JSON. Un token JWT (JSON Web Token) è un token di accesso basato su JSON che fornisce una o più attestazioni su un servizio. Ad esempio, un server potrebbe generare un token con la dichiarazione "registrata come amministratore" e fornirla a un client. Il client potrebbe quindi utilizzare quel token per dimostrare di aver eseguito l'accesso come amministratore.

L'SDK consumer utilizza il token web JSON fornito dall'applicazione per comunicare con Fleet Engine. Per ulteriori informazioni, consulta Autenticazione e autorizzazione di Fleet Engine.

Il token di autorizzazione deve includere un'attestazione tripid:TRIP_ID nell'intestazione authorization del token, dove TRIP_ID è l'ID viaggio. In questo modo, l'SDK per consumatori può accedere ai dettagli della corsa, tra cui la posizione del veicolo, il percorso e l'orario di arrivo stimato.

Callback di token web JSON

L'SDK consumer registra un callback del token di autorizzazione con l'applicazione durante l'inizializzazione. L'SDK chiama l'applicazione per ottenere un token per tutte le richieste di rete che richiedono l'autorizzazione.

Ti consigliamo vivamente di memorizzare i token di autorizzazione nella cache dell'implementazione del callback e di aggiornarli solo una volta trascorso il tempo expiry. I token devono essere emessi con una scadenza di un'ora.

Il callback del token di autorizzazione specifica quale token di servizio è necessario per il servizio TripService. Fornisce anche il valore tripId richiesto per il contesto.

Il seguente esempio di codice mostra come implementare un callback di token di autorizzazione.

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

Inizializzare l'API

Prima di seguire queste procedure, si presume che tu abbia abilitato i servizi appropriati e l'SDK consumer.

Ottieni l'istanza ConsumerApi

Per utilizzare l'SDK consumer, la tua app deve inizializzare ConsumerApi in modo asincrono. L'API è un singleton. Il metodo di inizializzazione prevede un valore AuthTokenFactory. La fabbrica genera nuovi token JWT per l'utente quando necessario.

providerId è l'ID progetto del tuo progetto Google Cloud. Consulta la guida dell'utente di Fleet Engine per ulteriori informazioni sulla creazione del progetto.

La tua app deve implementare AuthTokenFactory come descritto in Autenticazione SDK consumer.

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
}

SDK Maps e renderer di Maps

L'SDK consumer v2.x.x supporta l'SDK Maps per Android 18.1.0 e versioni successive. La tabella riportata di seguito riassume il renderer predefinito in base alla versione di Maps SDK e la supportabilità di entrambi i renderer. Ti consigliamo, tuttavia, di utilizzare il renderer più recente. Se devi utilizzare il renderer precedente, puoi specificarlo esplicitamente tramite MapsInitializer.initialize().

Versione SDK Maps Supporta il renderer più recente Supporta il renderer precedente Renderer predefinito
V18.1.0 e precedenti Precedente*
V18.2.0 Più recenti

* Con il lancio del nuovo renderer di Maps, il renderer più recente sarà predefinito.

Aggiungi Maps SDK come dipendenza

Gradle

Aggiungi il seguente codice a build.gradle:

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

Maven

Aggiungi il seguente codice a pom.xml:

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

Inizializza Maps SDK prima di inizializzare l'SDK consumer

Nella classe Application o Activity all'avvio, chiama MapsInitializer.initialize() e attendi il risultato della richiesta del renderer prima di inizializzare l'SDK Consumer.

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

Crea l'interfaccia utente

Puoi utilizzare ConsumerMapFragment o ConsumerMapView per creare l'interfaccia utente per la tua applicazione. ConsumerMapFragment ti consente di definire la tua mappa utilizzando un Fragment, mentre ConsumerMapView ti consente di utilizzare un View. La funzionalità di ride sharing è la stessa per ConsumerMapView e ConsumerMapFragment, quindi puoi sceglierne una a seconda che sia più adatta alla tua applicazione: View o Fragment.

Aggiunta del supporto per i drawable API 19 (KitKat) e Vector

Se la progettazione della tua app richiede il supporto per dispositivi API 19 (KitKat) e drawable vettoriali, aggiungi il seguente codice alla tua Attività. Questo codice estende AppCompatActivity all'utilizzo dei drawables vettoriali in Consumer SDK.

Java

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

// ...

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

Kotlin

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

// ...

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

Aggiungere la vista o il frammento della mappa

Puoi creare la mappa per visualizzare la condivisione del percorso in un frammento Android o in una vista, che definisci nel file XML del layout dell'applicazione (situato in /res/layout). Il frammento (o vista) fornisce quindi l'accesso alla mappa di condivisione del percorso, che la tua app può accedere e modificare. La mappa fornisce anche un handle all'ConsumerController, che consente alla tua app di controllare e personalizzare l'esperienza di condivisione del percorso.

Mappa del percorso di condivisione e controller

Puoi definire la mappa di condivisione del percorso come un frammento (utilizzando ConsumerMapFragment) o come una vista (utilizzando ConsumerMapView), come mostrato nel seguente codice di esempio. Il tuo metodo onCreate() deve quindi chiamare getConsumerGoogleMapAsync(callback), che restituisce il ConsumerGoogleMap in modo asincrono nel callback. Puoi quindi utilizzare ConsumerGoogleMap per visualizzare la condivisione del percorso, che può essere aggiornato in base alle esigenze dell'app.

ConsumerMapFragment

Sei tu a definire il frammento nel file XML di layout dell'applicazione, come mostrato nel seguente esempio di codice.

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

La chiamata a getConsumerGoogleMapAsync() deve provenire dal metodo onCreate().

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

La visualizzazione può essere utilizzata in un frammento o in un'attività, come definito nel file XML.

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

La chiamata a getConsumerGoogleMapAsync() deve provenire da onCreate(). Oltre al parametro di callback, richiede l'attività o il frammento contenenti e GoogleMapOptions (che può essere null), contenente gli attributi di configurazione per MapView. La classe base dell'attività o del frammento deve essere rispettivamente FragmentActivity o Fragment di assistenza, poiché forniscono accesso al suo ciclo di vita.

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

Un MapView in un frammento è uguale all'esempio precedente per MapView in un'attività, ad eccezione del fatto che il frammento gonfia il layout che include MapView nel metodo onCreateView() del frammento.

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

Regolare lo zoom della fotocamera per mettere a fuoco un percorso

Il pulsante La mia posizione predefinito integrato in Maps SDK centra la fotocamera sulla posizione del dispositivo.

Se è attiva una sessione di condivisione del percorso, ti consigliamo di centrare la fotocamera per concentrarti sul viaggio anziché sulla posizione del dispositivo.

Soluzione integrata SDK consumer per Android: fotocamera automatica

Per consentirti di concentrarti sul percorso anziché sulla posizione del dispositivo, l'SDK consumer offre una funzionalità Fotocamera automatica che è attivata per impostazione predefinita. La fotocamera esegue lo zoom per mettere a fuoco il percorso condiviso e la tappa successiva del viaggio.

AutoCamera

Personalizzazione del comportamento della videocamera

Se vuoi avere un maggiore controllo sul comportamento della videocamera, puoi disattivare o attivare la fotocamera automatica utilizzando ConsumerController.setAutoCameraEnabled().

ConsumerController.getCameraUpdate() restituisce i limiti della fotocamera consigliati in quel momento. Puoi quindi fornire questo CameraUpdate come argomento a GoogleMap.moveCamera() o GoogleMap.animateCamera().

Accedere al ridesharing e alle mappe

Per supportare il ridesharing e l'interazione con la mappa nella tua applicazione, devi avere accesso a ConsumerGoogleMap e ConsumerController. ConsumerMapFragment e ConsumerMapView restituiscono entrambi in modo asincrono ConsumerGoogleMap in ConsumerMapReadyCallback. ConsumerGoogleMap restituisce ConsumerController da getConsumerController(). Puoi accedere a ConsumerGoogleMap e ConsumerController nel seguente modo.

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 è una classe wrapper per la classe GoogleMap. Consente alla tua app di interagire con la mappa utilizzando un'API equivalente a GoogleMap. L'uso della mappa per i consumatori consente alla tua app e al ridesharing di interagire senza soluzione di continuità con la stessa mappa di base di Google Maps. Ad esempio, GoogleMap consente una sola registrazione di callback, ma ConsumerGoogleMap supporta i callback con doppia registrazione. Questi callback consentono alla tua app e alla tua ride sharing di registrare i callback che vengono chiamati in sequenza.

ConsumerController

ConsumerController offre accesso a funzionalità di ride sharing, ad esempio monitoraggio delle corse, controllo dello stato delle corse e impostazione delle posizioni.

Configura la condivisione del percorso

Dopo che il backend ha abbinato un consumatore a un veicolo, utilizza JourneySharingSession per iniziare l'interfaccia utente di condivisione del percorso. La condivisione del percorso mostra la posizione e il percorso del veicolo corrispondenti. Dopo aver implementato l'SDK nella tua app, puoi aggiungere la funzionalità per monitorare le corse, ascoltare gli aggiornamenti e gestire gli errori. Le seguenti procedure presuppongono che i servizi di backend siano in uso e che i servizi per l'abbinamento dei consumatori ai veicoli siano operativi.

  1. Registra un listener su un oggetto TripModel per ottenere dettagli sulla corsa, come l'orario di arrivo stimato (orario di arrivo stimato) e la distanza che il veicolo deve percorrere prima dell'arrivo.

    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. Configura il tuo viaggio utilizzando 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)
    

Interrompi condivisione percorso

Assicurati di interrompere la condivisione del percorso quando non è più necessaria, ad esempio quando l'attività host viene eliminata. L'interruzione della condivisione del percorso arresta anche le richieste di rete a Fleet Engine e impedisce le perdite di memoria.

Il codice di esempio seguente mostra come interrompere la condivisione del percorso.

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

Gestire gli errori di blocco

Il metodo onTripRefreshError restituisce gli errori che si verificano durante il monitoraggio delle corse. La mappatura degli errori dell'SDK consumer segue le stesse linee guida HTTP/RPC stabilite per la piattaforma Google Cloud. Gli errori comuni che emergono durante il monitoraggio della corsa includono i seguenti:

HTTP RPC Descrizione
400 INVALID_ARGUMENT Il client ha specificato un nome percorso non valido. Il nome della corsa deve essere nel formato providers/{provider_id}/trips/{trip_id}. provider_id deve essere l'ID del progetto Cloud di proprietà del fornitore di servizi.
401 NON AUTENTICATO Richiesta non autenticata a causa di un token JWT non valido. Questo errore si verifica se il token JWT è firmato senza ID trip o se il token JWT è scaduto.
403 PERMISSION_DENIED Il client non dispone di autorizzazioni sufficienti. Questo errore si verifica se il token JWT non è valido, se il client non dispone dell'autorizzazione o se l'API non è abilitata per il progetto client. Il token JWT potrebbe mancare o il token è firmato con un ID trip che non corrisponde all'ID di corsa richiesto.
429 RESOURCE_EXHAUSTED La quota di risorse è pari a zero o la frequenza di traffico supera il limite.
503 UNAVAILABLE Servizio non disponibile. In genere il server non è attivo.
504 DEADLINE_EXCEEDED Scadenza richiesta superata. Questo si verifica solo se il chiamante imposta una scadenza più breve della scadenza predefinita del metodo (ad esempio, la scadenza richiesta non è sufficiente per consentire al server di elaborare la richiesta) e la richiesta non è stata completata entro la scadenza.

Per maggiori informazioni, consulta Gestione degli errori dell'SDK consumer.