On-demand Rides and Deliveries Solution is currently available only to select partners.

Create and display shared-pool trips

Shared-pool trips are shared trips for multiple consumers that simultaneously share the vehicle. That is, the trips are concurrent, not independent. The way this works is similar to the way airport shuttles work, except the driver can also drop consumers off along the route.

The main difference between a shared-pool and a single-destination trip, is that in with a shared-pool trip, the trip operator could be transporting more than one rider at the same time.

This tutorial walks you through the process of creating a shared-pool trip. It also shows how you can then integrate that trip with your consumer-application so that your customers can visualize the trip progress from their phones. You do this integration using the Consumer SDK.

Step 1. Create a vehicle in Fleet Engine

Vehicles are objects that represent the vehicles in your fleet. You must create them in Fleet Engine in order to be able to track them in the consumer app.

You can create a vehicle using either of the following two approaches:

gRPC
Call the CreateVehicle() method with the CreateVehicleRequest request message. You must have Fleet Engine Super User privileges to call CreateVehicle().
REST
Call https://fleetengine.googleapis.com/v1/providers.vehicles.create.

Caveats

The following caveats apply when you create a vehicle.

  • Be sure to set the initial vehicle state to OFFLINE. This ensures that Fleet Engine can discover your vehicle for trip matching.

  • The vehicle's provider_id must be the same as the project ID of the Google Cloud Project that contains the Service Accounts used for calling Fleet Engine. While multiple service accounts can access the Fleet Engine for the same rideshare provider, Fleet Engine doesn't currently support service accounts from different Google Cloud Projects accessing the same vehicles.

  • The response returned from CreateVehicle() contains the Vehicle instance. The instance is deleted after seven days if it has not been updated using UpdateVehicle(). You should call GetVehicle() before calling CreateVehicle() just to confirm that the vehicle doesn't already exist. If GetVehicle() returns a NOT_FOUND error, then you should proceed with calling CreateVehicle(). For more information, see Vehicles and their lifecycle.

Example

The following provider code sample demonstrates how to create a vehicle in the 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;
}

To create a Vehicle that supports back-to-back trips, you must set the backToBackEnabled field in the Vehicle object passed to CreateVehicleRequest as true.

Vehicle vehicle = Vehicle.newBuilder()
    .setVehicleState(VehicleState.OFFLINE)
    .addSupportedTripTypes(TripType.EXCLUSIVE)
    .setMaximumCapacity(4)
    .setVehicleType(VehicleType.newBuilder().setCategory(VehicleType.Category.AUTO))
    .setBackToBackEnabled(true) // Set as 'true' so vehicle can be assigned back-to-back trips.
    .build();

Step 2. Enable location tracking

Location tracking refers to tracking the vehicle's location during the trip, where the driver app sends telemetry to the Fleet Engine, which contains the vehicles current location. This constantly updated stream of position information is used to convey the vehicle's progress along the trip's route. When you enable location tracking, the driver app starts sending this telemetry, at a default frequency of once every five seconds.

You enable location tracking for Android and iOS as follows:

Example

The following code example demonstrates how to enable location tracking.

Java

RidesharingVehicleReporter vehicleReporter = ...;

vehicleReporter.enableLocationTracking();

Swift

vehicleReporter.locationTrackingEnabled = true

Objective-C

_vehicleReporter.locationTrackingEnabled = YES;

Step 3. Set the vehicle's state to online

You bring a vehicle into service (that is, to make it available for use) by setting its state to online, but you cannot do this until after you have enabled location tracking.

You set the vehicle's state to online for Android and iOS as follows:

Example

The following code example demonstrates how to set the vehicle's state to ONLINE.

Java

vehicleReporter.setVehicleState(VehicleState.ONLINE);

Swift

vehicleReporter.update(.online)

Objective-C

[_vehicleReporter updateVehicleState:GMTDVehicleStateOnline];

Step 4. Create a trip in Fleet Engine

In order to create a shared-pool trip, you create a Trip object just like you would for a single-destination trip.

A trip is an object that represents a journey, which is a collection geocoordinate points, including origin, waypoints, and dropoff points. You must create one Trip object for each trip request so that the request can be matched to a vehicle and then tracked.

Supply required attributes

The following fields are required to create a shared-pool trip.

parent
A string that includes the provider ID. This must be the same as the project ID of the Google Cloud Project that contains the Service Accounts used for calling Fleet Engine
trip_id
A string that you create, that uniquely identifies this trip.
trip
Trip object to create.

This following fields need to be set in the Trip object passed to CreateTripRequest:

trip_type
TripType.SHARED
pickup_point
The trip's point of origin.
dropoff_point
The trip's dropoff point. This field is not required at trip creation and can be set later by calling UpdateTrip.

Example

The following backend integration sample demonstrates how to create a trip and automatically assign to a vehicle as shared-pool.

// Vehicle with VEHICLE_ID ID is already created and it is assigned Trip A.

static final String PROJECT_ID = "my-rideshare-co-gcp-project";
static final String TRIP_ID = "shared-trip-A";
static final String VEHICLE_ID = "your-vehicle-id";
static final String TRIP_A_ID = "trip-a-id";
static final String TRIP_B_ID = "trip-b-id";

TripServiceBlockingStub tripService = TripService.newBlockingStub(channel);

String parent = "providers/" + PROJECT_ID;

LatLng tripBPickup =
    LatLng.newBuilder().setLatitude(-12.12314).setLongitude(88.142123).build();
LatLng tripBDropoff =
    LatLng.newBuilder().setLatitude(-14.12314).setLongitude(90.142123).build();

TerminalLocation tripBPickupTerminalLocation =
    TerminalLocation.newBuilder().setPoint(tripBPickup).build();
TerminalLocation tripBDropoffTerminalLocation =
    TerminalLocation.newBuilder().setPoint(tripBDropoff).build();

// TripA already exists and it's assigned to a vehicle with VEHICLE_ID ID.
Trip tripB = Trip.newBuilder()
    .setTripType(TripType.SHARED)
    .setVehicleId(VEHICLE_ID)
    .setPickupPoint(tripBPickupTerminalLocation)
    .setDropoffPoint(tripBDropoffTerminalLocation)
    .addAllVehicleWaypoints(
        // This is where you define the arrival order for unvisited waypoints.
        // If you don’t specify an order, then the Fleet Engine adds Trip B’s
        // waypoints to the end of Trip A’s.
        ImmutableList.of(
            // Trip B’s pickup point.
            TripWaypoint.newBuilder()
                .setLocation(tripBPickupTerminalLocation)
                .setTripId(TRIP_B_ID)
                .setWaypointType(WaypointType.PICKUP_WAYPOINT_TYPE)
                .build(),
            // Trip A’s drop-off point.
            TripWaypoint.newBuilder()
                .setLocation(tripA.getDropoffPoint())
                .setTripId(TRIP_A_ID)
                .setWaypointType(WaypointType.DROP_OFF_WAYPOINT_TYPE)
                .build(),
            // Trip B’s drop-off point.
            TripWaypoint.newBuilder()
                .setLocation(tripBDropoffTerminalLocation)
                .setTripId(TRIP_B_ID)
                .setWaypointType(WaypointType.DROP_OFF_WAYPOINT_TYPE)
                .build()))
    .build();

// Create Trip request
CreateTripRequest createTripRequest = CreateTripRequest.newBuilder()
    .setParent(parent)
    .setTripId(TRIP_B_ID)
    .setTrip(tripB)
    .build();

try {
  // createdTrip.remainingWaypoints will contain shared-pool waypoints.
  // [tripB.pickup, tripA.dropoff, tripB.dropoff]
  Trip createdTrip = tripService.createTrip(createTripRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case ALREADY_EXISTS:
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}

Step 5. Update the trip with the vehicle ID and waypoints

You must configure the trip with a vehicle ID so that the Fleet Engine can track the vehicle along its route.

You must introduce an order to the unvisited waypoints in the trip's collection of vehicle waypoints (Trip.vehicle_waypoints). Fleet Engine uses this list to automatically update the trip waypoints for all trips in the shared-pool.

For example, consider two shared-pool trips: Trip A and Trip B. Trip A is enroute to its drop-off location. Then Trip B is added to the same vehicle. In one UpdateTripRequest for Trip B, you set the vehicleId, and also set Trip.vehicle_waypoints to the optimal waypoint order: B PickupA Drop-offB Drop-off.

  • Calling getVehicle() returns a list of remaining waypoints (remainingWaypoints) that contains
    B PickupA Drop-offB Drop-off.
  • Either getTrip() or the onTripRemainingWaypointsUpdated callback for Trip A returns a list of remaining waypoints (remainingWaypoints) that contains B PickupA Drop-off.
  • Either getTrip() or the onTripRemainingWaypointsUpdated callback for Trip B returns a list of remaining waypoints (remainingWaypoints) that contains B PickupA Drop-offB Drop-off.

Example

The following backend integration sample demonstrates how to update a trip with the vehicle ID and waypoints for two shared-pool trips.

static final String PROJECT_ID = "my-rideshare-co-gcp-project";
static final String TRIP_A_ID = "share-trip-A";
static final String TRIP_B_ID = "share-trip-B";
static final String VEHICLE_ID = "Vehicle";

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

// Get Trip A and Trip B objects from either the Fleet Engine or storage.
Trip tripA = …;
Trip tripB = …;

TripServiceBlockingStub tripService = TripService.newBlockingStub(channel);

// The trip settings to update.
Trip trip = Trip.newBuilder()
    .setVehicleId(VEHICLE_ID)
    .addAllVehicleWaypoints(
        // This is where you define the arrival order for unvisited waypoints.
        // If you don’t specify an order, then the Fleet Engine adds Trip B’s
        // waypoints to the end of Trip A’s.
        ImmutableList.of(
            // Trip B’s pickup point.
            TripWaypoint.newBuilder()
                .setLocation(tripB.getPickupPoint())
                .setTripId(TRIP_B_ID)
                .setWaypointType(WaypointType.PICKUP_WAYPOINT_TYPE)
                .build(),
            // Trip A’s drop-off point.
            TripWaypoint.newBuilder()
                .setLocation(tripA.getDropoffPoint())
                .setTripId(TRIP_A_ID)
                .setWaypointType(WaypointType.DROP_OFF_WAYPOINT_TYPE)
                .build(),
            // Trip B’s drop-off point.
            TripWaypoint.newBuilder()
                .setLocation(tripB.getDropoffPoint())
                .setTripId(TRIP_B_ID)
                .setWaypointType(WaypointType.DROP_OFF_WAYPOINT_TYPE)
                .build()))
    .build();

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

// Error handling. If Fleet Engine has both a trip and vehicle with the IDs,
// and if the credentials validate, and if the given vehicle_waypoints list
// is valid, 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:          // Either the trip or vehicle does not exist.
      break;
    case PERMISSION_DENIED:
      break;
    case INVALID_REQUEST:    // vehicle_waypoints is invalid.
      break;
  }
  return;
}

Step 6. Listen for trip updates in the consumer app

  • For Android, you can listen for data updates from a trip by obtaining a TripModel object from the TripModelManager and registering a TripModelCallback listener.

  • For iOS, you can listen for data updates from a trip by obtaining a GMTCTripModel object from the GMTCTripService and registering a GMTCTripModelSubscriber subscriber.

A TripModelCallback listener and GMTCTripModelSubscriber subscriber let your app receive periodic trip progress updates on each refresh based on the auto refresh interval. Only values that change can trigger the callback. Otherwise, the callback remains silent.

The TripModelCallback.onTripUpdated() and [GMTCTripModelSubscriber didUpdateTrip] methods are always called, regardless of any data changes.

Example 1

The following code sample demonstrates how to obtain a TripModel from TripModelManager/GMTCTripService and set a listener on it.

Java

// Start journey sharing after a trip has been created via the 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);

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

Example 2

The following code sample demonstrates how to set up a TripModelCallback listener and GMTCTripModelSubscriber subscriber.

Java

/**
 * Callback registered with {@link TripModel#registerTripCallback(LifecycleOwner, boolean,
 * TripModelCallback)} or {@link TripModel#registerTripCallback(TripModelCallback)}.
 *
 * Trip related data can be temporarily unavailable at scheduled callback due to factors such as
 * weak or lost mobile signal in the reporting vehicle. Value of the related field will be {@code
 * null} in that scenario. Please treat it accordingly and expect {@code nonnull} data at subsequent
 * callbacks.
 */
public abstract class TripModelCallback {

  /**
   * Called when the {@link TripStatus} is updated.
   *
   * @param tripInfo Current trip information.
   * @param status The current status of the trip.
   */
  public void onTripStatusUpdated(TripInfo tripInfo, @TripStatus int status) {}

  /**
   * Called when the route is updated.
   *
   * @param tripInfo Current trip information.
   * @param route Ordered list of {@link LatLng} representing the trip vehicle's route.
   */
  public void onTripActiveRouteUpdated(TripInfo tripInfo, List<LatLng> route) {}

  /**
   * Called when the trip's vehicle location is updated.
   *
   * @param tripInfo Current trip information.
   * @param vehicleLocation The trip vehicle's updated location information.
   */
  public void onTripVehicleLocationUpdated(
      TripInfo tripInfo, @Nullable VehicleLocation vehicleLocation) {}

  /**
   * Called when the trip's pickup location is updated.
   *
   * @param tripInfo Current trip information.
   * @param pickup {@link TerminalLocation} of the updated pickup location. {@code null} value means
   *     this data is temporarily unavailable at scheduled callback.
   */
  public void onTripPickupLocationUpdated(TripInfo tripInfo, @Nullable TerminalLocation pickup) {}

  /**
   * Called when the vehicle's arrival time or estimated arrival time at the pickup point is
   * updated. Before the vehicle arrives, it is an estimate; after, it is the actual arrival time.
   *
   * @param tripInfo Current trip information.
   * @param timestampMillis milliseconds of UTC time since Unix epoch. {@code null} value means this
   *     data is temporarily unavailable at scheduled callback.
   */
  public void onTripPickupUTimeUpdated(TripInfo tripInfo, @Nullable Long timestampMillis) {}

  /**
   * Called when the trip's dropoff location is updated.
   *
   * @param tripInfo Current trip information.
   * @param dropoff {@link TerminalLocation} of the updated dropoff location. {@code null} value
   *     means this data is temporarily unavailable at scheduled callback.
   */
  public void onTripDropoffLocationUpdated(TripInfo tripInfo, @Nullable TerminalLocation dropoff) {}

  /**
   * Called when the vehicle's arrival time or estimated arrival time at the dropoff point is
   * updated. Before the vehicle arrives, it is an estimate; after, it is the actual arrival time.
   *
   * @param tripInfo Current trip information.
   * @param timestampMillis milliseconds of UTC time since Unix epoch. {@code null} value means this
   *     data is temporarily unavailable at scheduled callback.
   */
  public void onTripDropoffTimeUpdated(TripInfo tripInfo, @Nullable Long timestampMillis) {}

  /**
   * Called when the estimated arrival time of the vehicle at the next waypoint (which may or may
   * not belong to the named trip) has changed.
   *
   * @param tripInfo Current trip information.
   * @param timestampMillis milliseconds of UTC time since Unix epoch. {@code null} value means this
   *     data is temporarily unavailable at scheduled callback.
   */
  public void onTripETAToNextWaypointUpdated(TripInfo tripInfo, @Nullable Long timestampMillis) {}

  /**
   * Called when the remaining distance of the active leg has changed. The active leg is the route
   * from the vehicle until the next waypoint belonging to the trip.
   *
   * @param tripInfo Current trip information.
   * @param distanceMeters The length of the remaining leg, in meters. {@code null} value means this
   *     data is temporarily unavailable at scheduled callback.
   */
  public void onTripActiveRouteRemainingDistanceUpdated(
      TripInfo tripInfo, @Nullable Integer distanceMeters) {}

  /**
   * Called when there is an error updating the trip state, typically due to a network connectivity
   * error.
   *
   * @param tripInfo Current trip information.
   * @param error The error.
   */
  public void onTripUpdateError(TripInfo tripInfo, TripUpdateError error) {}

  /**
   * Called when the scheduled update has been completed and the {@link TripModelCallback} callbacks
   * have been completed for any changed data. Called every time the trip is updated even if no data
   * has changed. The update interval can be modified in {@link
   * TripModel#setTripModelOptions(TripModelOptions)}.
   *
   * @param tripInfo Current trip information.
   */
  public void onTripUpdated(TripInfo tripInfo) {}

  /**
   * Called when the trip's list of remaining waypoints has changed.
   *
   * @param tripInfo Current trip information.
   * @param waypointList The updated list of remaining waypoints.
   */
  public void onTripRemainingWaypointsUpdated(TripInfo tripInfo, List<TripWaypoint> waypointList) {}

  /**
   * Called when the trip's list of intermediate destinations has changed.
   *
   * @param tripInfo Current trip information.
   * @param intermediateDestinations The updated list of intermediate destination locations.
   */
  public void onTripIntermediateDestinationsUpdated(
      TripInfo tripInfo, List<TerminalLocation> intermediateDestinations) {}

  /**
   * Called when the distance of the remaining route has changed.
   *
   * @param tripInfo Current trip information.
   * @param distanceMeters The length of the remaining leg, in meters. {@code null} value means this
   *     data is temporarily unavailable at scheduled callback.
   */
  public void onTripRemainingRouteDistanceUpdated(
      TripInfo tripInfo, @Nullable Integer distanceMeters) {}

  /**
   * Called when the remaining route has changed. For example, this may be triggered when the
   * remaining route traffic data has changed or when the remaining route waypoints have changed.
   *
   * @param tripInfo Current trip information.
   * @param route Ordered list of {@link LatLng} representing the trip vehicle's route.
   */
  public void onTripRemainingRouteUpdated(TripInfo tripInfo, List<LatLng> route) {}
}

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

You can access information for the trip any time as follows:

  • Call the Consumer SDK for Android method TripModel.getTripInfo(). Calling this method doesn't force a data refresh, although data still continues to be refreshed at the refresh frequency.

  • Get the Consumer SDK for iOS property GMTCTripModel.currentTrip.

Step 7. Display the journey in the consumer app

You can access the Rides and Deliveries user interface element APIs as follows:

Example

The following code example demonstrates how to start the journey sharing user interface.

Java

JourneySharingSession 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];

By default, the Consumer SDK displays just the active leg in the route, but you have the option of displaying the remaining leg, which includes the destination.

If you want to display information about waypoints from other trips, you can access all of the waypoints relevant to a trip as follows:

Step 8. Manage the trip state in the Fleet Engine

You specify the state of a trip using one of the TripStatus enumeration values. When a trip's state changes (for example, changing from ENROUTE_TO_PICKUP to ARRIVED_AT_PICKUP) you must update the trip state via the Fleet Engine. Trip state always begins with a value of NEW, and ends with a value of either COMPLETE or CANCELED. For more information, see trip_status.

Example

The following backend integration sample demonstrates how to update the trip state in the Fleet Engine.

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