追蹤行程後,消費者應用程式會顯示 適合供消費者使用為此,您的應用程式必須啟動 追蹤行程、更新行程進度,以及在行程時停止追蹤 完成。
本文將說明這項程序的運作方式。
開始追蹤行程
以下說明如何透過分享旅程開始追蹤行程:
收集所有使用者輸入內容,例如下車和上車地點 來自
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];
}
更新行程進度
您可以在行程期間,按照下列方式管理行程進度:
行程完成或取消時,請停止監聽更新。 如需範例,請參閱 停止監聽更新範例。
開始監聽更新範例
以下範例說明如何註冊 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];
...
}
停止監聽更新範例
以下範例說明如何取消 tripModel
的註冊作業
回呼。
Swift
/*
* MapViewController.swift
*/
deinit {
self.currentTripModel.unregisterSubscriber(self)
}
Objective-C
/*
* MapViewController.m
*/
- (void)dealloc {
[self.currentTripModel unregisterSubscriber:self];
...
}
處理行程更新範例
以下範例說明如何實作 GMTCTripModelSubscriber
行程狀態更新時,用來處理回呼的通訊協定。
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
但發生錯誤,可以取得回呼
透過實作委派方法以 tripModel
模式執行作業
tripModel(_:didFailUpdateTripWithError:)
。發生錯誤
的訊息是否符合 Google Cloud 錯誤標準詳細的錯誤資訊
訊息定義和所有錯誤代碼,請參閱
Google Cloud 錯誤說明文件。
以下是行程監控過程中可能發生的幾個常見錯誤:
HTTP | RPC | 說明 |
---|---|---|
400 | INVALID_ARGUMENT | 用戶端指定的行程名稱無效。行程名稱必須遵循
格式:providers/{provider_id}/trips/{trip_id} 。
provider_id 必須是
連線服務供應商 |
401 | 未驗證 | 如果沒有有效的驗證憑證,便會收到這則錯誤訊息。 舉例來說,如果簽署 JWT 權杖時不含行程 ID 或 JWT 權杖, 已過期。 |
403 | PERMISSION_DENIED | 如果用戶端沒有足夠的權限,就會收到這個錯誤 (例如,具備消費者角色的使用者嘗試呼叫 updateTrip), JWT 權杖無效,或是用戶端專案未啟用 API。 缺少 JWT 權杖,或是權杖簽署時使用的行程 ID 與要求的行程 ID 不符。 |
429 | RESOURCE_EXHAUSTED | 資源配額為 0,或流量速率超出上限。 |
503 | 無法使用 | 服務無法使用,通常是因伺服器停止運作所致。 |
504 | DEADLINE_EXCEEDED | 已超出要求期限。只有在呼叫端設定了 如果期限短於方法的預設期限 (即 要求的期限不足,伺服器無法處理要求) 要求未在期限內完成。 |
處理消費者 SDK 錯誤
Consumer SDK 利用回呼,將行程更新錯誤傳送至消費者應用程式
以注意力機制為基礎回呼參數是平台專屬的傳回類型 (
TripUpdateError
在 Android 裝置上,以及
NSError
。
擷取狀態碼
傳遞至回呼的錯誤通常是 gRPC 錯誤,您也可以 會以狀態碼的形式,從用戶端擷取額外資訊。對於 完整的狀態碼清單,請參閱 gRPC 中的狀態碼及其用途。
Swift
系統會在 tripModel(_:didFailUpdateTripWithError:)
中回呼 NSError
。
// 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
系統會在 tripModel:didFailUpdateTripWithError:
中回呼 NSError
。
// 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 會自動取得 復原時間
狀態碼 | 說明 |
---|---|
ABORTED | 伺服器已停止傳送回應。這通常是由 伺服器的問題。 |
已取消 | 伺服器已終止傳出回應。這通常
會發生在
應用程式傳送至背景,或容器中的狀態變更 消費者應用程式。 |
INTERRUPTED | |
DEADLINE_EXCEEDED | 伺服器回應的時間過長。 |
無法使用 | 伺服器無法使用。這通常是由網路造成的 問題。 |
用戶端錯誤
下列狀態碼代表用戶端錯誤,您必須採取行動 解決問題。Consumer SDK 會繼續重試行程,直到您 必須等到您採取行動之後才能恢復分享歷程。
狀態碼 | 說明 |
---|---|
INVALID_ARGUMENT | 消費者應用程式指定的行程名稱無效。行程名稱必須
請採用 providers/{provider_id}/trips/{trip_id} 格式。
|
NOT_FOUND | 這個行程從未建立。 |
PERMISSION_DENIED | 消費者應用程式權限不足。發生這個錯誤的原因包括:
|
RESOURCE_EXHAUSTED | 資源配額為零或流量速率超過 速限。 |
未驗證 | JWT 權杖無效,導致要求驗證失敗。這個 發生錯誤時,可能是因為在簽署 JWT 權杖時並未提供行程 ID;或 系統就會刪除金鑰 |