Seguir uma viagem no iOS

Selecione a plataforma: Android iOS JavaScript

Quando você segue uma viagem, seu app para o consumidor exibe o local da veículo apropriado ao consumidor. Para fazer isso, seu app precisa iniciar acompanhar uma viagem, atualizar o andamento e parar de segui-la quando ela é concluída.

Este documento explica como esse processo funciona.

Começar a seguir uma viagem

Para começar a seguir uma viagem usando o compartilhamento de viagens:

  • Reunir todas as entradas do usuário, como locais de desembarque e embarque de um ViewController.

  • Crie um novo ViewController para iniciar o compartilhamento da jornada diretamente.

O exemplo a seguir mostra como começar a compartilhar uma jornada imediatamente após a é carregada.

Swift

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

Parar de seguir uma viagem

Você para de seguir uma viagem quando ela é concluída ou cancelada. O seguinte mostra como parar de compartilhar a viagem ativa.

Swift

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

Atualizar viagem

Durante uma viagem, você gerencia o andamento da seguinte forma:

Quando uma viagem for concluída ou cancelada, pare de detectar atualizações. Para conferir um exemplo, consulte Exemplo de parar de detectar atualizações.

Exemplo de como começar a detectar atualizações

O exemplo a seguir mostra como registrar o callback tripModel.

Swift

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

Exemplo de parar de detectar atualizações

O exemplo a seguir mostra como cancelar o registro do tripModel o retorno de chamada.

Swift

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

Objective-C

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

Exemplo de gerenciamento de atualizações de viagem

O exemplo abaixo mostra como implementar o GMTCTripModelSubscriber. para tratar callbacks quando o estado da viagem é atualizado.

Swift

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

Gerenciar erros de viagem

Se você assinou o tripModel e um erro ocorrer, será possível receber o callback de tripModel implementando o método delegado tripModel(_:didFailUpdateTripWithError:). Erro seguem o padrão Google Cloud Error. Para detalhes de erro definições de mensagens e todos os códigos de erro, consulte Documentação de erros do Google Cloud.

Confira alguns erros comuns que podem ocorrer durante o monitoramento da viagem:

HTTP RPC Descrição
400 INVALID_ARGUMENT O cliente especificou um nome de viagem inválido. O nome da viagem deve seguir o formato providers/{provider_id}/trips/{trip_id}. O provider_id precisa ser o ID do projeto do Cloud de propriedade de o provedor de serviços.
401 UNAUTHENTICATED Você vai receber esse erro se não houver credenciais de autenticação válidas. Por exemplo, se o token JWT for assinado sem um ID de viagem ou o token JWT expirou.
403 PERMISSION_DENIED Você vai receber esse erro se o cliente não tiver permissão suficiente (por exemplo, um usuário com o papel de consumidor tenta chamar updateTrip), se o token JWT é inválido ou a API não está ativada para o projeto do cliente. O token JWT pode estar ausente ou pode estar assinado com um ID de viagem que não corresponde ao ID da viagem solicitado.
429 RESOURCE_EXHAUSTED A cota de recursos está em zero ou a taxa de tráfego excede o limite.
503 INDISPONÍVEL Serviço indisponível. Geralmente, o servidor está desativado.
504 DEADLINE_EXCEEDED O prazo de solicitação foi excedido. Esse erro ocorre apenas se o autor da chamada definir um prazo mais curto que o prazo padrão do método (ou seja, o o prazo solicitado não for suficiente para o servidor processar a solicitação) e a solicitação não foi concluída dentro do prazo.

Processar erros do SDK do consumidor

O SDK para o consumidor envia erros de atualização de viagem ao aplicativo do consumidor usando um callback mecanismo de atenção. O parâmetro callback é um tipo de retorno específico da plataforma ( TripUpdateError no Android, e NSError no iOS).

Extrair códigos de status

Os erros transmitidos ao callback são normalmente erros gRPC, e também é possível extrair informações adicionais deles na forma de um código de status. Para o lista completa de códigos de status, consulte Códigos de status e o uso deles no gRPC (em inglês).

Swift

O NSError é chamado de volta no 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

O NSError é chamado de volta no 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;
    ...
  }
}

Interpretar códigos de status

Os códigos de status abrangem dois tipos de erros: erros relacionados ao servidor e à rede e erros do lado do cliente.

Erros de servidor e de rede

Os códigos de status a seguir são para erros de rede ou de servidor, e você e nenhuma ação será necessária para resolvê-los. O SDK do consumidor automaticamente se recupera delas.

Código de statusDescrição
ABORTED O servidor parou de enviar a resposta. Isso é normalmente causado por um um problema no servidor.
CANCELADO O servidor encerrou a resposta enviada. Isso normalmente acontece quando
o aplicativo é enviado para o segundo plano ou quando há uma mudança de estado na
App para o consumidor.
INTERRUPTED
DEADLINE_EXCEEDED O servidor demorou muito para responder.
INDISPONÍVEL O servidor não estava disponível. Isso geralmente é causado por uma conexão de rede problema.

Erros do cliente

Os códigos de status a seguir referem-se a erros do cliente, e você deve tomar medidas para e resolvê-los. O SDK para consumidores continuará tentando atualizar a viagem até que você encerrar o compartilhamento da jornada, mas ele não se recuperará até que você realize uma ação.

Código de statusDescrição
INVALID_ARGUMENT O aplicativo do consumidor especificou um nome de viagem inválido. O nome da viagem deve siga o formato providers/{provider_id}/trips/{trip_id}.
NOT_FOUND A viagem não foi criada.
PERMISSION_DENIED O app para o consumidor não tem permissões suficientes. Esse erro ocorre quando:
  • O app para o consumidor não tem permissões
  • O SDK do consumidor não está ativado para o projeto no Google Cloud do Cloud.
  • O token JWT está ausente ou é inválido.
  • O token JWT é assinado com um ID de viagem que não corresponde ao viagem solicitada.
RESOURCE_EXHAUSTED A cota de recursos está em zero ou a taxa do fluxo de tráfego excede a limite de velocidade.
UNAUTHENTICATED A autenticação da solicitação falhou devido a um token JWT inválido. Isso ocorre quando o token JWT é assinado sem um ID de viagem ou quando o token JWT tiver expirado.