כשעוקבים אחרי נסיעה, האפליקציה למשתמשים מציגה למשתמש את המיקום של הרכב המתאים. כדי לעשות את זה, האפליקציה צריכה להתחיל לעקוב אחרי נסיעה, לעדכן את ההתקדמות של הנסיעה ולהפסיק לעקוב אחרי הנסיעה כשהיא מסתיימת.
במאמר הזה מוסבר איך התהליך הזה עובד.
איך מתחילים לעקוב אחרי נסיעה
כדי להתחיל לעקוב אחרי נסיעה:
אוספים את כל הקלטים של המשתמשים, כמו מיקומי איסוף והורדה, מ-
ViewController.כדי להתחיל לעקוב אחרי נסיעה באופן ישיר, צריך ליצור
ViewControllerחדש.
בדוגמה הבאה אפשר לראות איך מתחילים לעקוב אחרי נסיעה מיד אחרי שהתצוגה נטענת.
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];
}
הפסקת המעקב אחרי נסיעה
המעקב אחרי הנסיעה נפסק כשהיא מסתיימת או מבוטלת. בדוגמה הבאה מוסבר איך להפסיק את השיתוף של הנסיעה הפעילה.
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];
}
עדכון ההתקדמות בנסיעה
במהלך הנסיעה, אתם מנהלים את ההתקדמות שלה באופן הבא:
מתחילים להאזין לעדכונים. דוגמה לתחילת האזנה לעדכונים.
טיפול בעדכונים לגבי הנסיעה. לדוגמה, ראו דוגמה לטיפול בעדכוני נסיעות.
כשהנסיעה מסתיימת או מבוטלת, מפסיקים להאזין לעדכונים. דוגמה לכך מופיעה בקטע דוגמה להפסקת ההאזנה לעדכונים.
דוגמה להאזנה לעדכונים
בדוגמה הבאה אפשר לראות איך רושמים את הקריאה החוזרת (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];
...
}
דוגמה להפסקת ההאזנה לעדכונים
בדוגמה הבאה אפשר לראות איך מבטלים את הרישום של הקריאה החוזרת (callback) tripModel.
Swift
/*
* MapViewController.swift
*/
deinit {
self.currentTripModel.unregisterSubscriber(self)
}
Objective-C
/*
* MapViewController.m
*/
- (void)dealloc {
[self.currentTripModel unregisterSubscriber:self];
...
}
דוגמה לטיפול בעדכוני נסיעות
בדוגמה הבאה אפשר לראות איך מטמיעים את הפרוטוקול GMTCTripModelSubscriber כדי לטפל בקריאות חוזרות (callbacks) כשמצב הנסיעה מתעדכן.
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.
}
טיפול בשגיאות בנסיעות
אם נרשמתם ל-tripModel ומתרחשת שגיאה, אתם יכולים לקבל את הקריאה החוזרת (callback) של tripModel על ידי הטמעה של שיטת הנציג tripModel(_:didFailUpdateTripWithError:). הודעות השגיאה תואמות לתקן השגיאות של Google Cloud. לפירוט של הגדרות הודעות השגיאה וכל קודי השגיאה, קראו את מאמרי העזרה בנושא שגיאות ב-Google Cloud.
הנה כמה שגיאות נפוצות שיכולות להתרחש במהלך מעקב אחר נסיעות:
| HTTP | הכנסה לקליק | תיאור |
|---|---|---|
| 400 | INVALID_ARGUMENT | הלקוח ציין שם נסיעה לא תקין. שם הנסיעה חייב להיות בפורמט providers/{provider_id}/trips/{trip_id}. הערך של provider_id חייב להיות המזהה של הפרויקט ב-Cloud שבבעלות ספק השירות. |
| 401 | UNAUTHENTICATED | השגיאה הזו מופיעה אם אין פרטי כניסה תקינים לאימות. לדוגמה, אם אסימון ה-JWT נחתם בלי מזהה נסיעה או אם פג התוקף של אסימון ה-JWT. |
| 403 | PERMISSION_DENIED | השגיאה הזו מוצגת אם ללקוח אין מספיק הרשאות (לדוגמה, משתמש עם תפקיד צרכן מנסה להפעיל את updateTrip), אם אסימון ה-JWT לא תקין או אם ה-API לא מופעל בפרויקט של הלקוח. יכול להיות שאסימון ה-JWT חסר או שהאסימון חתום באמצעות מזהה נסיעה שלא תואם למזהה הנסיעה המבוקש. |
| 429 | RESOURCE_EXHAUSTED | מכסת המשאבים היא אפס או שקצב התנועה חורג מהמגבלה. |
| 503 | UNAVAILABLE | השירות לא זמין. בדרך כלל השרת מושבת. |
| 504 | DEADLINE_EXCEEDED | המועד האחרון לבקשה חלף. השגיאה הזו מתרחשת רק אם הגורם ששלח את הבקשה הגדיר מועד אחרון קצר יותר מהמועד האחרון שמוגדר כברירת מחדל ל-method (כלומר, המועד האחרון שהוגדר לא מספיק לשרת כדי לעבד את הבקשה), והבקשה לא הסתיימה לפני המועד האחרון. |
טיפול בשגיאות ב-Consumer SDK
ה-SDK לצרכן שולח שגיאות עדכון של נסיעות לאפליקציה למשתמשים באמצעות מנגנון קריאה חוזרת (callback). הפרמטר של הקריאה החוזרת (callback) הוא סוג החזרה ספציפי לפלטפורמה (
TripUpdateError
ב-Android, ו-
NSError
ב-iOS).
חילוץ קודי סטטוס
השגיאות שמועברות לקריאה החוזרת הן בדרך כלל שגיאות gRPC, ואפשר גם לחלץ מהן מידע נוסף בצורה של קוד סטטוס. לרשימה המלאה של קודי הסטטוס, ראו קודי סטטוס והשימוש בהם ב-gRPC.
Swift
הפונקציה 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;
...
}
}
הסבר על קודי סטטוס
קודי הסטטוס מתייחסים לשני סוגים של שגיאות: שגיאות שקשורות לשרת ולרשת, ושגיאות בצד הלקוח.
שגיאות בחיבור לשרת ולרשת
קודי הסטטוס הבאים הם של שגיאות ברשת או בשרת, ואין צורך לבצע פעולה כלשהי כדי לפתור אותן. ה-Consumer SDK מתאושש מהן באופן אוטומטי.
| קוד סטטוס | תיאור |
|---|---|
| הפעולה בוטלה | השרת הפסיק לשלוח את התשובה. בדרך כלל זה קורה בגלל בעיה בשרת. |
| בוטלה | השרת סיים את התגובה היוצאת. בדרך כלל זה קורה כש האפליקציה מועברת לרקע, או כשיש שינוי במצב של האפליקציה למשתמשים. |
| עם הפסקה | |
| DEADLINE_EXCEEDED | לשרת לקח יותר מדי זמן להגיב. |
| UNAVAILABLE | השרת לא היה זמין. בדרך כלל זה קורה בגלל בעיה ברשת. |
שגיאות בצד הלקוח
קודי הסטטוס הבאים הם של שגיאות בצד הלקוח, וצריך לבצע פעולה כדי לפתור אותן. Consumer SDK ימשיך לנסות לרענן את הנסיעה עד שתסיימו את שיתוף הנסיעה, אבל הוא לא יתאושש עד שתבצעו פעולה.
| קוד סטטוס | תיאור |
|---|---|
| INVALID_ARGUMENT | האפליקציה למשתמשים ציינה שם נסיעה לא חוקי. שם הנסיעה חייב להיות בפורמט providers/{provider_id}/trips/{trip_id}.
|
| NOT_FOUND | הנסיעה לא נוצרה. |
| PERMISSION_DENIED | לאפליקציה למשתמשים אין מספיק הרשאות. השגיאה הזו קורית:
|
| RESOURCE_EXHAUSTED | מכסת המשאבים היא אפס, או שקצב זרימת התנועה חורג מהמגבלה. |
| UNAUTHENTICATED | האימות של הבקשה נכשל בגלל אסימון JWT לא תקין. השגיאה הזו מתרחשת כשאסימון ה-JWT נחתם בלי מזהה נסיעה, או כשתוקף אסימון ה-JWT פג. |