Когда вы отслеживаете поездку, ваше приложение для пользователей отображает местоположение соответствующего транспортного средства. Для этого вашему приложению необходимо начать отслеживать поездку, обновлять информацию о ходе поездки и остановить отслеживание по ее завершении.
В этом документе описывается, как работает этот процесс.
Начните следить за путешествием
Вот как начать отслеживать поездку:
Соберите все пользовательские данные, такие как места высадки и посадки, из
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()
}
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];
}
Прекратите следить за поездкой
Отслеживание поездки прекращается после ее завершения или отмены. В следующем примере показано, как прекратить делиться информацией об активной поездке.
Быстрый
/*
* 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 .
Быстрый
/*
* 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 .
Быстрый
/*
* MapViewController.swift
*/
deinit {
self.currentTripModel.unregisterSubscriber(self)
}
Objective-C
/*
* 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.
}
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 Errors. Подробные определения сообщений об ошибках и все коды ошибок см. в документации Google Cloud Errors .
Вот некоторые распространенные ошибки, которые могут возникнуть при отслеживании поездок:
| HTTP | РПК | Описание |
|---|---|---|
| 400 | НЕВЕРНЫЙ АРГУМЕНТ | Клиент указал недопустимое название поездки. Название поездки должно соответствовать формату providers/{provider_id}/trips/{trip_id} . provider_id должен быть идентификатором облачного проекта, принадлежащего поставщику услуг. |
| 401 | НЕПОДТВЕРЖДЕННЫЙ | Эта ошибка возникает, если отсутствуют действительные учетные данные для аутентификации. Например, если токен JWT подписан без идентификатора поездки или срок действия токена JWT истек. |
| 403 | ДОСТУП ЗАПРЕЩЕН | Эта ошибка возникает, если у клиента недостаточно прав доступа (например, пользователь с ролью потребителя пытается вызвать функцию updateTrip), если JWT-токен недействителен или API не включен для проекта клиента. Возможно, JWT-токен отсутствует или подписан с идентификатором поездки, который не соответствует запрошенному идентификатору поездки. |
| 429 | ИСТЕЧЕНИЕ РЕСУРСОВ | Квота ресурсов равна нулю или скорость трафика превышает лимит. |
| 503 | НЕДОСТУПНО | Сервис недоступен. Обычно сервер не работает. |
| 504 | СРОК ПРЕВЫШЕН | Превышен срок выполнения запроса. Эта ошибка возникает только в том случае, если вызывающая сторона устанавливает срок, который короче, чем срок по умолчанию для метода (то есть, запрошенного срока недостаточно для обработки запроса сервером), и запрос не был завершен в течение этого срока. |
Обработка ошибок потребительского SDK
SDK для потребителей отправляет ошибки обновления поездки в приложение потребителя с помощью механизма обратного вызова. Параметр обратного вызова имеет тип возвращаемого значения, специфичный для платформы ( TripUpdateError на Android и 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
...
}
}
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;
...
}
}
Интерпретация кодов состояния
Коды состояния охватывают два типа ошибок: ошибки, связанные с сервером и сетью, и ошибки на стороне клиента.
Ошибки сервера и сети
Приведенные ниже коды состояния указывают на ошибки сети или сервера, и вам не нужно предпринимать никаких действий для их устранения. SDK потребителя автоматически восстанавливается после них.
| Код состояния | Описание |
|---|---|
| ПРЕРВАНО | Сервер перестал отправлять ответ. Обычно это происходит из-за неполадок на сервере. |
| ОТМЕНЕНО | Сервер прервал отправку исходящего ответа. Обычно это происходит, когда Приложение переводится в фоновый режим или при изменении состояния. Потребительское приложение. |
| ПРЕРВАННЫЙ | |
| СРОК ПРЕВЫШЕН | Сервер слишком долго отвечал. |
| НЕДОСТУПНО | Сервер недоступен. Обычно это происходит из-за проблем с сетью. |
Ошибки клиента
Приведенные ниже коды состояния указывают на ошибки клиента, и для их устранения необходимо принять меры. SDK для потребителей продолжает попытки обновления поездки до тех пор, пока вы не завершите обмен данными о поездке, но процесс не восстановится, пока вы не предпримете необходимые действия.
| Код состояния | Описание |
|---|---|
| НЕВЕРНЫЙ АРГУМЕНТ | В приложении для потребителей указано недопустимое название поездки; название поездки должно соответствовать формату providers/{provider_id}/trips/{trip_id} . |
| НЕ НАЙДЕНО | Эта поездка так и не была организована. |
| ДОСТУП ЗАПРЕЩЕН | Приложение «Потребитель» имеет недостаточные права доступа. Эта ошибка возникает в следующих случаях:
|
| ИСТЕЧЕНИЕ РЕСУРСОВ | Квота ресурсов равна нулю, или интенсивность транспортного потока превышает допустимую скорость. |
| НЕПОДТВЕРЖДЕННЫЙ | Запрос не прошел аутентификацию из-за недействительного JWT-токена. Эта ошибка возникает либо когда JWT-токен подписан без идентификатора поездки, либо когда срок действия JWT-токена истек. |