Решение Last Mile Fleet Solution в настоящее время доступно только для избранных клиентов. Свяжитесь с отделом продаж , чтобы узнать больше.

Начало работы с Driver SDK для iOS

Driver SDK — это библиотека, которую вы интегрируете в свое приложение для драйверов. Он отвечает за обновление Fleet Engine с указанием местоположения водителя, маршрута, оставшегося расстояния и расчетного времени прибытия. Он также интегрируется с Navigation SDK, который предоставляет водителю пошаговые инструкции по навигации.

Минимальные системные требования

  • Мобильное устройство должно работать под управлением iOS 13 или более поздней версии.
  • Xcode версии 14 или новее.
  • Предварительные условия

    В этом руководстве предполагается, что в вашем приложении уже реализован навигационный SDK , а серверная часть Fleet Engine настроена и доступна. Однако в примере кода представлен образец настройки Navigation 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
    

    Адрес электронной почты, используемый для входа, должен быть членом группы Workspace.

    Автоматизация (создание систем или непрерывная интеграция)

    Настройте хосты автоматизации в соответствии с лучшими практиками :

    • Если ваш процесс выполняется в среде Google Cloud, используйте автоматическое определение учетных данных.

    • В противном случае сохраните файл ключей сервисного аккаунта в безопасном месте в файловой системе хоста и установите соответствующую переменную среды GOOGLE_APPLICATION_CREDENTIALS .

    Адрес электронной почты сервисной учетной записи, связанный с учетными данными, должен быть членом группы Workspace.

    Конфигурация проекта

    Вы можете настроить Driver SDK для iOS с помощью Cocoapods или вручную.

    Используйте какаоподы

    Чтобы настроить Driver SDK для iOS, вам потребуются следующие элементы:

    • Инструмент CocoaPods: Чтобы установить этот инструмент, откройте Терминал и выполните следующую команду. shell sudo gem install cocoapods Для получения более подробной информации обратитесь к руководству по началу работы с CocoaPods .
    1. Создайте подфайл для Driver SDK для iOS и используйте его для установки API и его зависимостей: Создайте файл с именем Podfile в каталоге вашего проекта. Этот файл определяет зависимости вашего проекта. Отредактируйте подфайл и добавьте свои зависимости. Вот пример, который включает зависимости:

      source "https://github.com/CocoaPods/Specs.git"
      
      target 'YOUR_APPLICATION_TARGET_NAME_HERE' do
        pod 'GoogleRidesharingDriver'
      end
      
    2. Сохраните подфайл. Откройте терминал и перейдите в каталог, содержащий подфайл:

      cd <path-to-project>
      
    3. Запустите команду установки модуля. При этом будут установлены API, указанные в подфайле, а также все зависимости, которые они могут иметь.

      pod install
      
    4. Закройте Xcode, а затем откройте (дважды щелкните) файл .xcworkspace вашего проекта, чтобы запустить Xcode. С этого момента вы должны использовать файл .xcworkspace для открытия проекта.

    Альфа/бета-версии SDK

    Чтобы настроить альфа- или бета-версию Driver SDK для iOS, вам потребуются следующие элементы:

    • Инструмент CocoaPods: Чтобы установить этот инструмент, откройте Терминал и выполните следующую команду.

      sudo gem install cocoapods
      

      Дополнительные сведения см. в руководстве по началу работы с CocoaPods .

    • Ваша учетная запись разработчика в списке доступа Google. Репозиторий модулей альфа- и бета-версий SDK не является общедоступным. Чтобы получить доступ к этим версиям, обратитесь к инженеру по работе с клиентами Google. Инженер добавляет вашу учетную запись разработчика в список доступа, а затем устанавливает файл cookie для аутентификации.

    После того как ваш проект будет в списке доступа, вы сможете получить доступ к модулю.

    1. Создайте подфайл для Driver SDK для iOS и используйте его для установки API и его зависимостей: Создайте файл с именем 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
      
    2. Сохраните подфайл. Откройте терминал и перейдите в каталог, содержащий подфайл:

      cd <path-to-project>
      
    3. Запустите команду установки модуля. При этом будут установлены API, указанные в подфайле, а также все зависимости, которые они могут иметь.

      pod install
      
    4. Закройте Xcode, а затем откройте (дважды щелкните) файл .xcworkspace вашего проекта, чтобы запустить Xcode. С этого момента вы должны использовать файл .xcworkspace для открытия проекта.

    Реализация авторизации и аутентификации

    Когда ваше приложение для водителей генерирует и отправляет обновления на серверную часть 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 , используя идентификатор поставщика, идентификатор транспортного средства, 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

      Сообщает приложению для водителей, что серверные службы успешно получили обновление местоположения и состояния автомобиля.

    • 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