Suivre un trajet dans iOS

Sélectionnez une plate-forme : Android iOS JavaScript

Lorsque vous suivez un trajet, votre application grand public affiche l'emplacement du véhicule approprié. Pour ce faire, votre application doit commencer à suivre un trajet, mettre à jour la progression du trajet et arrêter de suivre un trajet lorsqu'il est terminé.

Ce document décrit le fonctionnement de ce processus.

Suivre un trajet

Pour suivre un trajet :

  • Rassemblez toutes les entrées utilisateur, telles que les lieux de dépôt et de prise en charge, à partir d'un ViewController.

  • Créez un ViewController pour commencer à suivre un trajet directement.

L'exemple suivant montre comment commencer à suivre un trajet immédiatement après le chargement de la vue.

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

Ne plus suivre un trajet

Vous arrêtez de suivre un trajet lorsqu'il est terminé ou annulé. L'exemple suivant montre comment arrêter de partager le trajet en cours.

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

Mettre à jour la progression

Pendant un trajet, vous gérez la progression du trajet comme suit:

Lorsqu'un trajet se termine ou est annulé, arrêtez d'écouter les mises à jour. Pour obtenir un exemple, consultez la section Exemple d'arrêt de l'écoute des mises à jour.

Exemple de démarrage de l'écoute des mises à jour

L'exemple suivant montre comment enregistrer le rappel 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];
  ...
}

Exemple d'arrêt de l'écoute d'informations

L'exemple suivant montre comment annuler l'enregistrement du rappel tripModel.

Swift

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

Objective-C

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

Exemple de gestion des mises à jour de trajets

L'exemple suivant montre comment implémenter le protocole GMTCTripModelSubscriber pour gérer les rappels lorsque l'état du trajet est mis à jour.

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

Gérer les erreurs de trajet

Si vous vous êtes abonné à tripModel et qu'une erreur se produit, vous pouvez obtenir le rappel de tripModel en implémentant la méthode déléguée tripModel(_:didFailUpdateTripWithError:). Les messages d'erreur suivent la norme Google Cloud. Pour obtenir des définitions détaillées des messages d'erreur et de tous les codes d'erreur, consultez la documentation sur les erreurs Google Cloud.

Voici quelques erreurs courantes qui peuvent se produire lors de la surveillance des trajets :

HTTP RPC Description
400 INVALID_ARGUMENT Le client a spécifié un nom de trajet non valide. Le nom du trajet doit respecter le format providers/{provider_id}/trips/{trip_id}. provider_id doit correspondre à l'ID du projet Cloud appartenant au fournisseur de services.
401 UNAUTHENTICATED Ce message d'erreur s'affiche si aucun identifiant d'authentification n'est valide. C'est le cas, par exemple, si le jeton JWT est signé sans ID de trajet ou si le jeton JWT a expiré.
403 PERMISSION_DENIED Vous recevez cette erreur si le client ne dispose pas des autorisations suffisantes (par exemple, un utilisateur doté du rôle client tente d'appeler updateTrip), si le jeton JWT n'est pas valide ou si l'API n'est pas activée pour le projet client. Le jeton JWT est peut-être manquant ou il est signé avec un ID de trajet qui ne correspond pas à l'ID de trajet demandé.
429 RESOURCE_EXHAUSTED Le quota de ressources est égal à zéro ou le taux de trafic dépasse la limite.
503 UNAVAILABLE Service indisponible. Généralement, le serveur est inactif.
504 DEADLINE_EXCEEDED Délai de requête dépassé. Cette erreur ne se produit que si l'appelant définit un délai plus court que le délai par défaut de la méthode (le délai demandé ne suffit pas pour que le serveur traite la demande) et si la requête ne s'est pas terminée dans le délai.

Gérer les erreurs du SDK client

Le SDK Consumer envoie des erreurs de mise à jour de trajet à l'application grand public à l'aide d'un mécanisme de rappel. Le paramètre de rappel est un type de retour spécifique à la plate-forme (TripUpdateError sur Android et NSError sur iOS).

Extraire les codes d'état

Les erreurs transmises au rappel sont généralement des erreurs gRPC. Vous pouvez également en extraire des informations supplémentaires sous la forme d'un code d'état. Pour obtenir la liste complète des codes d'état, consultez la section Codes d'état et utilisation dans gRPC.

Swift

Le NSError est rappelé dans 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

Le NSError est rappelé dans 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;
    ...
  }
}

Interpréter les codes d'état

Les codes d'état couvrent deux types d'erreurs : les erreurs liées au serveur et au réseau, et les erreurs côté client.

Erreurs de serveur et de réseau

Les codes d'état suivants concernent des erreurs de réseau ou de serveur. Aucune action n'est requise de votre part pour les résoudre. Le SDK grand public les récupère automatiquement.

Code d'étatDescription
ABORTED Le serveur a cessé d'envoyer la réponse. Cela est généralement dû à un problème de serveur.
ANNULÉ Le serveur a interrompu la réponse sortante. Cela se produit normalement lorsque
l'application est envoyée en arrière-plan ou en cas de changement d'état dans l'application consommateur
.
INTERRUPTED
DEADLINE_EXCEEDED Le serveur a mis trop de temps à répondre.
UNAVAILABLE Le serveur n'était pas disponible. Ce problème est généralement dû à un problème réseau.

Erreurs client

Les codes d'état suivants correspondent à des erreurs client. Vous devez prendre des mesures pour les résoudre. Le SDK grand public continue de réessayer d'actualiser le trajet jusqu'à ce que vous mettiez fin au partage du trajet, mais il ne récupérera pas tant que vous n'aurez pas pris les mesures nécessaires.

Code d'étatDescription
INVALID_ARGUMENT L'application grand public a spécifié un nom de trajet non valide. Le nom du trajet doit respecter le format providers/{provider_id}/trips/{trip_id}.
NOT_FOUND Le voyage n'a jamais été créé.
PERMISSION_DENIED L'application grand public ne dispose pas d'autorisations suffisantes. Cette erreur se produit dans les cas suivants :
  • L'application grand public ne dispose pas d'autorisations
  • Le SDK client n'est pas activé pour le projet dans la console Google Cloud.
  • Le jeton JWT est manquant ou non valide.
  • Le jeton JWT est signé avec un ID de trajet qui ne correspond pas au trajet demandé.
RESOURCE_EXHAUSTED Le quota de ressources est nul ou le débit de trafic dépasse la limite de vitesse.
UNAUTHENTICATED L'authentification de la requête a échoué en raison d'un jeton JWT non valide. Cette erreur se produit soit lorsque le jeton JWT est signé sans ID de trajet, soit lorsque le jeton JWT a expiré.