Theo dõi chuyến đi trong iOS

Chọn nền tảng: Android iOS JavaScript

Khi bạn theo dõi một chuyến đi, ứng dụng dành cho người tiêu dùng của bạn sẽ hiển thị vị trí của phương tiện phù hợp cho người tiêu dùng. Để làm việc này, ứng dụng của bạn cần khởi động theo dõi một chuyến đi, cập nhật tiến trình của chuyến đi và ngừng theo dõi một chuyến đi khi hoàn tất.

Tài liệu này trình bày cách hoạt động của quy trình đó.

Bắt đầu theo dõi một chuyến đi

Sau đây là cách bạn bắt đầu theo dõi một chuyến đi bằng tính năng chia sẻ hành trình:

  • Thu thập tất cả thông tin đầu vào của người dùng, chẳng hạn như vị trí trả xe và đến lấy hàng từ ViewController.

  • Tạo một ViewController mới để trực tiếp bắt đầu chia sẻ hành trình.

Ví dụ sau đây cho biết cách bắt đầu chia sẻ một hành trình ngay sau lượt xem tải.

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

Dừng theo dõi một chuyến đi

Bạn ngừng theo dõi một chuyến đi khi chuyến đi đó đã kết thúc hoặc bị huỷ. Nội dung sau đây ví dụ cho biết cách dừng chia sẻ chuyến đi đang hoạt động.

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

Cập nhật tiến trình chuyến đi

Trong một chuyến đi, bạn quản lý tiến trình của chuyến đi như sau:

Khi một chuyến đi kết thúc hoặc bị huỷ, hãy ngừng nghe thông tin cập nhật. Để biết ví dụ, hãy xem Ví dụ về tính năng Dừng nghe để biết nội dung cập nhật.

Ví dụ về bắt đầu nghe để biết các bản cập nhật

Ví dụ sau đây cho thấy cách đăng ký lệnh gọi lại 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];
  ...
}

Ví dụ về dừng nghe để biết nội dung cập nhật

Ví dụ sau đây trình bày cách huỷ đăng ký tripModel .

Swift

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

Objective-C

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

Xử lý ví dụ về thông tin cập nhật chuyến đi

Ví dụ sau đây trình bày cách triển khai GMTCTripModelSubscriber giao thức để xử lý các lệnh gọi lại khi trạng thái chuyến đi được cập nhật.

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

Xử lý lỗi về chuyến đi

Nếu đã đăng ký tripModel và xảy ra lỗi, bạn có thể nhận lệnh gọi lại của tripModel bằng cách triển khai phương thức uỷ quyền tripModel(_:didFailUpdateTripWithError:). Lỗi các thông báo này tuân theo tiêu chuẩn Lỗi của Google Cloud. Để biết thông tin chi tiết về lỗi định nghĩa thông báo và tất cả mã lỗi, hãy tham khảo Tài liệu về Lỗi Google Cloud.

Dưới đây là một số lỗi phổ biến có thể xảy ra trong quá trình theo dõi chuyến đi:

HTTP RPC Mô tả
400 Hàm INVALID_ARGUMENT Khách hàng đã chỉ định tên chuyến đi không hợp lệ. Tên chuyến đi phải tuân theo providers/{provider_id}/trips/{trip_id}. Chiến lược phát hành đĩa đơn provider_id phải là mã nhận dạng của Dự án trên đám mây mà nhà cung cấp dịch vụ.
401 KHÔNG XÁC THỰC Bạn gặp lỗi này nếu không có thông tin xác thực hợp lệ. Ví dụ: nếu mã thông báo JWT được ký mà không có mã chuyến đi hoặc mã thông báo JWT đã hết hạn.
403 PERMISSION_DENIED Bạn gặp lỗi này nếu ứng dụng không có đủ quyền (ví dụ: một người dùng với vai trò người tiêu dùng cố gắng gọi updateTrip), nếu mã thông báo JWT không hợp lệ hoặc API chưa được bật cho dự án ứng dụng. Có thể thiếu mã thông báo JWT hoặc mã thông báo này đã được ký bằng mã chuyến đi không khớp với mã chuyến đi đã yêu cầu.
429 RESOURCE_EXHAUSTED Hạn mức tài nguyên bằng 0 hoặc tốc độ lưu lượng truy cập vượt quá hạn mức.
503 KHÔNG CÓ Dịch vụ hiện không hoạt động. Thông thường, máy chủ không hoạt động.
504 DEADLINE_EXCEEDED Đã vượt quá thời hạn yêu cầu. Lỗi này chỉ xảy ra nếu phương thức gọi đặt thời hạn ngắn hơn thời hạn mặc định của phương pháp (nghĩa là thời hạn thời hạn yêu cầu là không đủ để máy chủ xử lý yêu cầu) và yêu cầu không hoàn tất trong thời hạn.

Xử lý lỗi SDK của người tiêu dùng

SDK người tiêu dùng gửi lỗi cập nhật chuyến đi cho ứng dụng dành cho người tiêu dùng bằng lệnh gọi lại cơ chế. Tham số gọi lại là kiểu dữ liệu trả về dành riêng cho từng nền tảng ( TripUpdateError trên Android và NSError trên iOS).

Trích xuất mã trạng thái

Lỗi được chuyển đến lệnh gọi lại thường là lỗi gRPC và bạn cũng có thể trích xuất thông tin bổ sung từ các URL đó dưới dạng mã trạng thái. Đối với danh sách đầy đủ các mã trạng thái, xem Mã trạng thái và cách sử dụng chúng trong gRPC.

Swift

NSError được gọi lại trong 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 được gọi lại trong 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;
    ...
  }
}

Diễn giải mã trạng thái

Mã trạng thái bao gồm hai loại lỗi: lỗi liên quan đến máy chủ và lỗi mạng, và lỗi phía máy khách.

Lỗi máy chủ và mạng

Các mã trạng thái sau đây là cho lỗi mạng hoặc lỗi máy chủ và bạn không cần làm gì để giải quyết chúng. SDK người tiêu dùng tự động phục hồi từ họ.

Mã trạng tháiMô tả
ĐÃ THANH TOÁN Máy chủ đã ngừng gửi phản hồi. Điều này thường là do lỗi sự cố máy chủ.
ĐÃ HỦY Máy chủ đã chấm dứt phản hồi gửi đi. Thông thường xảy ra khi
ứng dụng được chuyển sang chạy ở chế độ nền hoặc khi có sự thay đổi về trạng thái trong
Ứng dụng dành cho người tiêu dùng.
INTERRUPTED
DEADLINE_EXCEEDED Máy chủ mất quá nhiều thời gian để phản hồi.
KHÔNG CÓ Máy chủ không khả dụng. Điều này thường là do mạng vấn đề.

Lỗi ứng dụng

Các mã trạng thái sau đây là dành cho các lỗi ứng dụng và bạn phải hành động để hãy giải quyết chúng. SDK người tiêu dùng sẽ tiếp tục thử lại để làm mới chuyến đi cho đến khi bạn kết thúc chia sẻ hành trình, nhưng tiện ích này sẽ không khôi phục cho đến khi bạn hành động.

Mã trạng tháiMô tả
Hàm INVALID_ARGUMENT Ứng dụng Người tiêu dùng đã chỉ định tên chuyến đi không hợp lệ; Tên chuyến đi phải sẽ tuân theo định dạng providers/{provider_id}/trips/{trip_id}.
NOT_FOUND Chuyến đi chưa được tạo.
PERMISSION_DENIED Ứng dụng Người tiêu dùng không có đủ quyền. Lỗi này xảy ra khi:
  • Ứng dụng Người tiêu dùng không có quyền
  • Bạn chưa bật SDK người tiêu dùng cho dự án trong Google Cloud Bảng điều khiển.
  • Mã thông báo JWT bị thiếu hoặc không hợp lệ.
  • Mã thông báo JWT được ký bằng mã chuyến đi không khớp với chuyến đi đã yêu cầu.
RESOURCE_EXHAUSTED Hạn mức tài nguyên bằng 0 hoặc tốc độ lưu lượng truy cập vượt quá giới hạn tốc độ.
KHÔNG XÁC THỰC Không xác thực được yêu cầu do mã thông báo JWT không hợp lệ. Chiến dịch này lỗi xảy ra khi mã thông báo JWT được ký mà không có mã chuyến đi, hoặc khi mã thông báo JWT đã hết hạn.