ルートをフォローすると、ユーザーアプリに適切な車両の位置が表示されます。そのため、アプリはルートのフォローを開始し、ルートの進行状況を更新し、ルートが完了したらフォローを停止する必要があります。
このドキュメントでは、そのプロセスの仕組みについて説明します。
ルートのフォローを開始する
ルートのフォローを開始する手順は次のとおりです。
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(_:didFailUpdateTripWithError:) を実装することで、tripModel のコールバック
を取得できます。エラー メッセージは、Google Cloud エラーの標準に準拠しています。エラー メッセージの定義とすべてのエラーコードについて詳しくは、
Google Cloud エラーのドキュメントをご覧ください。
ルートのモニタリング中に発生する可能性のある一般的なエラーをいくつか紹介します。
| HTTP | RPC | 説明 |
|---|---|---|
| 400 | INVALID_ARGUMENT | クライアントが無効なルート名を指定しました。ルート名は、
providers/{provider_id}/trips/{trip_id} の形式にする必要があります。
provider_id は、サービス プロバイダが所有する
Cloud プロジェクトの ID にする必要があります。 |
| 401 | UNAUTHENTICATED | 有効な認証情報がない場合に、このエラーが発生します。 たとえば、JWT トークンがルート ID なしで署名されている場合や、JWT トークン が期限切れの場合などです。 |
| 403 | PERMISSION_DENIED | クライアントに十分な権限がない場合 (コンシューマー ロールのユーザーが updateTrip を呼び出そうとした場合など)、JWT トークンが無効な場合、またはクライアント プロジェクトで API が有効になっていない場合に、このエラーが発生します。 JWT トークンがないか、リクエストされたルート ID と一致しないルート ID でトークンが署名されている可能性があります。 |
| 429 | RESOURCE_EXHAUSTED | リソース割り当てがゼロになっているか、トラフィック レートが上限を超えています。 |
| 503 | UNAVAILABLE | サービス利用不可。通常、サーバーがダウンしています。 |
| 504 | DEADLINE_EXCEEDED | リクエスト期限を超えました。このエラーは、呼び出し元が、メソッドのデフォルト期限よりも短い期限を設定し(つまり、 要求された期限はサーバーがリクエストを処理するのに十分ではない)、 リクエストがその期限内に完了しなかった場合にのみ発生します。 |
Consumer SDK のエラーを処理する
Consumer SDK は、コールバック メカニズムを使用して、ルートの更新エラーをユーザーアプリに送信します。コールバック パラメータは、プラットフォーム固有の戻り値の型(
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;
...
}
}
ステータス コードを解釈する
ステータス コードは、サーバーとネットワーク関連のエラーとクライアントサイドのエラーの 2 種類のエラーをカバーしています。
サーバーとネットワークのエラー
次のステータス コードは、ネットワーク エラーまたはサーバーエラーを示します。これらのエラーを解決するための対応は必要ありません。Consumer SDK は自動的に復旧します。
| ステータス コード | 説明 |
|---|---|
| ABORTED | サーバーがレスポンスの送信を停止しました。通常、これは サーバーの問題が原因で発生します。 |
| CANCELLED | サーバーが送信レスポンスを終了しました。通常、これはアプリがバックグラウンドに送信された場合、またはユーザーアプリの状態が変更された場合に発生します。 |
| INTERRUPTED | |
| DEADLINE_EXCEEDED | サーバーからの応答時間が長すぎます。 |
| UNAVAILABLE | サーバーが利用できませんでした。通常、これはネットワーク の問題が原因で発生します。 |
クライアントエラー
次のステータス コードはクライアント エラーを示します。これらのエラーを解決するには対応が必要です。Consumer SDK は、ルートの共有を終了するまでルートの更新を再試行しますが、対応するまで復旧しません。
| ステータス コード | 説明 |
|---|---|
| INVALID_ARGUMENT | ユーザーアプリが無効なルート名を指定しました。ルート名は、
providers/{provider_id}/trips/{trip_id} の形式にする必要があります。 |
| NOT_FOUND | ルートが作成されていません。 |
| PERMISSION_DENIED | ユーザーアプリに十分な権限がありません。このエラーは、次の場合に発生します。
|
| RESOURCE_EXHAUSTED | リソース割り当てがゼロになっているか、トラフィック フローのレートが 速度制限を超えています。 |
| UNAUTHENTICATED | 無効な JWT トークンが原因で、リクエストの認証に失敗しました。この エラーは、JWT トークンがルート ID なしで署名されている場合、または JWT トークンが期限切れの場合に発生します。 |