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

Вы можете использовать Driver SDK, чтобы обеспечить расширенную навигацию и отслеживание вашего приложения «Поездки и ход заказа». Driver SDK предоставляет обновленную информацию о местонахождении транспортных средств и задачах для системы On-demand Rides and Delivery Solution Fleet Engine.

Driver SDK информирует службы Fleet Engine и ваши таможенные службы о местонахождении и состоянии транспортного средства. Например, транспортное средство может находиться ONLINE или OFFLINE , а местоположение автомобиля меняется по ходу поездки.

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

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

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

    Вам также необходимо включить Maps SDK для iOS в своем проекте Google Cloud и получить ключ API .

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

    Менеджер пакетов Swift

    Driver SDK можно установить через Swift Package Manager . Чтобы добавить SDK, убедитесь, что вы удалили все существующие зависимости Driver SDK.

    Чтобы добавить SDK в новый или существующий проект, выполните следующие действия:

    1. Откройте project или workspace Xcode, затем выберите «Файл» > «Добавить зависимости пакета» .
    2. Введите https://github.com/googlemaps/ios-driver-sdk в качестве URL-адреса, нажмите Enter, чтобы загрузить пакет, и нажмите «Добавить пакет».
    3. Чтобы установить конкретную version , установите в поле «Правило зависимости» один из вариантов, зависящих от версии. Для новых проектов рекомендуем указывать последнюю версию и использовать опцию «Точная версия». После завершения нажмите «Добавить пакет».
    4. В окне «Выбор продуктов пакета» убедитесь, что GoogleRidesharingDriver будет добавлен к назначенной вами main цели. После завершения нажмите «Добавить пакет».
    5. Чтобы проверить установку, перейдите на панель General » целевой системы. В разделе «Платформы», «Библиотеки» и «Встроенный контент» вы должны увидеть установленные пакеты. Вы также можете просмотреть раздел «Зависимости пакетов» в «Навигаторе проекта», чтобы проверить пакет и его версию.

    Чтобы обновить package для существующего проекта, выполните следующие действия:

    1. В Xcode перейдите в «Файл» > «Пакеты» > «Обновить до последних версий пакетов».
    2. Чтобы проверить установку, перейдите в раздел «Зависимости пакетов» в «Навигаторе проекта» , чтобы проверить пакет и его версию.

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

    1. Закройте рабочую область Xcode. Откройте терминал и выполните следующую команду:
      sudo gem install cocoapods-deintegrate cocoapods-clean 
      pod deintegrate 
      pod cache clean --all
    2. Удалите Podfile , Podfile.resolved и workspace Xcode, если вы не используете их ни для чего, кроме CocoaPods.

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

    1. В настройках конфигурации проекта Xcode найдите Frameworks, Libraries и Embedded Content . Используйте знак минус (-) , чтобы удалить следующую структуру:

      • GoogleRidesharingDriver.xcframework
    2. Из каталога верхнего уровня вашего проекта Xcode удалите пакет GoogleRidesharingDriver .

    Какао-стручки

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

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

      source "https://github.com/CocoaPods/Specs.git"
      
      target 'YOUR_APPLICATION_TARGET_NAME_HERE' do
        pod 'GoogleRidesharingDriver'
      end
      

      Вот пример, который включает модули Alpha и Beta для Driver SDK в качестве зависимостей:

      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 для открытия проекта.

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

    Ручная установка

    XCFramework — это двоичный пакет, который вы используете для установки Driver SDK. Вы можете использовать этот пакет на нескольких платформах, включая машины, использующие Apple Silicon . В этом руководстве показано, как вручную добавить XCFramework, содержащий Driver SDK, в ваш проект и настроить параметры сборки в Xcode.

    Загрузите двоичный файл SDK и ресурсы:

    1. Извлеките файлы, чтобы получить доступ к XCFramework и ресурсам.

    2. Запустите Xcode и либо откройте существующий проект, либо создайте новый проект. Если вы новичок в iOS, создайте новый проект и выберите шаблон приложения iOS.

    3. Создайте группу Frameworks в группе проекта, если она еще не существует.

    4. Чтобы установить Driver SDK, перетащите файл GoogleRidesharingDriver.xcframework в свой проект в разделе «Платформы, библиотеки и встроенный контент» . При появлении запроса выберите Копировать элементы, если необходимо.

    5. Перетащите загруженный файл GoogleRidesharingDriver.bundle в каталог верхнего уровня вашего проекта Xcode. При появлении запроса выберите Copy items if needed .

    6. Выберите свой проект в Навигаторе проектов и выберите цель своего приложения.

    7. Откройте вкладку «Фазы сборки» и в разделе «Связывание двоичных файлов с библиотеками» добавьте следующие платформы и библиотеки, если они еще не присутствуют:

      • 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
      • LocalAuthentication.framework
      • OpenGLES.framework
      • QuartzCore.framework
      • SystemConfiguration.framework
      • UIKit.framework
      • WebKit.framework
    8. Выберите свой проект, а не конкретную цель, и откройте вкладку «Настройки сборки» . В разделе «Другие флаги компоновщика» добавьте -ObjC как для отладки, так и для выпуска. Если эти настройки не отображаются, измените фильтр на панели «Параметры сборки» с «Базовый» на «Все» .

    Добавить файл манифеста конфиденциальности Apple

    1. Загрузите пакет манифеста конфиденциальности для Driver SDK для iOS: GoogleRidesharingDriverPrivacy .
    2. Извлеките файл, чтобы получить доступ к GoogleRidesharingDriverPrivacy.bundle .
    3. Скопируйте GoogleRidesharingDriverPrivacy.bundle в каталог верхнего уровня вашего проекта Xcode.

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

    Когда ваше приложение для водителей генерирует и отправляет обновления на серверную часть Fleet Engine, запросы должны включать действительные токены доступа. Для авторизации и аутентификации этих запросов Driver SDK вызывает ваш объект в соответствии с протоколом GMTDAuthorization . Объект отвечает за предоставление необходимого токена доступа.

    Как разработчик приложения вы выбираете, как генерируются токены. Ваша реализация должна обеспечивать возможность делать следующее:

    • Получите токен доступа, возможно, в формате JSON, с HTTPS-сервера.
    • Разберите и кэшируйте токен.
    • Обновите токен по истечении срока его действия.

    Подробную информацию о токенах, ожидаемых сервером Fleet Engine, см. в разделе Создание веб-токена JSON (JWT) для авторизации .

    Идентификатор провайдера совпадает с идентификатором проекта Google Cloud. Для получения дополнительной информации см. Краткое руководство по запуску Fleet Engine .

    В следующем примере реализуется поставщик токенов доступа:

    Быстрый

    import GoogleRidesharingDriver
    
    private let providerURL = "INSERT_YOUR_TOKEN_PROVIDER_URL"
    
    class SampleAccessTokenProvider: NSObject, GMTDAuthorization {
      private struct AuthToken {
        // The cached vehicle token.
        let token: String
        // Keep track of when the token expires for caching.
        let expiration: TimeInterval
        // Keep track of the vehicle ID the cached token is for.
        let vehicleID: String
      }
    
      enum AccessTokenError: Error {
        case missingAuthorizationContext
        case missingData
      }
    
      private var authToken: AuthToken?
    
      func fetchToken(
        with authorizationContext: GMTDAuthorizationContext?,
        completion: @escaping GMTDAuthTokenFetchCompletionHandler
      ) {
        // Get the vehicle ID from the authorizationContext. This is set by the Driver SDK.
        guard let authorizationContext = authorizationContext else {
          completion(nil, AccessTokenError.missingAuthorizationContext)
          return
        }
        let vehicleID = authorizationContext.vehicleID
    
        // If appropriate, use the cached token.
        if let authToken = authToken,
          authToken.expiration > Date.now.timeIntervalSince1970 && authToken.vehicleID == vehicleID
        {
          completion(authToken.token, nil)
          return
        }
    
        // Otherwise, try to fetch a new token from your server.
        let request = URLRequest(url: URL(string: providerURL))
        let task = URLSession.shared.dataTask(with: request) { [weak self] data, _, error in
          guard let strongSelf = self else { return }
          guard error == nil else {
            completion(nil, error)
            return
          }
    
          // Replace the following key values with the appropriate keys based on your
          // server's expected response.
          let vehicleTokenKey = "VEHICLE_TOKEN_KEY"
          let tokenExpirationKey = "TOKEN_EXPIRATION"
          guard let data = data,
            let fetchData = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
            let token = fetchData[vehicleTokenKey] as? String,
            let expiration = fetchData[tokenExpirationKey] as? Double
          else {
            completion(nil, AccessTokenError.missingData)
            return
          }
    
          strongSelf.authToken = AuthToken(
            token: token, expiration: expiration, vehicleID: vehicleID)
          completion(token, nil)
        }
        task.resume()
      }
    }
    

    Цель-C

    #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 {
      // 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 vehicletoken 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
    

    Создайте экземпляр RidesharingDriverAPI.

    Чтобы получить экземпляр GMTDVehicleReporter , сначала необходимо создать экземпляр GMTDRidesharingDriverAPI , используя идентификатор поставщика, идентификатор транспортного средства, driverContext и accessTokenProvider. Идентификатор поставщика совпадает с идентификатором проекта Google Cloud. И вы можете получить доступ к экземпляру GMTDVehicleReporter напрямую из API драйвера.

    В следующем примере создается экземпляр GMTDRidesharingDriverAPI :

    Быстрый

    import GoogleRidesharingDriver
    
    private let providerID = "INSERT_YOUR_PROVIDER_ID"
    
    class SampleViewController: UIViewController {
      private let mapView: GMSMapView
    
      override func viewDidLoad() {
        super.viewDidLoad()
    
        let vehicleID = "INSERT_CREATED_VEHICLE_ID"
        let accessTokenProvider = SampleAccessTokenProvider()
        let driverContext = GMTDDriverContext(
          accessTokenProvider: accessTokenProvider,
          providerID: providerID,
          vehicleID: vehicleID,
          navigator: mapView.navigator)
        let ridesharingDriverAPI = GMTDRidesharingDriverAPI(driverContext: driverContext)
      }
    }
    

    Цель-C

    #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];
    
      GMTDRidesharingDriverAPI *ridesharingDriverAPI = [[GMTDRidesharingDriverAPI alloc] initWithDriverContext:driverContext];
    }
    

    При необходимости прослушивайте события VehicleReporter.

    GMTDVehicleReporter периодически обновляет транспортное средство, если locationTrackingEnabled имеет true . Чтобы реагировать на эти периодические обновления, любой объект может подписаться на события GMTDVehicleReporter соответствуя протоколу GMTDVehicleReporterListener .

    Вы можете обрабатывать следующие события:

    • vehicleReporter(_:didSucceed:)

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

    • vehicleReporter(_:didFail:withError:)

      Сообщает прослушивателю, что обновление транспортного средства не удалось. Пока отслеживание местоположения включено, GMTDVehicleReporter продолжает отправлять последние данные в серверную часть Fleet Engine.

    Следующий пример обрабатывает эти события:

    Быстрый

    import GoogleRidesharingDriver
    
    private let providerID = "INSERT_YOUR_PROVIDER_ID"
    
    class SampleViewController: UIViewController, GMTDVehicleReporterListener {
      private let mapView: GMSMapView
    
      override func viewDidLoad() {
        // Assumes you have implemented the sample code up to this step.
        ridesharingDriverAPI.vehicleReporter.add(self)
      }
    
      func vehicleReporter(_ vehicleReporter: GMTDVehicleReporter, didSucceed vehicleUpdate: GMTDVehicleUpdate) {
        // Handle update succeeded.
      }
    
      func vehicleReporter(_ vehicleReporter: GMTDVehicleReporter, didFail vehicleUpdate: GMTDVehicleUpdate, withError error: Error) {
        // Handle update failed.
      }
    }
    

    Цель-C

    /*
    
        *   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 have implemented the sample code up to this step.
      [ridesharingDriverAPI.vehicleReporter addListener:self];
    }
    
    -   (void)vehicleReporter:(GMTDVehicleReporter *)vehicleReporter didSucceedVehicleUpdate:(GMTDVehicleUpdate *)vehicleUpdate {
      // Handle update succeeded.
    }
    
    -   (void)vehicleReporter:(GMTDVehicleReporter *)vehicleReporter didFailVehicleUpdate:(GMTDVehicleUpdate *)vehicleUpdate withError:(NSError *)error {
      // Handle update failed.
    }
    
    @end
    

    Добавьте GMTDVehicleReporter в качестве прослушивателя GMSRoadSnappedLocationProvider.

    Чтобы предоставлять обновления местоположения в Driver SDK, GMTDVehicleReporter необходимо настроить в качестве прослушивателя GMSRoadSnappedLocationProvider .

    Быстрый

    import GoogleRidesharingDriver
    
    private let providerID = "INSERT_YOUR_PROVIDER_ID"
    
    class SampleViewController: UIViewController, GMTDVehicleReporterListener {
      private let mapView: GMSMapView
    
      override func viewDidLoad() {
        // Assumes you have implemented the sample code up to this step.
        if let roadSnappedLocationProvider = mapView.roadSnappedLocationProvider {
          roadSnappedLocationProvider.add(ridesharingDriverAPI.vehicleReporter)
          roadSnappedLocationProvider.startUpdatingLocation()
        }
      }
    }
    

    Цель-C

    /*
    
        *   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 have implemented the sample code up to this step.
      [_mapView.roadSnappedLocationProvider addListener:ridesharingDriverAPI.vehicleReporter];
      [_mapView.roadSnappedLocationProvider startUpdatingLocation];
    }
    
    @end
    

    Включить отслеживание местоположения

    Чтобы включить отслеживание местоположения, ваше приложение может установить для locationTrackingEnabled значение true в GMTDVehicleReporter . GMTDVehicleReporter автоматически отправляет обновления местоположения. После того, как службы сопоставят и назначат транспортное средство для поездки, GMTDVehicleReporter автоматически отправляет обновления маршрута, когда GMSNavigator находится в режиме навигации (когда пункт назначения задан с помощью setDestinations ).

    Маршрут, установленный во время обновления поездки, будет тем же маршрутом, по которому водитель движется во время сеанса навигации. Таким образом, чтобы совместное использование поездок работало правильно, путевая точка, установленная через setDestinations должна совпадать с пунктом назначения, установленным в серверной части Fleet Engine.

    Если для locationTrackingEnabled установлено значение true , обновления о поездках и транспортных средствах отправляются на серверную часть Fleet Engine через регулярные промежутки времени в зависимости от значения, установленного для locationUpdateInterval . Если для locationTrackingEnabled установлено значение false , обновления прекращаются, и на серверную часть Fleet Engine отправляется окончательный запрос на обновление транспортного средства, чтобы установить состояние транспортного средства на GMTDVehicleState.offline . См. updateVehicleState для получения особых рекомендаций по обработке сбоев, когда locationTrackingEnabled установлено значение false .

    В следующем примере включается отслеживание местоположения:

    Быстрый

    import GoogleRidesharingDriver
    
    private let providerID = "INSERT_YOUR_PROVIDER_ID"
    
    class SampleViewController: UIViewController, GMTDVehicleReporterListener {
      private let mapView: GMSMapView
    
      override func viewDidLoad() {
        // Assumes you have implemented the sample code up to this step.
        ridesharingDriverAPI.vehicleReporter.locationTrackingEnabled = true
      }
    }
    

    Цель-C

    /*
        *   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 have implemented the sample code up to this step.
      ridesharingDriverAPI.vehicleReporter.locationTrackingEnabled = YES;
    }
    
    @end
    

    По умолчанию интервал отчетов составляет 10 секунд, но интервал отчетов можно изменить с помощью locationUpdateInterval . Минимальный поддерживаемый интервал обновления составляет 5 секунд. Максимальный поддерживаемый интервал обновления составляет 60 секунд. Более частые обновления могут привести к замедлению запросов и ошибкам.

    Обновить состояние автомобиля

    В следующем примере показано, как установить состояние автомобиля в ONLINE . Подробности смотрите updateVehicleState .

    Быстрый

    import GoogleRidesharingDriver
    
    private let providerID = "INSERT_YOUR_PROVIDER_ID"
    
    class SampleViewController: UIViewController, GMTDVehicleReporterListener {
      private let mapView: GMSMapView
    
      override func viewDidLoad() {
        // Assumes you have implemented the sample code up to this step.
        ridesharingDriverAPI.vehicleReporter.update(.online)
      }
    }
    

    Цель-C

    #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 have implemented the sample code up to this step.
      [ridesharingDriverAPI.vehicleReporter
                                       updateVehicleState:GMTDVehicleStateOnline];
    }
    
    @end
    

    Ошибка 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
    

    Отключите обновление местоположения и отключите автомобиль от сети.

    Ваше приложение может отключить обновления и отключить автомобиль. Например, когда смена водителя заканчивается, ваше приложение может установить для locationTrackingEnabled значение false . Отключение обновлений также переводит статус автомобиля в OFFLINE на серверной части Fleet Engine.

    Быстрый

    vehicleReporter.locationTrackingEnabled = false
    

    Цель-C

    _vehicleReporter.locationTrackingEnabled = NO;