Следите за путешествием в 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 Errors. Подробные определения сообщений об ошибках и все коды ошибок см. в документации Google Cloud Errors .

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

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

Обработка ошибок потребительского SDK

SDK для потребителей отправляет ошибки обновления поездки в приложение потребителя с помощью механизма обратного вызова. Параметр обратного вызова имеет тип возвращаемого значения, специфичный для платформы ( 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;
    ...
  }
}

Интерпретация кодов состояния

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

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

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

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

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

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

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