یک سفر را در iOS دنبال کنید

پلتفرم مورد نظر را انتخاب کنید: اندروید، iOS، جاوا اسکریپت

وقتی شما یک سفر را دنبال می‌کنید، برنامه‌ی مصرف‌کننده‌ی شما موقعیت مکانی وسیله‌ی نقلیه‌ی مناسب را به مصرف‌کننده نمایش می‌دهد. برای انجام این کار، برنامه‌ی شما باید شروع به دنبال کردن یک سفر کند، پیشرفت سفر را به‌روزرسانی کند و پس از اتمام سفر، دنبال کردن آن را متوقف کند.

این سند نحوه عملکرد آن فرآیند را پوشش می‌دهد.

شروع به دنبال کردن یک سفر کنید

در اینجا نحوه شروع پیگیری یک سفر آورده شده است:

  • تمام ورودی‌های کاربر مانند مکان‌های تحویل و برداشت را از یک 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()
}

هدف-سی

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

هدف-سی

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

به‌روزرسانی پیشرفت سفر

در طول یک سفر، شما پیشرفت سفر را به شرح زیر مدیریت می‌کنید:

وقتی سفری تمام می‌شود یا لغو می‌شود، دیگر به به‌روزرسانی‌ها گوش ندهید . برای مثال، به مثال «توقف گوش دادن به به‌روزرسانی‌ها» مراجعه کنید.

شروع به گوش دادن به مثال‌های به‌روزرسانی کنید

مثال زیر نحوه ثبت callback tripModel را نشان می‌دهد.

سویفت

/*
 * MapViewController.swift
 */
override func viewDidLoad() {
  super.viewDidLoad()
  // Register for trip update events.
  self.currentTripModel.register(self)
}

هدف-سی

/*
 * MapViewController.m
 */
- (void)viewDidLoad {
  [super viewDidLoad];
  // Register for trip update events.
  [self.currentTripModel registerSubscriber:self];
  ...
}

مثال توقف گوش دادن به به‌روزرسانی‌ها

مثال زیر نحوه لغو ثبت callback مربوط به tripModel را نشان می‌دهد.

سویفت

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

هدف-سی

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

هدف-سی

/*
 * 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 ثبت کرده‌اید و خطایی رخ می‌دهد، می‌توانید با پیاده‌سازی متد delegate به نام tripModel(_:didFailUpdateTripWithError:) فراخوانی tripModel را دریافت کنید. پیام‌های خطا از استاندارد خطای Google Cloud پیروی می‌کنند. برای تعاریف دقیق پیام‌های خطا و تمام کدهای خطا، به مستندات خطاهای Google Cloud مراجعه کنید.

در اینجا به برخی از خطاهای رایجی که ممکن است هنگام نظارت بر سفر رخ دهد، اشاره می‌کنیم:

اچ‌تی‌پی آر پی سی توضیحات
۴۰۰ آرگومان نامعتبر مشتری نام سفر نامعتبری را مشخص کرده است. نام سفر باید از قالب providers/{provider_id}/trips/{trip_id} پیروی کند. provider_id باید شناسه پروژه ابری متعلق به ارائه دهنده خدمات باشد.
۴۰۱ احراز هویت نشده اگر هیچ اعتبارنامه‌ی احراز هویت معتبری وجود نداشته باشد، این خطا را دریافت می‌کنید. برای مثال، اگر توکن JWT بدون شناسه‌ی سفر امضا شده باشد یا توکن JWT منقضی شده باشد.
۴۰۳ مجوز_رد_شد اگر کلاینت مجوز کافی نداشته باشد (برای مثال، کاربری با نقش مصرف‌کننده سعی کند updateTrip را فراخوانی کند)، اگر توکن JWT نامعتبر باشد، یا API برای پروژه کلاینت فعال نباشد، این خطا را دریافت می‌کنید. ممکن است توکن JWT وجود نداشته باشد یا توکن با شناسه سفری امضا شده باشد که با شناسه سفر درخواستی مطابقت ندارد.
۴۲۹ منابع_تمام_شده سهمیه منابع صفر است یا نرخ ترافیک از حد مجاز فراتر رفته است.
۵۰۳ غیرقابل دسترس سرویس در دسترس نیست. معمولاً سرور از کار افتاده است.
۵۰۴ مهلت_تمام_شد مهلت درخواست تمام شد. این خطا فقط در صورتی رخ می‌دهد که فراخوانی‌کننده مهلتی کوتاه‌تر از مهلت پیش‌فرض متد تعیین کند (یعنی مهلت درخواستی برای پردازش درخواست توسط سرور کافی نباشد) و درخواست در مهلت مقرر به پایان نرسد.

مدیریت خطاهای SDK مصرف‌کننده

کیت توسعه نرم‌افزار مصرف‌کننده (Consumer SDK) با استفاده از مکانیزم فراخوانی، خطاهای به‌روزرسانی سفر را به برنامه مصرف‌کننده ارسال می‌کند. پارامتر فراخوانی، یک نوع بازگشتی مختص پلتفرم است ( TripUpdateError در اندروید و 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
    ...
  }
}

هدف-سی

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 به طور خودکار آنها را بازیابی می‌کند.

کد وضعیت توضیحات
سقط شده سرور ارسال پاسخ را متوقف کرد. این معمولاً به دلیل مشکل سرور ایجاد می‌شود.
لغو شد سرور پاسخ خروجی را قطع کرد. این معمولاً زمانی اتفاق می‌افتد که
برنامه به پس‌زمینه ارسال می‌شود، یا وقتی تغییری در وضعیت آن ایجاد می‌شود
برنامه مصرف کننده.
قطع شد
مهلت_تمام_شد سرور خیلی طول کشید تا پاسخ دهد.
غیرقابل دسترس سرور در دسترس نبود. این معمولاً به دلیل مشکل شبکه ایجاد می‌شود.

خطاهای کلاینت

کدهای وضعیت زیر مربوط به خطاهای کلاینت هستند و شما باید برای رفع آنها اقدام کنید. تا زمانی که اشتراک‌گذاری سفر را پایان ندهید، Consumer SDK به تلاش مجدد برای به‌روزرسانی سفر ادامه می‌دهد، اما تا زمانی که اقدامی نکنید، بازیابی نمی‌شود.

کد وضعیت توضیحات
آرگومان نامعتبر برنامه Consumer نام سفر نامعتبری را مشخص کرده است؛ نام سفر باید از قالب providers/{provider_id}/trips/{trip_id} پیروی کند.
یافت نشد این سفر هرگز ایجاد نشد.
مجوز_رد_شد برنامه Consumer مجوزهای کافی ندارد. این خطا زمانی رخ می‌دهد که:
  • برنامه Consumer مجوز ندارد
  • SDK مصرف‌کننده برای این پروژه در کنسول ابری گوگل فعال نشده است.
  • توکن JWT یا وجود ندارد یا نامعتبر است.
  • توکن JWT با شناسه سفری امضا شده است که با سفر درخواستی مطابقت ندارد.
منابع_تمام_شده سهمیه منابع صفر است، یا نرخ جریان ترافیک از حد مجاز سرعت فراتر می‌رود.
احراز هویت نشده درخواست به دلیل وجود توکن JWT نامعتبر، احراز هویت نشد. این خطا یا زمانی رخ می‌دهد که توکن JWT بدون شناسه سفر امضا شده باشد، یا زمانی که توکن JWT منقضی شده باشد.