Driver SDK — это библиотека, которую вы интегрируете в свое приложение для водителей. Он отвечает за обновление Fleet Engine с указанием местоположения водителя, маршрута, оставшегося расстояния и ожидаемого времени прибытия. Он также интегрируется с Navigation SDK, который предоставляет водителю пошаговые инструкции по навигации.
Минимальные системные требования
Предпосылки
В этом руководстве предполагается, что ваше приложение уже реализует Navigation SDK , а серверная часть Fleet Engine настроена и доступна. Однако в примере кода показано, как настроить пакет SDK для навигации .
Вы также должны включить Maps SDK для iOS в своем проекте Google Cloud и получить ключ API .
Получить доступ
Если вы являетесь клиентом Google Workspace, во время регистрации создайте группу Workspace , например google-maps-platform-sdk-users@workspacedomain.com
, и сообщите название Google. Это рекомендуемый подход. Затем ваша рабочая группа будет добавлена в список разрешенных, который предоставляет доступ к правильным репозиториям CocoaPods. Подтвердите, что адреса электронной почты пользователей и учетных записей служб, которым требуется доступ, включены в этот список.
Если ваша организация не может создавать группы рабочей области, отправьте в Google список адресов электронной почты пользователей и учетных записей служб, которым требуется доступ к этим артефактам.
Местное развитие
Для локальной разработки достаточно авторизоваться с помощью Cloud SDK .
gcloud
gcloud auth login
Электронная почта, используемая для входа, должна быть членом рабочей группы.
Автоматизация (построение систем или непрерывная интеграция)
Настройте хосты автоматизации в соответствии с рекомендациями :
Если ваш процесс выполняется в среде Google Cloud, используйте автоматическое определение учетных данных.
В противном случае сохраните файл ключа учетной записи службы в безопасном месте в файловой системе хоста и соответствующим образом задайте переменную среды GOOGLE_APPLICATION_CREDENTIALS .
Адрес электронной почты сервисной учетной записи, связанный с учетными данными, должен принадлежать группе Workspace.
Конфигурация проекта
Вы можете настроить Driver SDK с помощью CocoaPods.
Используйте CocoaPods
Чтобы настроить Driver SDK с помощью CocoaPods, вам потребуются следующие элементы:
- Инструмент CocoaPods: чтобы установить этот инструмент, откройте Терминал и выполните следующую команду.
shell sudo gem install cocoapods
Дополнительные сведения см. в руководстве по началу работы с CocoaPods .
Создайте Podfile для Driver SDK и используйте его для установки API и его зависимостей: Создайте файл с именем Podfile в каталоге вашего проекта. Этот файл определяет зависимости вашего проекта. Отредактируйте Podfile и добавьте свои зависимости. Вот пример, который включает зависимости:
source "https://github.com/CocoaPods/Specs.git" target 'YOUR_APPLICATION_TARGET_NAME_HERE' do pod 'GoogleRidesharingDriver' end
Сохраните подфайл. Откройте терминал и перейдите в каталог, содержащий подфайл:
cd <path-to-project>
Запустите команду установки модуля. Это установит API, указанные в подфайле, вместе со всеми возможными зависимостями.
pod install
Закройте Xcode, а затем откройте (дважды щелкните) файл .xcworkspace вашего проекта, чтобы запустить Xcode. С этого момента для открытия проекта необходимо использовать файл .xcworkspace.
Альфа/бета версии SDK
Чтобы настроить альфа- или бета-версии Driver SDK для iOS, вам потребуются следующие элементы:
Инструмент CocoaPods: чтобы установить этот инструмент, откройте Терминал и выполните следующую команду.
sudo gem install cocoapods
Дополнительные сведения см. в руководстве по началу работы с CocoaPods .
Ваша учетная запись разработки в списке доступа Google. Репозиторий модулей альфа- и бета-версий SDK не является общедоступным. Чтобы получить доступ к этим версиям, обратитесь к инженеру по работе с клиентами Google. Инженер добавляет вашу учетную запись разработки в список доступа, а затем устанавливает файл cookie для аутентификации.
После того, как ваш проект появится в списке доступа, вы сможете получить доступ к модулю.
Создайте Podfile для Driver SDK для iOS и используйте его для установки API и его зависимостей: Создайте файл с именем Podfile в каталоге вашего проекта. Этот файл определяет зависимости вашего проекта. Отредактируйте Podfile и добавьте свои зависимости. Вот пример, который включает зависимости:
source "https://cpdc-eap.googlesource.com/ridesharing-driver-sdk.git" source "https://github.com/CocoaPods/Specs.git" target 'YOUR_APPLICATION_TARGET_NAME_HERE' do pod 'GoogleRidesharingDriver' end
Сохраните подфайл. Откройте терминал и перейдите в каталог, содержащий подфайл:
cd <path-to-project>
Запустите команду установки модуля. Это установит API, указанные в подфайле, вместе со всеми возможными зависимостями.
pod install
Закройте Xcode, а затем откройте (дважды щелкните) файл .xcworkspace вашего проекта, чтобы запустить Xcode. С этого момента для открытия проекта необходимо использовать файл .xcworkspace.
Установите XCFramework
XCFramework — это двоичный пакет, который используется для установки Driver SDK. Вы можете использовать этот пакет на нескольких платформах, включая машины с чипсетом M1. В этом руководстве показано, как вручную добавить XCFramework, содержащий Driver SDK, в ваш проект и настроить параметры сборки в Xcode.
Распакуйте исходные файлы, которые вы получили от Google.
Запустите Xcode и либо откройте существующий проект, либо создайте новый проект. Если вы новичок в iOS, создайте новый проект и выберите шаблон приложения iOS.
Создайте группу Frameworks в своей группе проектов, если она еще не существует.
Перетащите файл
gRPCCertificates.bundle
, включенный в каталогResources
архива, содержащего XCFramework, в каталог верхнего уровня вашего проекта Xcode. При появлении запроса выберите Копировать элементы, если это необходимо.Чтобы установить Driver SDK, перетащите файл
GoogleRidesharingDriver.xcframework
в свой проект в разделеFrameworks, Libraries, and Embedded Content
. При появлении запроса выберите Копировать элементы, если это необходимо.Выберите свой проект в Навигаторе проектов и выберите цель вашего приложения.
Откройте вкладку Build Phases и в Link Binary with Libraries добавьте следующие платформы и библиотеки, если их еще нет:
-
Accelerate.framework
-
AudioToolbox.framework
-
AVFoundation.framework
-
CoreData.framework
-
CoreGraphics.framework
-
CoreLocation.framework
-
CoreTelephony.framework
-
CoreText.framework
-
GLKit.framework
-
ImageIO.framework
-
libc++.tbd
-
libxml2.tbd
-
libz.tbd
-
OpenGLES.framework
-
QuartzCore.framework
-
SystemConfiguration.framework
-
UIKit.framework
-
LocalAuthentication.framework
-
WebKit.framework
-
Выберите свой проект, а не конкретную цель, и откройте вкладку Build Settings . В разделе «Другие флаги компоновщика» добавьте
‑ObjC
как для отладки, так и для выпуска. Если эти настройки не отображаются, измените фильтр на панели Build Settings с Basic на All .
Реализовать авторизацию и аутентификацию
Когда ваше приложение Driver создает и отправляет обновления на серверную часть Fleet Engine, запросы должны включать действительные токены доступа. Чтобы авторизовать и аутентифицировать эти запросы, Driver SDK вызывает ваш объект, соответствующий протоколу GMTDAuthorization
. Объект отвечает за предоставление требуемого токена доступа.
Как разработчик приложения, вы выбираете, как генерируются токены. Ваша реализация должна предоставлять возможность делать следующее:
- Получите токен доступа, возможно, в формате JSON, с HTTPS-сервера.
- Разберите и кэшируйте токен.
- Обновите токен по истечении срока его действия.
Дополнительные сведения о токенах, ожидаемых сервером Fleet Engine, см. в разделе Создание веб-токена JSON (JWT) для авторизации .
Идентификатор поставщика совпадает с идентификатором проекта Google Cloud. Дополнительную информацию см. в Руководстве пользователя API доставки Fleet Engine .
В следующем примере реализуется поставщик маркеров доступа:
#import "SampleAccessTokenProvider.h"
#import <GoogleRidesharingDriver/GoogleRidesharingDriver.h>
// SampleAccessTokenProvider.h
@interface SampleAccessTokenProvider : NSObject<GMTDAuthorization>
@end
static NSString *const PROVIDER_URL = @"INSERT_YOUR_TOKEN_PROVIDER_URL";
// SampleAccessTokenProvider.m
@implementation SampleAccessTokenProvider{
// The cached vehicle token.
NSString *_cachedVehicleToken;
// Keep track of the vehicle ID the cached token is for.
NSString *_lastKnownVehicleID;
// Keep track of when tokens expire for caching.
NSTimeInterval _tokenExpiration;
}
- (void)fetchTokenWithContext:(nullable GMTDAuthorizationContext *)authorizationContext
completion:(nonnull GMTDAuthTokenFetchCompletionHandler)completion {
if (!completion) {
NSAssert(NO, @"%s encountered an unexpected nil completion.", __PRETTY_FUNCTION__);
return;
}
// Get the vehicle ID from the authorizationContext. This is set by the Driver SDK.
NSString *vehicleID = authorizationContext.vehicleID;
if (!vehicleID) {
NSAssert(NO, @"Vehicle ID is missing from authorizationContext.");
return;
}
// Clear cached vehicle token if vehicle ID has changed.
if (![_lastKnownVehicleID isEqual:vehicleID]) {
_tokenExpiration = 0.0;
_cachedVehicleToken = nil;
}
_lastKnownVehicleID = vehicleID;
// Clear cached vehicle token if it has expired.
if ([[NSDate date] timeIntervalSince1970] > _tokenExpiration) {
_cachedVehicleToken = nil;
}
// If appropriate, use the cached token.
if (_cachedVehicleToken) {
completion(_cachedVehicleToken, nil);
return;
}
// Otherwise, try to fetch a new token from your server.
NSURL *requestURL = [NSURL URLWithString:PROVIDER_URL];
NSMutableURLRequest *request =
[[NSMutableURLRequest alloc] initWithURL:requestURL];
request.HTTPMethod = @"GET";
// Replace the following key values with the appropriate keys based on your
// server's expected response.
NSString *vehicleTokenKey = @"VEHICLE_TOKEN_KEY";
NSString *tokenExpirationKey = @"TOKEN_EXPIRATION";
__weak typeof(self) weakSelf = self;
void (^handler)(NSData *_Nullable data, NSURLResponse *_Nullable response,
NSError *_Nullable error) =
^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) {
typeof(self) strongSelf = weakSelf;
if (error) {
completion(nil, error);
return;
}
NSError *JSONError;
NSMutableDictionary *JSONResponse =
[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&JSONError];
if (JSONError) {
completion(nil, JSONError);
return;
} else {
// Sample code only. No validation logic.
id expirationData = JSONResponse[tokenExpirationKey];
if ([expirationData isKindOfClass:[NSNumber class]]) {
NSTimeInterval expirationTime = ((NSNumber *)expirationData).doubleValue;
strongSelf->_tokenExpiration = [[NSDate date] timeIntervalSince1970] + expirationTime;
}
strongSelf->_cachedVehicleToken = JSONResponse[vehicleTokenKey];
completion(JSONResponse[vehicleTokenKey], nil);
}
};
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *mainQueueURLSession =
[NSURLSession sessionWithConfiguration:config delegate:nil
delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDataTask *task = [mainQueueURLSession dataTaskWithRequest:request completionHandler:handler];
[task resume];
}
@end
Создайте экземпляр DeliveryDriverAPI
Чтобы получить экземпляр GMTDDeliveryVehicleReporter
, сначала необходимо создать экземпляр GMTDDeliveryDriverAPI
, используя providerID, VehicleID, driverContext и accessTokenProvider. Идентификатор провайдера совпадает с идентификатором проекта Google Cloud. И вы можете получить доступ к экземпляру GMTDDeliveryVehicleReporter
напрямую из API драйвера.
В следующем примере создается экземпляр GMTDDeliveryDriverAPI
:
#import “SampleViewController.h”
#import “SampleAccessTokenProvider.h”
#import <GoogleRidesharingDriver/GoogleRidesharingDriver.h>
static NSString *const PROVIDER_ID = @"INSERT_YOUR_PROVIDER_ID";
@implementation SampleViewController {
GMSMapView *_mapView;
}
- (void)viewDidLoad {
NSString *vehicleID = @"INSERT_CREATED_VEHICLE_ID";
SampleAccessTokenProvider *accessTokenProvider =
[[SampleAccessTokenProvider alloc] init];
GMTDDriverContext *driverContext =
[[GMTDDriverContext alloc] initWithAccessTokenProvider:accessTokenProvider
providerID:PROVIDER_ID
vehicleID:vehicleID
navigator:_mapView.navigator];
GMTDDeliveryDriverAPI *deliveryDriverAPI = [[GMTDDeliveryDriverAPI alloc] initWithDriverContext:driverContext];
}
При желании прослушивайте события VehicleReporter
GMTDDeliveryVehicleReporter
периодически обновляет транспортное средство, если для locationTrackingEnabled
YES. Чтобы реагировать на эти периодические обновления, любой объект может подписаться на события GMTDDeliveryVehicleReporter
, соблюдая протокол GMTDVehicleReporterListener
.
Вы можете обрабатывать следующие события:
vehicleReporter:didSucceedVehicleUpdate
Сообщает приложению Driver, что серверные службы успешно получили информацию о местоположении и состоянии автомобиля.
vehicleReporter:didFailVehicleUpdate:withError
Сообщает слушателю, что обновление транспортного средства не удалось. Пока включено отслеживание местоположения,
GMTDDeliveryVehicleReporter
продолжает отправлять последние данные в серверную часть Fleet Engine.
В следующем примере обрабатываются эти события:
SampleViewController.h
@interface SampleViewController : UIViewController<GMTDVehicleReporterListener>
@end
SampleViewController.m
#import “SampleViewController.h”
#import “SampleAccessTokenProvider.h”
#import <GoogleRidesharingDriver/GoogleRidesharingDriver.h>
static NSString *const PROVIDER_ID = @"INSERT_YOUR_PROVIDER_ID";
@implementation SampleViewController {
GMSMapView *_mapView;
}
- (void)viewDidLoad {
// ASSUMES YOU IMPLEMENTED HAVE THE SAMPLE CODE UP TO THIS STEP.
[ridesharingDriverAPI.vehicleReporter addListener:self];
}
- (void)vehicleReporter:(GMTDDeliveryVehicleReporter *)vehicleReporter didSucceedVehicleUpdate:(GMTDVehicleUpdate *)vehicleUpdate {
// Handle update succeeded.
}
- (void)vehicleReporter:(GMTDDeliveryVehicleReporter *)vehicleReporter didFailVehicleUpdate:(GMTDVehicleUpdate *)vehicleUpdate withError:(NSError *)error {
// Handle update failed.
}
@end
Включить отслеживание местоположения
Чтобы включить отслеживание местоположения, ваше приложение может установить для locationTrackingEnabled
YES
в GMTDDeliveryVehicleReporter
. Затем GMTDDeliveryVehicleReporter
будет автоматически отправлять обновления местоположения. Когда GMSNavigator
находится в режиме навигации (когда пункт назначения задан через setDestinations
) и locationTrackingEnabled
установлено значение YES
, GMTDDeliveryVehicleReporter
также автоматически отправляет обновления маршрута и ETA.
Маршрут, установленный во время этих обновлений, будет тем же маршрутом, по которому движется водитель во время сеанса навигации. Таким образом, для правильной работы отслеживания отправлений путевая точка, установленная с помощью -setDestinations:callback:
должна совпадать с пунктом назначения, установленным в бэкэнде Fleet Engine.
Следующий пример включает отслеживание местоположения:
SampleViewController.m
#import “SampleViewController.h”
#import “SampleAccessTokenProvider.h”
#import <GoogleRidesharingDriver/GoogleRidesharingDriver.h>
static NSString *const PROVIDER_ID = @"INSERT_YOUR_PROVIDER_ID";
@implementation SampleViewController {
GMSMapView *_mapView;
}
- (void)viewDidLoad {
// ASSUMES YOU IMPLEMENTED HAVE THE SAMPLE CODE UP TO THIS STEP.
deliveryDriverAPI.vehicleReporter.locationTrackingEnabled = YES;
}
@end
По умолчанию интервал создания отчетов составляет 10 секунд, но этот интервал можно изменить с помощью locationUpdateInterval
. Минимальный поддерживаемый интервал обновления составляет 5 секунд. Максимальный поддерживаемый интервал обновления составляет 60 секунд. Более частые обновления могут привести к более медленным запросам и ошибкам.
Отключить обновления местоположения
Ваше приложение может отключить обновления местоположения для автомобиля. Например, когда смена водителя заканчивается, ваше приложение может установить для locationTrackingEnabled
значение NO
.
_vehicleReporter.locationTrackingEnabled = NO
Обработка ошибок update_mask
Когда GMTDDeliveryVehicleReporter
отправляет обновление транспортного средства, может возникнуть ошибка update_mask
, когда маска пуста, и обычно это происходит при первом обновлении после запуска. В следующем примере показано, как обработать эту ошибку:
Быстрый
import GoogleRidesharingDriver
class VehicleReporterListener: NSObject, GMTDVehicleReporterListener {
func vehicleReporter(
_ vehicleReporter: GMTDVehicleReporter,
didFail vehicleUpdate: GMTDVehicleUpdate,
withError error: Error
) {
let fullError = error as NSError
if let innerError = fullError.userInfo[NSUnderlyingErrorKey] as? NSError {
let innerFullError = innerError as NSError
if innerFullError.localizedDescription.contains("update_mask cannot be empty") {
emptyMaskUpdates += 1
return
}
}
failedUpdates += 1
}
override init() {
emptyMaskUpdates = 0
failedUpdates = 0
}
}
Цель-C
#import "VehicleReporterListener.h"
#import <GoogleRidesharingDriver/GoogleRidesharingDriver.h>
@implementation VehicleReporterListener {
NSInteger emptyMaskUpdates = 0;
NSInteger failedUpdates = 0;
}
- (void)vehicleReporter:(GMTDVehicleReporter *)vehicleReporter
didFailVehicleUpdate:(GMTDVehicleUpdate *)vehicleUpdate
withError:(NSError *)error {
for (NSError *underlyingError in error.underlyingErrors) {
if ([underlyingError.localizedDescription containsString:@"update_mask cannot be empty"]) {
emptyMaskUpdates += 1;
return;
}
}
failedUpdates += 1
}
@end