Quando segui un viaggio, la tua app per i consumatori mostra la posizione del veicolo appropriato al consumatore. Per farlo, la tua app deve iniziare a seguire un viaggio, aggiornare l'avanzamento del viaggio e smettere di seguirlo quando è completato.
Questo documento descrive come funziona la procedura.
Iniziare a seguire un viaggio
Ecco come iniziare a seguire un viaggio:
- Raccogli tutti gli input dell'utente, come le località di partenza e arrivo, da un - ViewController.
- Crea un nuovo - ViewControllerper iniziare a seguire un viaggio direttamente.
L'esempio seguente mostra come iniziare a seguire un viaggio immediatamente dopo il caricamento della visualizzazione.
Swift
/*
 * MapViewController.swift
 */
override func viewDidLoad() {
  super.viewDidLoad()
  ...
  self.mapView = GMTCMapView(frame: UIScreen.main.bounds)
  self.mapView.delegate = self
  self.view.addSubview(self.mapView)
}
func mapViewDidInitializeCustomerState(_: GMTCMapView) {
  self.mapView.pickupLocation = self.selectedPickupLocation
  self.mapView.dropoffLocation = self.selectedDropoffLocation
  self.startConsumerMatchWithLocations(
    pickupLocation: self.mapView.pickupLocation!,
    dropoffLocation: self.mapView.dropoffLocation!
  ) { [weak self] (tripName, error) in
    guard let strongSelf = self else { return }
    if error != nil {
      // print error message.
      return
    }
    let tripService = GMTCServices.shared().tripService
    // Create a tripModel instance for listening the update of the trip
    // specified by this trip name.
    let tripModel = tripService.tripModel(forTripName: tripName)
    // Create a journeySharingSession instance based on the tripModel
    let journeySharingSession = GMTCJourneySharingSession(tripModel: tripModel)
    // Add the journeySharingSession instance on the mapView for UI updating.
    strongSelf.mapView.show(journeySharingSession)
    // Register for the trip update events.
    tripModel.register(strongSelf)
    strongSelf.currentTripModel = tripModel
    strongSelf.currentJourneySharingSession = journeySharingSession
    strongSelf.hideLoadingView()
  }
  self.showLoadingView()
}
Objective-C
/*
 * MapViewController.m
 */
- (void)viewDidLoad {
  [super viewDidLoad];
  ...
  self.mapView = [[GMTCMapView alloc] initWithFrame:CGRectZero];
  self.mapView.delegate = self;
  [self.view addSubview:self.mapView];
}
// Handle the callback when the GMTCMapView did initialized.
- (void)mapViewDidInitializeCustomerState:(GMTCMapView *)mapview {
  self.mapView.pickupLocation = self.selectedPickupLocation;
  self.mapView.dropoffLocation = self.selectedDropoffLocation;
  __weak __typeof(self) weakSelf = self;
  [self startTripBookingWithPickupLocation:self.selectedPickupLocation
                           dropoffLocation:self.selectedDropoffLocation
                                completion:^(NSString *tripName, NSError *error) {
                                  __typeof(self) strongSelf = weakSelf;
                                  GMTCTripService *tripService = [GMTCServices sharedServices].tripService;
                                  // Create a tripModel instance for listening to updates to the trip specified by this trip name.
                                  GMTCTripModel *tripModel = [tripService tripModelForTripName:tripName];
                                  // Create a journeySharingSession instance based on the tripModel.
                                  GMTCJourneySharingSession *journeySharingSession =
                                    [[GMTCJourneySharingSession alloc] initWithTripModel:tripModel];
                                  // Add the journeySharingSession instance on the mapView for updating the UI.
                                  [strongSelf.mapView showMapViewSession:journeySharingSession];
                                  // Register for trip update events.
                                  [tripModel registerSubscriber:self];
                                  strongSelf.currentTripModel = tripModel;
                                  strongSelf.currentJourneySharingSession = journeySharingSession;
                                  [strongSelf hideLoadingView];
                                }];
    [self showLoadingView];
}
Smettere di seguire un viaggio
Smetti di seguire un viaggio quando è completato o annullato. L'esempio seguente mostra come interrompere la condivisione del viaggio attivo.
Swift
/*
 * MapViewController.swift
 */
func cancelCurrentActiveTrip() {
  // Stop the tripModel
  self.currentTripModel.unregisterSubscriber(self)
  // Remove the journey sharing session from the mapView's UI stack.
  self.mapView.hide(journeySharingSession)
}
Objective-C
/*
 * MapViewController.m
 */
- (void)cancelCurrentActiveTrip {
  // Stop the tripModel
  [self.currentTripModel unregisterSubscriber:self];
  // Remove the journey sharing session from the mapView's UI stack.
  [self.mapView hideMapViewSession:journeySharingSession];
}
Aggiornare l'avanzamento del viaggio
Durante un viaggio, gestisci l'avanzamento del viaggio nel seguente modo:
- Inizia ad ascoltare gli aggiornamenti. Per un esempio, vedi Esempio di avvio dell'ascolto degli aggiornamenti. 
- Gestire eventuali aggiornamenti della corsa. Per un esempio, vedi Esempio di gestione degli aggiornamenti della corsa 
Quando una corsa viene completata o cancellata, interrompi l'ascolto degli aggiornamenti. Per un esempio, vedi Esempio di interruzione dell'ascolto degli aggiornamenti.
Esempio di avvio dell'ascolto degli aggiornamenti
Il seguente esempio mostra come registrare il callback tripModel.
Swift
/*
 * MapViewController.swift
 */
override func viewDidLoad() {
  super.viewDidLoad()
  // Register for trip update events.
  self.currentTripModel.register(self)
}
Objective-C
/*
 * MapViewController.m
 */
- (void)viewDidLoad {
  [super viewDidLoad];
  // Register for trip update events.
  [self.currentTripModel registerSubscriber:self];
  ...
}
Esempio di interruzione dell'ascolto degli aggiornamenti
L'esempio seguente mostra come annullare la registrazione del callback tripModel.
Swift
/*
 * MapViewController.swift
 */
deinit {
  self.currentTripModel.unregisterSubscriber(self)
}
Objective-C
/*
 * MapViewController.m
 */
- (void)dealloc {
  [self.currentTripModel unregisterSubscriber:self];
  ...
}
Esempio di gestione degli aggiornamenti del viaggio
L'esempio seguente mostra come implementare il protocollo GMTCTripModelSubscriber
per la gestione dei callback quando lo stato del viaggio viene aggiornato.
Swift
/*
 * MapViewController.swift
 */
func tripModel(_: GMTCTripModel, didUpdate trip: GMTSTrip?, updatedPropertyFields: GMTSTripPropertyFields) {
  // Update the UI with the new `trip` data.
  self.updateUI(with: trip)
}
func tripModel(_: GMTCTripModel, didUpdate tripStatus: GMTSTripStatus) {
  // Handle trip status did change.
}
func tripModel(_: GMTCTripModel, didUpdateActiveRouteRemainingDistance activeRouteRemainingDistance: Int32) {
  // Handle remaining distance of active route did update.
}
func tripModel(_: GMTCTripModel, didUpdateActiveRoute activeRoute: [GMTSLatLng]?) {
  // Handle trip active route did update.
}
func tripModel(_: GMTCTripModel, didUpdate vehicleLocation: GMTSVehicleLocation?) {
  // Handle vehicle location did update.
}
func tripModel(_: GMTCTripModel, didUpdatePickupLocation pickupLocation: GMTSTerminalLocation?) {
  // Handle pickup location did update.
}
func tripModel(_: GMTCTripModel, didUpdateDropoffLocation dropoffLocation: GMTSTerminalLocation?) {
  // Handle drop off location did update.
}
func tripModel(_: GMTCTripModel, didUpdatePickupETA pickupETA: TimeInterval) {
  // Handle the pickup ETA did update.
}
func tripModel(_: GMTCTripModel, didUpdateDropoffETA dropoffETA: TimeInterval) {
  // Handle the drop off ETA did update.
}
func tripModel(_: GMTCTripModel, didUpdateRemaining remainingWaypoints: [GMTSTripWaypoint]?) {
  // Handle updates to the pickup, dropoff or intermediate destinations of the trip.
}
func tripModel(_: GMTCTripModel, didFailUpdateTripWithError error: Error?) {
  // Handle the error.
}
func tripModel(_: GMTCTripModel, didUpdateIntermediateDestinations intermediateDestinations: [GMTSTerminalLocation]?) {
  // Handle the intermediate destinations being updated.
}
func tripModel(_: GMTCTripModel, didUpdateActiveRouteTraffic activeRouteTraffic: GMTSTrafficData?) {
  // Handle trip active route traffic being updated.
}
Objective-C
/*
 * MapViewController.m
 */
#pragma mark - GMTCTripModelSubscriber implementation
- (void)tripModel:(GMTCTripModel *)tripModel
            didUpdateTrip:(nullable GMTSTrip *)trip
    updatedPropertyFields:(enum GMTSTripPropertyFields)updatedPropertyFields {
  // Update the UI with the new `trip` data.
  [self updateUIWithTrip:trip];
  ...
}
- (void)tripModel:(GMTCTripModel *)tripModel didUpdateTripStatus:(enum GMTSTripStatus)tripStatus {
  // Handle trip status did change.
}
- (void)tripModel:(GMTCTripModel *)tripModel
    didUpdateActiveRouteRemainingDistance:(int32_t)activeRouteRemainingDistance {
   // Handle remaining distance of active route did update.
}
- (void)tripModel:(GMTCTripModel *)tripModel
    didUpdateActiveRoute:(nullable NSArray<GMTSLatLng *> *)activeRoute {
  // Handle trip active route did update.
}
- (void)tripModel:(GMTCTripModel *)tripModel
    didUpdateVehicleLocation:(nullable GMTSVehicleLocation *)vehicleLocation {
  // Handle vehicle location did update.
}
- (void)tripModel:(GMTCTripModel *)tripModel
    didUpdatePickupLocation:(nullable GMTSTerminalLocation *)pickupLocation {
  // Handle pickup location did update.
}
- (void)tripModel:(GMTCTripModel *)tripModel
    didUpdateDropoffLocation:(nullable GMTSTerminalLocation *)dropoffLocation {
  // Handle drop off location did update.
}
- (void)tripModel:(GMTCTripModel *)tripModel didUpdatePickupETA:(NSTimeInterval)pickupETA {
  // Handle the pickup ETA did update.
}
- (void)tripModel:(GMTCTripModel *)tripModel
    didUpdateRemainingWaypoints:(nullable NSArray<GMTSTripWaypoint *> *)remainingWaypoints {
  // Handle updates to the pickup, dropoff or intermediate destinations of the trip.
}
- (void)tripModel:(GMTCTripModel *)tripModel didUpdateDropoffETA:(NSTimeInterval)dropoffETA {
  // Handle the drop off ETA did update.
}
- (void)tripModel:(GMTCTripModel *)tripModel didFailUpdateTripWithError:(nullable NSError *)error {
  // Handle the error.
}
- (void)tripModel:(GMTCTripModel *)tripModel
    didUpdateIntermediateDestinations:
        (nullable NSArray<GMTSTerminalLocation *> *)intermediateDestinations {
  // Handle the intermediate destinations being updated.
}
- (void)tripModel:(GMTCTripModel *)tripModel
    didUpdateActiveRouteTraffic:(nullable GMTSTrafficData *)activeRouteTraffic {
  // Handle trip active route traffic being updated.
}
Gestire gli errori di viaggio
Se hai eseguito la sottoscrizione di tripModel e si verifica un errore, puoi ricevere il callback
di tripModel implementando il metodo delegato
tripModel(_:didFailUpdateTripWithError:). I messaggi di errore
seguono lo standard di errore di Google Cloud. Per definizioni dettagliate dei messaggi di errore e tutti i codici di errore, consulta la documentazione sugli errori di Google Cloud.
Di seguito sono riportati alcuni errori comuni che possono verificarsi durante il monitoraggio del viaggio:
| HTTP | RPC | Descrizione | 
|---|---|---|
| 400 | INVALID_ARGUMENT | Il client ha specificato un nome del viaggio non valido. Il nome del viaggio deve seguire il formato providers/{provider_id}/trips/{trip_id}. L'provider_id deve essere l'ID del progetto Cloud di proprietà del service provider. | 
| 401 | UNAUTHENTICATED | Ricevi questo errore se non sono presenti credenziali di autenticazione valide. Ad esempio, se il token JWT è firmato senza un ID viaggio o se il token JWT è scaduto. | 
| 403 | PERMISSION_DENIED | Ricevi questo errore se il client non dispone di autorizzazioni sufficienti (ad esempio, un utente con il ruolo di consumatore tenta di chiamare updateTrip), se il token JWT non è valido o se l'API non è abilitata per il progetto client. Il token JWT potrebbe essere mancante o firmato con un ID viaggio che non corrisponde all'ID viaggio richiesto. | 
| 429 | RESOURCE_EXHAUSTED | La quota di risorse è pari a zero o la velocità del traffico supera il limite. | 
| 503 | UNAVAILABLE | Servizio non disponibile. In genere il server non è attivo. | 
| 504 | DEADLINE_EXCEEDED | Scadenza richiesta superata. Questo errore si verifica solo se il chiamante imposta una scadenza più breve di quella predefinita del metodo (ovvero la scadenza richiesta non è sufficiente per consentire al server di elaborare la richiesta) e la richiesta non è stata completata entro la scadenza. | 
Gestire gli errori dell'SDK consumer
L'SDK Consumer invia gli errori di aggiornamento del viaggio all'app consumer utilizzando un meccanismo di callback. Il parametro di callback è un tipo restituito specifico della piattaforma (
TripUpdateError
su Android e
NSError
su iOS).
Codici di stato dell'estrazione
Gli errori passati al callback sono in genere errori gRPC e puoi anche estrarre ulteriori informazioni sotto forma di codice di stato. Per l'elenco completo dei codici di stato, consulta Codici di stato e loro utilizzo in gRPC.
Swift
Il NSError viene richiamato in tripModel(_:didFailUpdateTripWithError:).
// Called when there is a trip update error.
func tripModel(_ tripModel: GMTCTripModel, didFailUpdateTripWithError error: Error?) {
  // Check to see if the error comes from gRPC.
  if let error = error as NSError?, error.domain == "io.grpc" {
    let gRPCErrorCode = error.code
    ...
  }
}
Objective-C
Il NSError viene richiamato in tripModel:didFailUpdateTripWithError:.
// Called when there is a trip update error.
- (void)tripModel:(GMTCTripModel *)tripModel didFailUpdateTripWithError:(NSError *)error {
  // Check to see if the error comes from gRPC.
  if ([error.domain isEqualToString:@"io.grpc"]) {
    NSInteger gRPCErrorCode = error.code;
    ...
  }
}
Interpretare i codici di stato
I codici di stato coprono due tipi di errori: errori relativi al server e alla rete ed errori lato client.
Errori del server e di rete
I seguenti codici di stato si riferiscono a errori di rete o del server e non devi intraprendere alcuna azione per risolverli. L'SDK consumer si riprende automaticamente da questi errori.
| Codice di stato | Descrizione | 
|---|---|
| INTERROTTO | Il server ha interrotto l'invio della risposta. Di solito questo problema è causato da un problema del server. | 
| CANCELLATO | Il server ha terminato la risposta in uscita. Ciò si verifica
      in genere quando l'app viene inviata in background o quando si verifica una modifica dello stato nell'app consumer. | 
| INTERROTTO | |
| DEADLINE_EXCEEDED | Il server ha impiegato troppo tempo per rispondere. | 
| UNAVAILABLE | Il server non era disponibile. Di solito questo problema è causato da un problema di rete. | 
Errori client
I seguenti codici di stato si riferiscono a errori del client e devi intervenire per risolverli. L'SDK Consumer continua a riprovare ad aggiornare il viaggio finché non interrompi la condivisione del viaggio, ma non verrà ripristinato finché non intervieni.
| Codice di stato | Descrizione | 
|---|---|
| INVALID_ARGUMENT | L'app Consumer ha specificato un nome del viaggio non valido. Il nome del viaggio deve
      seguire il formato providers/{provider_id}/trips/{trip_id}. | 
| NOT_FOUND | Il viaggio non è mai stato creato. | 
| PERMISSION_DENIED | L'app Consumer non dispone di autorizzazioni sufficienti. Questo errore si verifica quando: 
 | 
| RESOURCE_EXHAUSTED | La quota di risorse è pari a zero o la velocità del flusso di traffico supera il limite di velocità. | 
| UNAUTHENTICATED | L'autenticazione della richiesta non è riuscita a causa di un token JWT non valido. Questo errore si verifica quando il token JWT viene firmato senza un ID viaggio oppure quando il token JWT è scaduto. |