Следите за путешествием в iOS

Выберите платформу: Android iOS JavaScript

Когда вы отслеживаете поездку, ваше приложение отображает потребителю местоположение соответствующего транспортного средства. Для этого приложению необходимо начать отслеживать поездку, обновить ход поездки и прекратить отслеживать поездку после её завершения.

В этом документе описывается, как работает этот процесс.

Начать следить за поездкой

Вот как можно начать следить за поездкой:

  • Собирайте все пользовательские данные, такие как места высадки и посадки, из ViewController .

  • Создайте новый ViewController , чтобы начать отслеживать поездку напрямую.

В следующем примере показано, как начать отслеживать поездку сразу после загрузки представления.

Быстрый

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

Остановить отслеживание поездки

Вы прекращаете отслеживать поездку, когда она завершена или отменена. В следующем примере показано, как прекратить публикацию активной поездки.

Быстрый

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

Обновить ход поездки

Во время поездки вы управляете ходом поездки следующим образом:

Когда поездка завершена или отменена, прекратите прослушивание обновлений . Пример см. в разделе «Пример прекращения прослушивания обновлений» .

Пример начала прослушивания обновлений

В следующем примере показано, как зарегистрировать обратный вызов tripModel .

Быстрый

/*
 * 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];
  ...
}

Пример прекращения прослушивания обновлений

В следующем примере показано, как отменить регистрацию обратного вызова tripModel .

Быстрый

/*
 * MapViewController.swift
 */
deinit {
  self.currentTripModel.unregisterSubscriber(self)
}

Objective-C

/*
 * MapViewController.m
 */
- (void)dealloc {
  [self.currentTripModel unregisterSubscriber:self];
  ...
}

Пример обработки обновлений поездки

В следующем примере показано, как реализовать протокол GMTCTripModelSubscriber для обработки обратных вызовов при обновлении состояния поездки.

Быстрый

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

Обработка ошибок поездки

Если вы подписались на tripModel и произошла ошибка, вы можете получить обратный вызов tripModel , реализовав метод делегата tripModel(_:didFailUpdateTripWithError:) . Сообщения об ошибках соответствуют стандарту Google Cloud Error. Подробные определения сообщений об ошибках и все коды ошибок см. в документации Google Cloud Errors .

Вот некоторые распространенные ошибки, которые могут возникнуть при мониторинге поездки:

HTTP RPC Описание
400 НЕВЕРНЫЙ_АРГУМЕНТ Клиент указал недопустимое название поездки. Название поездки должно иметь формат providers/{provider_id}/trips/{trip_id} . В качестве provider_id должен быть указан идентификатор облачного проекта, принадлежащего поставщику услуг.
401 НЕ ПОДТВЕРЖДЕНО Эта ошибка возникает, если отсутствуют действительные учётные данные аутентификации. Например, если токен JWT подписан без идентификатора поездки или срок действия токена JWT истёк.
403 ДОСТУП ЗАПРЕЩЕН Эта ошибка возникает, если у клиента недостаточно прав (например, пользователь с ролью потребителя пытается вызвать updateTrip), если токен JWT недействителен или API не включен для клиентского проекта. Возможно, токен JWT отсутствует или токен подписан идентификатором поездки, не соответствующим запрошенному идентификатору поездки.
429 RESOURCE_EXHAUSTED Квота ресурсов равна нулю или скорость трафика превышает лимит.
503 НЕДОСТУПНО Сервис недоступен. Обычно сервер не работает.
504 DEADLINE_EXCEEDED Превышен срок выполнения запроса. Эта ошибка возникает только в том случае, если вызывающий объект устанавливает срок, который короче срока выполнения метода по умолчанию (то есть запрошенного срока недостаточно для обработки запроса сервером), и запрос не был завершён в установленный срок.

Обработка ошибок Consumer SDK

Consumer SDK отправляет ошибки обновления данных о поездках в приложение Consumer с помощью механизма обратного вызова. Параметр обратного вызова имеет тип возвращаемого значения, зависящий от платформы ( TripUpdateError на Android и NSError на iOS).

Извлечь коды статуса

Ошибки, передаваемые в функцию обратного вызова, обычно являются ошибками gRPC, и вы также можете извлечь из них дополнительную информацию в виде кода состояния. Полный список кодов состояния см. в разделе Коды состояния и их использование в gRPC .

Быстрый

NSError вызывается обратно в 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

NSError вызывается обратно в 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;
    ...
  }
}

Интерпретировать коды статуса

Коды состояния охватывают два вида ошибок: ошибки, связанные с сервером и сетью, и ошибки на стороне клиента.

Ошибки сервера и сети

Следующие коды состояния соответствуют ошибкам сети или сервера, и вам не нужно предпринимать никаких действий для их устранения. Consumer SDK автоматически устраняет их.

Код статуса Описание
ПРЕРВАНО Сервер перестал отправлять ответ. Обычно это вызвано проблемами на сервере.
ОТМЕНЕНО Сервер прервал исходящий ответ. Обычно это происходит, когда
приложение отправляется в фоновый режим или когда происходит изменение состояния
Потребительское приложение.
ПРЕРВАН
DEADLINE_EXCEEDED Сервер слишком долго не отвечал.
НЕДОСТУПНО Сервер был недоступен. Обычно это происходит из-за проблем с сетью.

Ошибки клиента

Следующие коды состояния относятся к ошибкам клиента, и вам необходимо принять меры для их устранения. Consumer SDK продолжит попытки обновить данные о поездке, пока вы не завершите обмен данными о поездке, но не восстановится, пока вы не примете меры.

Код статуса Описание
НЕВЕРНЫЙ_АРГУМЕНТ Приложение Consumer указало недопустимое название поездки. Название поездки должно иметь формат providers/{provider_id}/trips/{trip_id} .
НЕ НАЙДЕНО Поездка так и не была реализована.
ДОСТУП ЗАПРЕЩЕН У приложения Consumer недостаточно прав. Эта ошибка возникает, когда:
  • Приложение Consumer не имеет разрешений
  • Consumer SDK не включен для проекта в Google Cloud Console.
  • Токен JWT отсутствует или недействителен.
  • Токен JWT подписан идентификатором поездки, который не соответствует запрошенной поездке.
RESOURCE_EXHAUSTED Квота ресурсов равна нулю, или скорость транспортного потока превышает ограничение скорости.
НЕ ПОДТВЕРЖДЕНО Запрос не прошёл аутентификацию из-за недействительного токена JWT. Эта ошибка возникает, если токен JWT подписан без идентификатора поездки или если срок действия токена JWT истёк.