驱动程序 SDK 使用入门 (iOS)

您可以使用 Driver SDK 为“行程和订单进度”应用提供增强的导航和跟踪功能。Driver SDK 可为按需行程和送货解决方案舰队引擎提供车辆位置和任务更新。

Driver SDK 可让 Fleet Engine 服务和自定义服务了解车辆的位置和状态。例如,车辆可以是 ONLINEOFFLINE,并且车辆位置会随着行程的进行而变化。

最低系统要求

  • 移动设备必须搭载 iOS 14 或更高版本。
  • Xcode 版本 15 或更高版本。
  • 前提条件

    本指南假定您的应用已实现 Navigation SDK,并且 Fleet Engine 后端已设置且可用。不过,示例代码演示了如何设置 Navigation SDK

    您还必须在 Google Cloud 项目中启用 Maps SDK for iOS获取 API 密钥

    项目配置

    Swift Package Manager

    驱动程序 SDK 可通过 Swift Package Manager 安装。如需添加 SDK,请确保您已移除所有现有的驱动程序 SDK 依赖项。

    要将 SDK 添加到新项目或现有项目,请按以下步骤操作:

    1. 打开 Xcode projectworkspace,然后前往 File(文件)> Add Package Dependencies(添加软件包依赖项)
    2. 输入 https://github.com/googlemaps/ios-driver-sdk 作为网址,按 Enter 键拉取软件包,然后点击“Add Package”(添加软件包)。
    3. 如需安装特定的 version,请将依赖项规则字段设置为某个基于版本的选项。对于新项目,我们建议指定最新版本并使用“确切版本”选项。完成后,点击“添加文件包”。
    4. Choose Package Products 窗口中,确认 GoogleRidesharingDriver 会添加到指定的 main 目标。完成后,点击“添加软件包”。
    5. 如需验证安装,请前往目标的 General 窗格。在框架、库和嵌入式内容中,您应该会看到已安装的软件包。 您还可以查看“项目导航器”的“软件包依赖项”部分,以验证软件包及其版本。

    如需更新现有项目的 package,请按以下步骤操作:

    1. 在 Xcode 中,转到“File(文件)> Packages”(软件包)>“Update To Latest Package Versions”(更新软件包版本)”。
    2. 如需验证安装,请前往项目导航器软件包依赖项部分,验证软件包及其版本。

    如需移除使用 CocoaPods 添加的现有驱动程序 SDK 依赖项,请按以下步骤操作:

    1. 关闭 Xcode 工作区。打开终端并执行以下命令:
      sudo gem install cocoapods-deintegrate cocoapods-clean 
      pod deintegrate 
      pod cache clean --all
    2. 如果您不将 PodfilePodfile.resolved 和 Xcode workspace 用于 CocoaPods 以外的其他用途,请移除它们。

    如需手动移除现有的驱动程序 SDK,请按以下步骤操作:

    1. 在 Xcode 项目配置设置中,找到框架、库和嵌入式内容。使用减号 (-) 移除以下框架:

      • GoogleRidesharingDriver.xcframework
    2. 从 Xcode 项目的顶级目录中,移除 GoogleRidesharingDriver 软件包。

    CocoaPods

    如需使用 CocoaPods 配置驱动程序 SDK,您需要以下各项:

    • CocoaPods 工具:如需安装此工具,请打开终端并运行以下命令。
       sudo gem install cocoapods
    
    1. 为驱动程序 SDK 创建 Podfile,并使用它来安装 API 及其依赖项:在项目目录中创建一个名为 Podfile 的文件。此文件定义您项目的依赖项。修改 Podfile 并添加依赖项。以下是包含依赖项的示例:

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

      以下示例包含驱动程序 SDK 的 Alpha 版和 Beta 版 Pod 作为依赖项:

      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. 保存 Podfile。打开一个终端并转到包含 Podfile 的目录:

      cd <path-to-project>
      
    3. 运行 pod 安装命令。此操作会安装 Podfile 中指定的 API 及其可能具有的任何依赖项。

      pod install
      
    4. 关闭 Xcode,然后打开(双击)您项目的 .xcworkspace 文件以启动 Xcode。从此刻开始,您必须使用 .xcworkspace 文件打开项目。

    如需了解详情,请参阅 CocoaPods 入门指南

    手动安装

    XCFramework 是用于安装驱动程序 SDK 的二进制软件包。您可以在多个平台上使用此软件包,包括使用 Apple 芯片的机器。本指南介绍了如何将包含驱动程序 SDK 的 XCFramework 手动添加到您的项目中,以及如何在 Xcode 中配置构建设置。

    下载 SDK 二进制文件和资源:

    1. 解压缩文件以访问 XCFramework 和资源。

    2. 启动 Xcode,并打开现有项目或创建一个新项目。如果您刚开始接触 iOS,请创建一个新项目,然后选择 iOS 应用模板。

    3. 在项目组下创建一个框架组(如果还没有)。

    4. 如需安装驱动程序 SDK,请将 GoogleRidesharingDriver.xcframework 文件拖动到框架、库和嵌入式内容下的项目中。出现提示时,选择“Copy items if needed”。

    5. 将下载的 GoogleRidesharingDriver.bundle 拖到 Xcode 项目的顶级目录中。出现提示时,选择 Copy items if needed

    6. 从项目导航器中选择您的项目,然后选择应用的目标。

    7. 打开“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
      • LocalAuthentication.framework
      • OpenGLES.framework
      • QuartzCore.framework
      • SystemConfiguration.framework
      • UIKit.framework
      • WebKit.framework
    8. 选择您的项目(而不是特定目标),并打开 Build Settings(构建设置)标签页。在 Other Linker Flags 部分中,为调试和发布代码添加 -ObjC。如果看不到这些设置,请在“Build Settings”(构建设置)栏中将过滤条件从 Basic(基本)更改为 All(全部)。

    添加 Apple 隐私清单文件

    1. 下载适用于 iOS 的驱动程序 SDK 的 Privacy Manifest 软件包:GoogleRidesharingDriverPrivacy
    2. 解压缩该文件以访问 GoogleRidesharingDriverPrivacy.bundle
    3. 使用这些方法中的一种GoogleRidesharingDriverPrivacy.bundle 添加到 Xcode 项目导航器中。务必针对应用的目标选中“添加到目标”复选框。添加后,PrivacyInfo 文件会显示在“项目”导航器中,您可以检查相应的值。
    4. Xcode 隐私权信息屏幕截图
    5. 为您的应用创建归档,然后从归档中生成隐私报告,验证隐私清单是否已添加。

    实现授权和身份验证

    当驱动程序应用生成更新并将其发送到 Fleet Engine 后端时,请求必须包含有效的访问令牌。为了对这些请求进行授权和身份验证,Driver SDK 会按照 GMTDAuthorization 协议调用您的对象。该对象负责提供所需的访问令牌。

    作为应用开发者,您可以选择令牌的生成方式。您的实现应能够执行以下操作:

    • 从 HTTPS 服务器提取访问令牌(可能采用 JSON 格式)。
    • 解析并缓存令牌。
    • 请在令牌过期后刷新令牌。

    如需详细了解 Fleet Engine 服务器预期的令牌,请参阅创建 JSON 网络令牌 (JWT) 以进行授权

    提供方 ID 与 Google Cloud 项目 ID 相同。如需了解详情,请参阅 Fleet Engine 快速入门指南

    以下示例实现了访问令牌提供程序:

    Swift

    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()
      }
    }
    

    Objective-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 实例,您首先需要使用 providerID、VehicleID、driverContext 和 accessTokenProvider 创建 GMTDRidesharingDriverAPI 实例。providerID 与 Google Cloud 项目 ID 相同。您也可以直接从 Driver API 访问 GMTDVehicleReporter 实例。

    以下示例创建了一个 GMTDRidesharingDriverAPI 实例:

    Swift

    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)
      }
    }
    

    Objective-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 事件

    locationTrackingEnabledtrue 时,GMTDVehicleReporter 会定期更新车辆。为了响应这些定期更新,任何对象都可以通过符合 GMTDVehicleReporterListener 协议来订阅 GMTDVehicleReporter 事件。

    您可以处理以下事件:

    以下示例处理这些事件:

    Swift

    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.
      }
    }
    

    Objective-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

    为了向驱动程序 SDK 提供位置信息更新,必须将 GMTDVehicleReporter 设置为 GMSRoadSnappedLocationProvider 的监听器。

    Swift

    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()
        }
      }
    }
    

    Objective-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
    

    启用位置跟踪

    如需启用位置信息跟踪,您的应用可以在 GMTDVehicleReporter 上将 locationTrackingEnabled 设置为 trueGMTDVehicleReporter 会自动发送位置信息更新。在服务匹配并将车辆分配给行程后,当 GMSNavigator 处于导航模式(通过 setDestinations 设置目的地时)时,GMTDVehicleReporter 会自动发送路线更新。

    行程更新期间设置的路线将与驾驶员在导航会话期间导航到的路线相同。因此,为了使行程共享正常运行,通过 setDestinations 设置的航点应与在 Fleet Engine 后端中设置的目的地一致。

    如果 locationTrackingEnabled 设置为 true,系统会根据为 locationUpdateInterval 设置的值定期将行程和车辆更新发送到 Fleet Engine 后端。如果 locationTrackingEnabled 设置为 false,系统会停止更新,并向 Fleet Engine 后端发送最终的车辆更新请求,以将车辆状态设置为 GMTDVehicleState.offline。如需了解在 locationTrackingEnabled 设置为 false 时处理失败问题的特殊注意事项,请参阅 updateVehicleState

    以下示例启用了位置跟踪:

    Swift

    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
      }
    }
    

    Objective-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

    Swift

    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)
      }
    }
    

    Objective-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 错误,并且通常发生在启动后的首次更新时。以下示例展示了如何处理此错误:

    Swift

    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
      }
    }
    
    

    Objective-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。停用更新还会在 Fleet Engine 后端将车辆的状态设置为 OFFLINE

    Swift

    vehicleReporter.locationTrackingEnabled = false
    

    Objective-C

    _vehicleReporter.locationTrackingEnabled = NO;