Criar e mostrar uma única viagem de destino

Neste tutorial, explicamos o processo de criação de uma viagem com um único embarque e desembarque e, em seguida, o compartilhamento dessa jornada com um consumidor.

Pré-requisitos

Para concluir este tutorial, faça o seguinte:

  1. Configure o motor da frota. Para mais informações, consulte Fleet Engine: configuração inicial.

  2. Integrar seu app ao SDK do Driver. Para ver mais informações, consulte Como inicializar o SDK do driver para Android e o Guia de integração do SDK do driver para iOS.

  3. Integre seu app voltado ao consumidor com o SDK do consumidor. Para mais informações, consulte Introdução ao SDK do consumidor para Android e Introdução ao SDK do consumidor para iOS.

  4. Configurar tokens de autorização. Para mais informações sobre tokens de autorização, consulte Como criar um JSON Web Token para autorização, no guia "Introdução ao Fleet Engine", e Autenticação e autorização, na documentação do SDK do consumidor para o Fleet Engine.

Etapa 1. Criar um veículo no Fleet Engine

Os veículos são objetos que representam os veículos da sua frota. É necessário criá-los no Fleet Engine para rastreá-los no app do consumidor.

Você pode criar um veículo usando uma destas duas abordagens:

gRPC
Chame o método CreateVehicle() com a mensagem de solicitação CreateVehicleRequest. Você precisa ter privilégios de superusuário do Fleet Engine para chamar CreateVehicle().
REST
Ligue para https://fleetengine.googleapis.com/v1/providers.vehicles.create.

Advertências

As ressalvas a seguir se aplicam quando você cria um veículo.

  • Defina o estado inicial do veículo como OFFLINE. Isso garante que o Fleet Engine possa detectar seu veículo para fazer a correspondência da viagem.

  • O provider_id do veículo precisa ser igual ao ID do projeto do Google Cloud que contém as contas de serviço usadas para chamar o Fleet Engine. Várias contas de serviço podem acessar o Fleet Engine para o mesmo provedor de compartilhamento de navegação, mas o Fleet Engine atualmente não oferece suporte a contas de serviço de diferentes projetos do Google Cloud que acessam os mesmos veículos.

  • A resposta retornada de CreateVehicle() contém a instância Vehicle. A instância será excluída após sete dias se não tiver sido atualizada usando UpdateVehicle(). Chame GetVehicle() antes de chamar CreateVehicle() apenas para confirmar que o veículo ainda não existe. Se GetVehicle() retornar um erro NOT_FOUND, continue chamando CreateVehicle(). Para mais informações, consulte Veículos e o ciclo de vida deles.

Exemplo

O exemplo de código de provedor a seguir demonstra como criar um veículo no Fleet Engine.

static final String PROJECT_ID = "my-rideshare-co-gcp-project";

VehicleServiceBlockingStub vehicleService = VehicleService.newBlockingStub(channel);

String parent = "providers/" + PROJECT_ID;

Vehicle vehicle = Vehicle.newBuilder()
    .setVehicleState(VehicleState.OFFLINE)  // Initial state
    .addSupportedTripTypes(TripType.EXCLUSIVE)
    .setMaximumCapacity(4)
    .setVehicleType(VehicleType.newBuilder().setCategory(VehicleType.Category.AUTO))
    .build();

CreateVehicleRequest createVehicleRequest = CreateVehicleRequest.newBuilder()
    .setParent(parent)
    .setVehicleId("8241890")  // Vehicle ID assigned by solution provider.
    .setVehicle(vehicle)      // Initial state.
    .build();

// The Vehicle is created in the OFFLINE state, and no initial position is
// provided.  When the driver app calls the rideshare provider, the state can be
// set to ONLINE, and the driver app updates the vehicle location.
try {
  Vehicle createdVehicle = vehicleService.createVehicle(createVehicleRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case ALREADY_EXISTS:
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}

Etapa 2: Ativar rastreamento de localização

O rastreamento de localização se refere ao local do veículo durante a viagem, em que o app do motorista envia telemetria para o Fleet Engine, que contém a localização atual do veículo. Esse fluxo de informações de posição constantemente atualizado é usado para transmitir o progresso do veículo ao longo do trajeto da viagem. Quando você ativa o rastreamento de localização, o app do driver começa a enviar essa telemetria a uma frequência padrão de uma vez a cada cinco segundos.

Ative o acompanhamento de local para Android e iOS da seguinte maneira:

Exemplo

O exemplo de código a seguir demonstra como ativar o monitoramento de localização.

Java

RidesharingVehicleReporter vehicleReporter = ...;

vehicleReporter.enableLocationTracking();

Kotlin

val vehicleReporter = ...

vehicleReporter.enableLocationTracking()

Swift

vehicleReporter.locationTrackingEnabled = true

Objective-C

_vehicleReporter.locationTrackingEnabled = YES;

Etapa 3. Definir o estado do veículo como on-line

Para colocar um veículo em serviço (ou seja, disponibilizá-lo para uso), defina o estado dele como on-line, mas não faça isso antes de ativar o rastreamento de localização.

Defina o estado do veículo como on-line para Android e iOS da seguinte maneira:

Exemplo

O exemplo de código abaixo demonstra como definir o estado do veículo como ONLINE.

Java

vehicleReporter.setVehicleState(VehicleState.ONLINE);

Kotlin

vehicleReporter.setVehicleState(VehicleState.ONLINE)

Swift

vehicleReporter.update(.online)

Objective-C

[_vehicleReporter updateVehicleState:GMTDVehicleStateOnline];

Etapa 4. Criar uma viagem no Fleet Engine

Programaticamente, um Trip é um objeto que representa uma jornada. Você precisa criar um objeto para cada solicitação de viagem, de modo que eles possam ser associados a veículos e depois rastreados.

Atributos obrigatórios

Os campos a seguir são obrigatórios para criar uma viagem.

parent
Uma string que inclui o ID do provedor. Precisa ser o mesmo ID do projeto do Google Cloud que contém as contas de serviço usadas para chamar o Fleet Engine
trip_id
Uma string que você cria e que identifica exclusivamente essa viagem.
trip_type
Um dos valores de enumeração TripType (SHARED ou EXCLUSIVE).
pickup_point
O ponto de origem da viagem.

Ao criar uma viagem, você pode informar number_of_passengers, dropoff_point e vehicle_id, mas esses campos não são obrigatórios. Quando você fornece um vehicle_id, a viagem contém uma lista de waypoints restantes, que você pode usar para definir o destino no app do motorista.

Exemplo

O exemplo a seguir demonstra como criar uma viagem para o Grand Indonesia East Mall. A viagem envolve dois passageiros, é exclusiva e o status é new. O provider_id da viagem precisa ser igual ao ID do projeto. No exemplo, o provedor de transporte por aplicativo criou o projeto do Google Cloud com o ID my-rideshare-co-gcp-project. Esse projeto precisa incluir uma conta de serviço para chamar o Fleet Engine.

static final String PROJECT_ID = "my-rideshare-co-gcp-project";

TripServiceBlockingStub tripService = TripService.newBlockingStub(channel);

// Trip initial settings.
String parent = "providers/" + PROJECT_ID;

Trip trip = Trip.newBuilder()
    .setTripType(TripType.EXCLUSIVE) // Use TripType.SHARED for carpooling.
    .setPickupPoint(                 // Grand Indonesia East Mall.
        TerminalLocation.newBuilder().setPoint(
            LatLng.newBuilder()
                .setLatitude(-6.195139).setLongitude(106.820826)))
    .setNumberOfPassengers(2)
    // Provide the drop-off point if available.
    .setDropoffPoint(
        TerminalLocation.newBuilder().setPoint(
            LatLng.newBuilder()
                .setLatitude(-6.1275).setLongitude(106.6537)))
    .build();

// Create trip request
CreateTripRequest createTripRequest = CreateTripRequest.newBuilder()
    .setParent(parent)
    .setTripId("trip-8241890")  // Trip ID assigned by the provider.
    .setTrip(trip)              // The initial state is NEW.
    .build();

// Error handling.
try {
  Trip createdTrip = tripService.createTrip(createTripRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case ALREADY_EXISTS:
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}

Etapa 5. Definir o destino no app do motorista

Depois de parear um consumidor com um motorista, configure o destino da viagem no app dele. É possível recuperar o destino do veículo na coleção de waypoints, que é retornada por GetTrip(), UpdateTrip() e GetVehicle().

Para que o app do consumidor renderize corretamente a viagem, as coordenadas geográficas (LatLng) fornecidas a setDestination() precisam corresponder às do waypoint da viagem. Para mais informações, consulte os tutoriais Rotear para um único destino e Rotear para vários destinos.

Exemplo

O exemplo de código a seguir demonstra como definir o destino no app de motorista.

Java

private void navigateToPlace(String placeId, RoutingOptions travelMode) {
  Waypoint destination;
  try {
    destination = Waypoint.fromPlaceId(placeId, null);
  } catch (Waypoint.UnsupportedPlaceIdException e) {
    displayMessage("Error starting navigation: Place ID is not supported.");
    return;
  }

  // Create a future to await the result of the asynchronous navigator task.
  ListenableResultFuture<Navigator.RouteStatus> pendingRoute =
      mNavigator.setDestination(destination, travelMode);

  // Define the action to perform when the SDK has determined the route.
  pendingRoute.setOnResultListener(
      new ListenableResultFuture.OnResultListener<Navigator.RouteStatus>() {
        @Override
        public void onResult(Navigator.RouteStatus code) {
          switch (code) {
            case OK:
              // Hide the toolbar to maximize the navigation UI.
              if (getActionBar() != null) {
                getActionBar().hide();
              }

              // Enable voice audio guidance (through the device speaker).
              mNavigator.setAudioGuidance(
                  Navigator.AudioGuidance.VOICE_ALERTS_AND_GUIDANCE);

              // Simulate vehicle progress along the route for demo/debug builds.
              if (BuildConfig.DEBUG) {
                mNavigator.getSimulator().simulateLocationsAlongExistingRoute(
                    new SimulationOptions().speedMultiplier(5));
              }

              // Start turn-by-turn guidance along the current route.
              mNavigator.startGuidance();
              break;
            // Handle error conditions returned by the navigator.
            case NO_ROUTE_FOUND:
              displayMessage("Error starting navigation: No route found.");
              break;
            case NETWORK_ERROR:
              displayMessage("Error starting navigation: Network error.");
              break;
            case ROUTE_CANCELED:
              displayMessage("Error starting navigation: Route canceled.");
              break;
            default:
              displayMessage("Error starting navigation: "
                  + String.valueOf(code));
          }
        }
      });
}

Kotlin

private fun navigateToPlace(placeId: String, travelMode: RoutingOptions) {
  val destination =
    try {
      Waypoint.fromPlaceId(placeId, null)
    } catch (e: Waypoint.UnsupportedPlaceIdException) {
      displayMessage("Error starting navigation: Place ID is not supported.")
      return@navigateToPlace
    }

  // Create a future to await the result of the asynchronous navigator task.
  val pendingRoute = mNavigator.setDestination(destination, travelMode)

  // Define the action to perform when the SDK has determined the route.
  pendingRoute.setOnResultListener(
    object : ListenableResultFuture.OnResultListener<Navigator.RouteStatus>() {
      override fun onResult(code: Navigator.RouteStatus) {
        when (code) {
          Navigator.RouteStatus.OK -> {
            // Hide the toolbar to maximize the navigation UI.
            getActionBar()?.hide()

            // Enable voice audio guidance (through the device speaker).
            mNavigator.setAudioGuidance(Navigator.AudioGuidance.VOICE_ALERTS_AND_GUIDANCE)

            // Simulate vehicle progress along the route for demo/debug builds.
            if (BuildConfig.DEBUG) {
              mNavigator
                .getSimulator()
                .simulateLocationsAlongExistingRoute(SimulationOptions().speedMultiplier(5))
            }

            // Start turn-by-turn guidance along the current route.
            mNavigator.startGuidance()
          }
          Navigator.RouteStatus.NO_ROUTE_FOUND -> {
            displayMessage("Error starting navigation: No route found.")
          }
          Navigator.RouteStatus.NETWORK_ERROR -> {
            displayMessage("Error starting navigation: Network error.")
          }
          Navigator.RouteStatus.ROUTE_CANCELED -> {
            displayMessage("Error starting navigation: Route canceled.")
          }
          else -> {
            displayMessage("Error starting navigation: ${code.name}")
          }
        }
      }
    }
  )
}

Swift

private func startNavigation() {
  let destinations = [
    GMSNavigationWaypoint(
      placeID: "ChIJnUYTpNASkFQR_gSty5kyoUk", title: "PCC Natural Market"),
    GMSNavigationWaypoint(
      placeID: "ChIJJ326ROcSkFQRBfUzOL2DSbo", title: "Marina Park"),
  ]

  mapView.navigator?.setDestinations(destinations, callback: { routeStatus in
    guard routeStatus == .OK else {
      // Error starting navigation.
      return
    }
    mapView.locationSimulator?.simulateLocationsAlongExistingRoute()
    mapView.navigator?.isGuidanceActive = true
    mapView.navigator?.sendsBackgroundNotifications = true
    mapView.cameraMode = .following
  })
}

Objective-C

- (void)startNavigation {
  NSArray<GMSNavigationWaypoint *> *destinations =
  @[[[GMSNavigationWaypoint alloc] initWithPlaceID:@"ChIJnUYTpNASkFQR_gSty5kyoUk"
                                             title:@"PCC Natural Market"],
    [[GMSNavigationWaypoint alloc] initWithPlaceID:@"ChIJJ326ROcSkFQRBfUzOL2DSbo"
                                             title:@"Marina Park"]];

  [_mapView.navigator setDestinations:destinations
                             callback:^(GMSRouteStatus routeStatus) {
                               if (routeStatus != GMSRouteStatusOK) {
                                 // Error starting navigation.
                                 return;
                               }
                               [_mapView.locationSimulator simulateLocationsAlongExistingRoute];
                               _mapView.navigator.guidanceActive = YES;
                               _mapView.navigator.sendsBackgroundNotifications = YES;
                               _mapView.cameraMode = GMSNavigationCameraModeFollowing;
                             }];
}

Etapa 6. Detectar atualizações de viagens no app para consumidores

  • No Android, você pode detectar atualizações de dados de uma viagem acessando um objeto TripModel do TripModelManager e registrando um listener TripModelCallback.

  • No iOS, você pode detectar atualizações de dados de uma viagem acessando um objeto GMTCTripModel do GMTCTripService e registrando um assinante GMTCTripModelSubscriber.

Um listener TripModelCallback e um assinante GMTCTripModelSubscriber permitem que o app receba atualizações periódicas do andamento da viagem em cada atualização com base no intervalo da atualização automática. Somente os valores que mudam podem acionar o callback. Caso contrário, o callback permanecerá silencioso.

Os métodos TripModelCallback.onTripUpdated() e tripModel(_:didUpdate:updatedPropertyFields:) são sempre chamados, independentemente de qualquer mudança de dados.

Exemplo 1

O exemplo de código abaixo demonstra como conseguir um TripModel de TripModelManager/GMTCTripService e definir um listener.

Java

// Start journey sharing after a trip has been created via Fleet Engine.
TripModelManager tripModelManager = consumerApi.getTripModelManager();

// Get a TripModel object.
TripModel tripModel = tripModelManager.getTripModel(tripName);

// Register a listener on the trip.
TripModelCallback tripCallback = new TripModelCallback() {
  ...
};
tripModel.registerTripCallback(tripCallback);

// Set the refresh interval.
TripModelOptions tripModelOptions = TripModelOptions.builder()
    .setRefreshInterval(5000) // interval in milliseconds, so 5 seconds
    .build();
tripModel.setTripModelOptions(tripModelOptions);

// The trip stops auto-refreshing when all listeners are unregistered.
tripModel.unregisterTripCallback(tripCallback);

Kotlin

// Start journey sharing after a trip has been created via Fleet Engine.
val tripModelManager = consumerApi.getTripModelManager()

// Get a TripModel object.
val tripModel = tripModelManager.getTripModel(tripName)

// Register a listener on the trip.
val tripCallback = TripModelCallback() {
  ...
}

tripModel.registerTripCallback(tripCallback)

// Set the refresh interval.
val tripModelOptions =
  TripModelOptions.builder()
    .setRefreshInterval(5000) // interval in milliseconds, so 5 seconds
    .build()

tripModel.setTripModelOptions(tripModelOptions)

// The trip stops auto-refreshing when all listeners are unregistered.
tripModel.unregisterTripCallback(tripCallback)

Swift

let tripService = GMTCServices.shared().tripService

// Create a tripModel instance for listening for updates from the trip
// specified by the trip name.
let tripModel = tripService.tripModel(forTripName: tripName)

// Register for the trip update events.
tripModel.register(self)

// Set the refresh interval (in seconds).
tripModel.options.autoRefreshTimeInterval = 5

// Unregister for the trip update events.
tripModel.unregisterSubscriber(self)

Objective-C

GMTCTripService *tripService = [GMTCServices sharedServices].tripService;

// Create a tripModel instance for listening for updates from the trip
// specified by the trip name.
GMTCTripModel *tripModel = [tripService tripModelForTripName:tripName];

// Register for the trip update events.
[tripModel registerSubscriber:self];

// Set the refresh interval (in seconds).
tripModel.options.autoRefreshTimeInterval = 5;

// Unregister for the trip update events.
[tripModel unregisterSubscriber:self];

Exemplo 2

O exemplo de código a seguir demonstra como configurar um listener TripModelCallback e um assinante GMTCTripModelSubscriber.

Java

// Implements a callback for the trip model so your app can listen for trip
// updates from Fleet Engine.
TripModelCallback subscriber =
  new TripModelCallback() {

    @Override
    public void onTripStatusUpdated(TripInfo tripInfo, @TripStatus int status) {
      // ...
    }

    @Override
    public void onTripActiveRouteUpdated(TripInfo tripInfo, List<LatLng> route) {
      // ...
    }

    @Override
    public void onTripVehicleLocationUpdated(
        TripInfo tripInfo, @Nullable VehicleLocation vehicleLocation) {
      // ...
    }

    @Override
    public void onTripPickupLocationUpdated(
        TripInfo tripInfo, @Nullable TerminalLocation pickup) {
      // ...
    }

    @Override
    public void onTripPickupTimeUpdated(TripInfo tripInfo, @Nullable Long timestampMillis) {
      // ...
    }

    @Override
    public void onTripDropoffLocationUpdated(
        TripInfo tripInfo, @Nullable TerminalLocation dropoff) {
      // ...
    }

    @Override
    public void onTripDropoffTimeUpdated(TripInfo tripInfo, @Nullable Long timestampMillis) {
      // ...
    }

    @Override
    public void onTripETAToNextWaypointUpdated(
        TripInfo tripInfo, @Nullable Long timestampMillis) {
      // ...
    }

    @Override
    public void onTripActiveRouteRemainingDistanceUpdated(
        TripInfo tripInfo, @Nullable Integer distanceMeters) {
      // ...
    }

    @Override
    public void onTripUpdateError(TripInfo tripInfo, TripUpdateError error) {
      // ...
    }

    @Override
    public void onTripUpdated(TripInfo tripInfo) {
      // ...
    }

    @Override
    public void onTripRemainingWaypointsUpdated(
        TripInfo tripInfo, List<TripWaypoint> waypointList) {
      // ...
    }

    @Override
    public void onTripIntermediateDestinationsUpdated(
        TripInfo tripInfo, List<TerminalLocation> intermediateDestinations) {
      // ...
    }

    @Override
    public void onTripRemainingRouteDistanceUpdated(
        TripInfo tripInfo, @Nullable Integer distanceMeters) {
      // ...
    }

    @Override
    public void onTripRemainingRouteUpdated(TripInfo tripInfo, List<LatLng> route) {
      // ...
    }
  };

Kotlin

// Implements a callback for the trip model so your app can listen for trip
// updates from Fleet Engine.
val subscriber =
  object : TripModelCallback() {
    override fun onTripStatusUpdated(tripInfo: TripInfo, status: @TripStatus Int) {
      // ...
    }

    override fun onTripActiveRouteUpdated(tripInfo: TripInfo, route: List<LatLng>) {
      // ...
    }

    override fun onTripVehicleLocationUpdated(
      tripInfo: TripInfo,
      vehicleLocation: VehicleLocation?
    ) {
      // ...
    }

    override fun onTripPickupLocationUpdated(tripInfo: TripInfo, pickup: TerminalLocation?) {
      // ...
    }

    override fun onTripPickupTimeUpdated(tripInfo: TripInfo, timestampMillis: Long?) {
      // ...
    }

    override fun onTripDropoffLocationUpdated(tripInfo: TripInfo, dropoff: TerminalLocation?) {
      // ...
    }

    override fun onTripDropoffTimeUpdated(tripInfo: TripInfo, timestampMillis: Long?) {
      // ...
    }

    override fun onTripETAToNextWaypointUpdated(tripInfo: TripInfo, timestampMillis: Long?) {
      // ...
    }

    override fun onTripActiveRouteRemainingDistanceUpdated(
      tripInfo: TripInfo,
      distanceMeters: Int?
    ) {
      // ...
    }

    override fun onTripUpdateError(tripInfo: TripInfo, error: TripUpdateError) {
      // ...
    }

    override fun onTripUpdated(tripInfo: TripInfo) {
      // ...
    }

    override fun onTripRemainingWaypointsUpdated(
      tripInfo: TripInfo,
      waypointList: List<TripWaypoint>
    ) {
      // ...
    }

    override fun onTripIntermediateDestinationsUpdated(
      tripInfo: TripInfo,
      intermediateDestinations: List<TerminalLocation>
    ) {
      // ...
    }

    override fun onTripRemainingRouteDistanceUpdated(tripInfo: TripInfo, distanceMeters: Int?) {
      // ...
    }

    override fun onTripRemainingRouteUpdated(tripInfo: TripInfo, route: List<LatLng>) {
      // ...
    }
  }

Swift

class TripModelSubscriber: NSObject, GMTCTripModelSubscriber {

  func tripModel(_: GMTCTripModel, didUpdate trip: GMTSTrip?, updatedPropertyFields: GMTSTripPropertyFields) {
    // Update the UI with the new `trip` data.
    updateUI(with: trip)
    ...
  }

  func tripModel(_: GMTCTripModel, didUpdate tripStatus: GMTSTripStatus) {
    // Handle trip status did change.
  }

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

  ...
}

Objective-C

@interface TripModelSubscriber : NSObject <GMTCTripModelSubscriber>
@end

@implementation TripModelSubscriber

- (void)tripModel:(GMTCTripModel *)tripModel
            didUpdateTrip:(nullable GMTSTrip *)trip
    updatedPropertyFields:(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
    didUpdateActiveRoute:(nullable NSArray<GMTSLatLng *> *)activeRoute {
  // Handle trip 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.
}
…
@end

Você pode acessar informações sobre a viagem a qualquer momento da seguinte maneira:

  • Chame o método TripModel.getTripInfo() do SDK do consumidor para Android. Chamar esse método não força uma atualização de dados, embora os dados ainda continuem a ser atualizados na frequência de atualização.

  • Faça o download da propriedade GMTCTripModel.currentTrip do SDK do consumidor para iOS.

Etapa 7. Atualize a viagem com o ID do veículo.

Você precisa configurar a viagem com um ID de veículo para que o Fleet Engine possa rastrear o veículo ao longo do trajeto.

  • É possível atualizar a viagem com o ID do veículo chamando o endpoint UpdateTrip com um UpdateTripRequest. Use o campo update_mask para especificar que você está atualizando o ID do veículo.

Observações

  • Se você não especificar um destino ao criar a viagem, poderá fazê-lo aqui.

  • Se você precisar trocar de veículo em uma viagem em andamento, defina o estado dela como novo e, em seguida, atualize a viagem (como fez acima) com o novo ID do veículo.

Exemplo

O exemplo de código a seguir demonstra como atualizar a viagem com um ID de veículo.

static final String PROJECT_ID = "my-rideshare-co-gcp-project";
static final String TRIP_ID = "trip-8241890";

String tripName = "providers/" + PROJECT_ID + "/trips/" + TRIP_ID;

TripServiceBlockingStub tripService = TripService.newBlockingStub(channel);

// The trip settings to update.
Trip trip = Trip.newBuilder()
    .setVehicleId("8241890")
    .build();

// The trip update request.
UpdateTripRequest updateTripRequest =
    UpdateTripRequest.newBuilder()      // No need for the header.
        .setName(tripName)
        .setTrip(trip)
        .setUpdateMask(FieldMask.newBuilder().addPaths("vehicle_id"))
        .build();

// Error handling.
// If the Fleet Engine has both a trip and vehicle with IDs, and if the
// credentials validate, then the service updates the trip.
try {
  Trip updatedTrip = tripService.updateTrip(updateTripRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case NOT_FOUND:                    // Neither the trip nor vehicle exist.
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}

Etapa 8. Mostre a jornada no app para o consumidor

Use o objeto ConsumerController para acessar as APIs do elemento da interface do usuário Rides e Deliveries.

Para mais informações, consulte Como usar as APIs do elemento da interface do usuário.

Exemplo

O exemplo de código a seguir demonstra como iniciar a jornada da interface do usuário.

Java

JourneySharingSession session = JourneySharingSession.createInstance(tripModel);
consumerController.showSession(session);

Kotlin

val session = JourneySharingSession.createInstance(tripModel)
consumerController.showSession(session)

Swift

let journeySharingSession = GMTCJourneySharingSession(tripModel: tripModel)
mapView.show(journeySharingSession)

Objective-C

GMTCJourneySharingSession *journeySharingSession =
    [[GMTCJourneySharingSession alloc] initWithTripModel:tripModel];
[self.mapView showMapViewSession:journeySharingSession];

Etapa 9: Gerenciar o estado da viagem no Fleet Engine

Especifique o estado de uma viagem usando um dos valores de enumeração TripStatus. Quando o estado de uma viagem muda (por exemplo, de ENROUTE_TO_PICKUP para ARRIVED_AT_PICKUP), você precisa atualizar o estado da viagem usando o Fleet Engine. O estado da viagem sempre começa com o valor NEW e termina com COMPLETE ou CANCELED. Para mais informações, consulte trip_status.

Exemplo

O exemplo de código a seguir demonstra como atualizar o estado da viagem no mecanismo da frota.

static final String PROJECT_ID = "my-rideshare-co-gcp-project";
static final String TRIP_ID = "trip-8241890";

String tripName = "providers/" + PROJECT_ID + "/trips/" + TRIP_ID;

TripServiceBlockingStub tripService = TripService.newBlockingStub(channel);

// Trip settings to be updated.
Trip trip = Trip.newBuilder()
    .setTripStatus(TripStatus.ARRIVED_AT_PICKUP)
    .build();

// Trip update request
UpdateTripRequest updateTripRequest = UpdateTripRequest.newBuilder()
    .setName(tripName)
    .setTrip(trip)
    .setUpdateMask(FieldMask.newBuilder().addPaths("trip_status"))
    .build();

// Error handling.
try {
  Trip updatedTrip = tripService.updateTrip(updateTripRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case NOT_FOUND:            // The trip doesn't exist.
      break;
    case FAILED_PRECONDITION:  // The given trip status is invalid.
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}