공유 수영장 여행 만들기 및 표시하기

공유 수영장 이동은 여러 소비자가 동시에 차량을 공유하는 공유 이동입니다. 즉, 해당 이동은 독립적이지 않고 동시적입니다. 작동 방식은 공항 셔틀버스의 작동 방식과 유사하지만 운전자가 경로 중에 소비자를 하차할 수도 있다는 점이 다릅니다.

공용 수영장 이동과 단일 목적지 이동의 주요 차이점은 공용 수영장 이동에서는 이동 운영자가 동시에 둘 이상의 승객을 수송할 수 있다는 점입니다.

이 튜토리얼에서는 공유 수영장 여행을 만드는 과정을 안내합니다. 또한 고객이 휴대전화에서 이동 진행 상황을 시각화할 수 있도록 해당 이동을 소비자 애플리케이션과 통합하는 방법도 보여줍니다. 이 통합은 Consumer SDK를 사용하여 수행합니다.

1단계: Fleet Engine에서 차량 만들기

차량은 Fleet의 차량을 나타내는 객체입니다. 소비자 앱에서 이벤트를 추적하려면 Fleet Engine에서 객체를 만들어야 합니다.

다음 두 가지 접근 방식 중 하나를 사용하여 차량을 만들 수 있습니다.

gRPC
CreateVehicleRequest 요청 메시지와 함께 CreateVehicle() 메서드를 호출합니다. CreateVehicle()을(를) 호출하려면 Fleet Engine 수퍼유저 권한이 있어야 합니다.
REST
https://fleetengine.googleapis.com/v1/providers.vehicles.create에 전화 걸기

주의사항

차량을 만들 때는 다음 주의사항이 적용됩니다.

  • 초기 차량 상태를 OFFLINE로 설정해야 합니다. 이렇게 하면 Fleet Engine이 이동에 맞는 차량을 찾을 수 있습니다.

  • 차량의 provider_id는 Fleet Engine을 호출하는 데 사용되는 서비스 계정이 포함된 Google Cloud 프로젝트의 프로젝트 ID와 동일해야 합니다. 여러 서비스 계정이 동일한 차량 공유 제공업체의 Fleet Engine에 액세스할 수 있지만 현재 Fleet Engine은 동일한 차량에 액세스하는 여러 Google Cloud 프로젝트의 서비스 계정을 지원하지 않습니다.

  • CreateVehicle()에서 반환된 응답에는 Vehicle 인스턴스가 포함됩니다. UpdateVehicle()를 사용하여 업데이트되지 않은 인스턴스는 7일 후에 삭제됩니다. 차량이 이미 존재하지 않는지 확인하기 위해 CreateVehicle()를 호출하기 전에 GetVehicle()를 호출해야 합니다. GetVehicle()NOT_FOUND 오류를 반환하면 CreateVehicle() 호출을 진행해야 합니다. 자세한 내용은 차량 및 차량 수명 주기를 참고하세요.

다음 제공업체 코드 샘플은 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;
}

공유 풀 이동을 지원하는 Vehicle를 만들려면 CreateVehicleRequest에 전달된 Vehicle 객체의 지원되는 이동 유형 목록에 TripType.SHARED를 추가해야 합니다.

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

2단계: 위치 추적 사용 설정

위치 추적은 이동 중에 차량의 위치를 추적하는 것을 의미하며 여기서 운전자 앱이 차량의 현재 위치가 포함된 Fleet Engine으로 원격 분석을 전송합니다. 위치 정보에서 지속적으로 업데이트되는 이 스트림은 이동 경로를 따라 차량의 진행 상황을 전달하는 데 사용됩니다. 위치 추적을 사용 설정하면 드라이버 앱이 기본 빈도인 5초마다 한 번씩 이 원격 분석 데이터를 전송하기 시작합니다.

Android 및 iOS에서 위치 추적을 사용 설정하는 방법은 다음과 같습니다.

다음 코드 예에서는 위치 추적을 사용 설정하는 방법을 보여줍니다.

Java

RidesharingVehicleReporter vehicleReporter = ...;

vehicleReporter.enableLocationTracking();

Kotlin

val vehicleReporter = ...

vehicleReporter.enableLocationTracking()

Swift

vehicleReporter.locationTrackingEnabled = true

Objective-C

_vehicleReporter.locationTrackingEnabled = YES;

3단계: 차량 상태를 온라인으로 설정

차량의 상태를 온라인으로 설정하여 (즉, 차량을 사용할 수 있도록 하기 위해) 차량을 가동하지만 위치 추적을 사용 설정하기 전에는 차량을 사용할 수 없습니다.

Android 및 iOS의 경우 다음과 같이 차량 상태를 온라인으로 설정합니다.

다음 코드 예는 차량 상태를 ONLINE로 설정하는 방법을 보여줍니다.

Java

vehicleReporter.setVehicleState(VehicleState.ONLINE);

Kotlin

vehicleReporter.setVehicleState(VehicleState.ONLINE)

Swift

vehicleReporter.update(.online)

Objective-C

[_vehicleReporter updateVehicleState:GMTDVehicleStateOnline];

4단계: Fleet Engine에서 이동 만들기

공용 수영장 이동을 만들려면 단일 목적지 이동과 마찬가지로 Trip 객체를 만듭니다.

이동은 출발지, 경유지, 하차 지점을 포함하는 지리 좌표 지점인 여정을 나타내는 객체입니다. 요청을 차량과 일치시킨 다음 추적할 수 있도록 각 이동 요청에 대해 하나의 Trip 객체를 만들어야 합니다.

필수 속성 제공

공유 수영장 여행을 만들려면 다음 필드가 필요합니다.

parent
공급업체 ID가 포함된 문자열입니다. Fleet Engine을 호출하는 데 사용되는 서비스 계정이 포함된 Google Cloud 프로젝트의 프로젝트 ID와 동일해야 합니다.
trip_id
이 여정을 고유하게 식별하는, 만드는 문자열입니다.
trip
생성할 Trip 객체입니다.

다음 필드는 CreateTripRequest에 전달된 Trip 객체에서 설정해야 합니다.

trip_type
TripType.SHARED
pickup_point
여행의 출발지입니다.
dropoff_point
경로의 하차 지점입니다. 이 필드는 경로를 만들 때 필요하지 않으며 나중에 UpdateTrip를 호출하여 설정할 수 있습니다.

다음 백엔드 통합 샘플은 경로를 만들고 차량에 공유 풀로 자동으로 할당하는 방법을 보여줍니다.

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

5단계: 차량 ID 및 경유지로 이동 업데이트

Fleet Engine이 경로를 따라 차량을 추적할 수 있도록 차량 ID로 이동을 구성해야 합니다.

  • UpdateTripRequestUpdateTrip 엔드포인트를 호출하여 차량 ID로 이동을 업데이트할 수 있습니다. update_mask 필드를 사용하여 차량 ID를 업데이트한다고 지정합니다.

경로의 차량 경유지 모음 (Trip.vehicle_waypoints)에서 방문하지 않은 경유지를 대상으로 순서를 도입해야 합니다. Fleet Engine은 이 목록을 사용하여 공유 풀에 있는 모든 이동의 이동 경유지를 자동으로 업데이트합니다.

예를 들어 공유 수영장 이동 두 개(이동 A이동 B)가 있다고 가정해 보겠습니다. 이동 A가 하차 위치로 이동 중입니다. 그런 다음 이동경로 B가 동일한 차량에 추가됩니다. 이동 B에 대한 하나의 UpdateTripRequest에서 vehicleId를 설정하고 Trip.vehicle_waypoints을 최적의 경유지 순서(B 수령A 하차B 하차)로 설정합니다.

  • getVehicle()를 호출하면
    B PickupA Drop-offB Drop-off를 포함하는 남은 경유지(remainingWaypoints) 목록이 반환됩니다.
  • 경로 AgetTrip() 또는 onTripRemainingWaypointsUpdated 콜백은 B 픽업A 하차를 포함하는 남은 경유지(remainingWaypoints) 목록을 반환합니다.
  • 이동 B에 대한 getTrip() 또는 onTripRemainingWaypointsUpdated 콜백은 B 수령A 하차B 하차를 포함하는 남은 경유지(remainingWaypoints) 목록을 반환합니다.

다음 백엔드 통합 샘플은 2개의 공유 풀 이동에 대해 차량 ID 및 경유지로 이동을 업데이트하는 방법을 보여줍니다.

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

6단계: 소비자 앱에서 경로 업데이트 수신 대기

  • Android의 경우 TripModelManager에서 TripModel 객체를 가져오고 TripModelCallback 리스너를 등록하여 경로의 데이터 업데이트를 수신 대기할 수 있습니다.

  • iOS의 경우 GMTCTripService에서 GMTCTripModel 객체를 가져오고 GMTCTripModelSubscriber 구독자를 등록하여 경로의 데이터 업데이트를 수신 대기할 수 있습니다.

TripModelCallback 리스너와 GMTCTripModelSubscriber 구독자를 사용하면 앱이 자동 새로고침 간격에 따라 새로고침할 때마다 정기적인 이동 진행률 업데이트를 수신할 수 있습니다. 변경되는 값만 콜백을 트리거할 수 있습니다. 그러지 않으면 콜백이 무음으로 유지됩니다.

TripModelCallback.onTripUpdated()tripModel(_:didUpdate:updatedPropertyFields:) 메서드는 데이터 변경사항에 관계없이 항상 호출됩니다.

예시 1

다음 코드 샘플은 TripModelManager/GMTCTripService에서 TripModel를 가져와서 리스너를 설정하는 방법을 보여줍니다.

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

예 2

다음 코드 샘플은 TripModelCallback 리스너와 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

언제든지 다음과 같이 이동 정보에 액세스할 수 있습니다.

  • Android용 Consumer SDK 메서드 TripModel.getTripInfo()를 호출합니다. 이 메서드를 호출해도 데이터를 새로고침 빈도로 계속 새로고침할 수는 있지만 강제로 데이터를 새로고침하지는 않습니다.

  • iOS용 Consumer SDK 속성 GMTCTripModel.currentTrip을 가져옵니다.

7단계: 소비자 앱에 여정 표시

다음과 같이 차량 및 배송 사용자 인터페이스 요소 API에 액세스할 수 있습니다.

다음 코드 예는 여정 공유 사용자 인터페이스를 시작하는 방법을 보여줍니다.

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

기본적으로 소비자 SDK는 경로의 활성 구간만 표시하지만 목적지를 포함하는 나머지 구간을 표시할 수도 있습니다.

다른 경로의 경유지 정보를 표시하려면 다음과 같이 이동과 관련된 모든 경유지에 액세스하면 됩니다.

8단계: Fleet Engine에서 이동 상태 관리

TripStatus 열거형 값 중 하나를 사용하여 이동 상태를 지정합니다. 이동 상태가 변경되면 (예: ENROUTE_TO_PICKUP에서 ARRIVED_AT_PICKUP로 변경) Fleet Engine을 통해 이동 상태를 업데이트해야 합니다. 이동 상태는 항상 NEW 값으로 시작하고 COMPLETE 또는 CANCELED 값으로 끝납니다. 자세한 내용은 trip_status를 참고하세요.

다음 백엔드 통합 샘플은 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;
}