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

您可以使用驱动程序 SDK 为您的 行程和订单进度应用。Driver SDK 提供的是 对按需乘车和送货解决方案舰队引擎的位置和任务更新。

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

最低系统要求

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

    本指南假定您的应用已实现导航 SDK舰队 引擎 后端已设置完毕且可用不过,示例代码提供了一个 如何设置 Navigation SDK

    您还必须启用 Maps SDK for iOS 创建 Google Cloud 项目,并获取 API 密钥

    项目配置

    Swift Package Manager

    驱动程序 SDK 可通过 进行安装 Swift Package Manager 的相关文档。要添加 SDK,请确保您已 移除了所有现有的驱动程序 SDK 依赖项。

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

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

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

    1. 如果您要从 9.0.0 之前的版本升级,就必须移除 以下依赖项:GoogleMapsBaseGoogleMapsCoreGoogleMapsM4B。请勿移除 GoogleMaps。有关详情,请参阅 9.0.0 版版本说明

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

      • GoogleMapsBase(仅适用于从 9.0.0 之前的版本进行的升级)
      • GoogleMapsCore(仅适用于从 9.0.0 之前的版本进行的升级)
      • GoogleMapsM4B(仅适用于从 9.0.0 之前的版本进行的升级)
    2. 在 Xcode 中,转到“File”(文件)>文件包 >更新到最新的软件包版本”。
    3. 如需验证安装,请前往 Project NavigatorPackage Dependencies 部分 以验证软件包及其版本。
    。 <ph type="x-smartling-placeholder">

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

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

    如需移除已安装的现有驱动程序 SDK 请按照以下步骤操作:

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

      • 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 作为依赖项:

      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 install 命令。这会安装 Podfile 及其可能具有的任何依赖项。

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

    请参阅 CocoaPods 使用入门 指南,了解更多信息 。

    手动安装

    XCFramework 是一个二进制包,用于将 驱动程序 SDK。你可以将此软件包用于 平台,包括使用 Apple 设备的计算机 硅。本指南介绍了如何 手动添加包含 将驱动程序 SDK 添加到项目中并配置 build Xcode 中的设置

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

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

    2. 启动 Xcode,并打开现有项目或创建新项目 项目。如果您是第一次使用 iOS,请创建一个新项目,并选择 iOS 应用模板。

    3. 在项目组下创建一个框架组(如果不存在) 。

    4. 要安装驱动程序 SDK,请拖动 GoogleRidesharingDriver.xcframework 文件复制到位于以下位置的项目中: 框架、库和嵌入式内容。出现提示时,选择 根据需要复制内容。

    5. 将已下载的“GoogleRidesharingDriver.bundle”拖动到顶层 目录中。出现提示时,选择 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 设置标签页。在 Other Linker Flags(其他链接器标记)部分中,添加 -ObjC 调试和发布。如果看不到这些设置,请更改 “Build Settings”(构建设置)栏中将过滤条件从“Basic”(基本)更改为“All”(全部)。

    检查 Apple 隐私清单文件

    Apple 要求为 App Store 中的应用提供应用隐私权详细信息。如需了解最新动态和更多信息,请访问 Apple App Store 隐私权详情页面

    Apple 隐私清单文件包含在 SDK 的资源包中。如需验证隐私清单文件是否包含在内并检查其内容,请创建应用的归档,并从归档中生成隐私报告

    实现授权和身份验证

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

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

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

    如需详细了解 Fleet Engine 服务器预期的令牌,请参阅创建 JSON Web 令牌 (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 的 GMTDRidesharingDriverAPI 实例, driveContext 和 accessTokenProvider。providerID 与 Google 相同 Cloud 项目 ID。您可以从以下位置访问 GMTDVehicleReporter 实例: Driver API

    以下示例将创建一个 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 事件

    GMTDVehicleReporter会定期在下列情况下更新车辆: “locationTrackingEnabled”为“true”。为了应对这些定期更新, 对象可以订阅 GMTDVehicleReporter 事件,方法是遵循 GMTDVehicleReporterListener 协议。

    您可以处理以下事件:

    以下示例会处理这些事件:

    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
    

    启用位置跟踪

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

    在行程更新期间设置的路线将与驾驶员的路线相同 在导航会话期间导航到哪里。因此,若要让行程分享功能发挥作用, 正确,通过 setDestinations 设置的航点应与 Fleet Engine 后端中设置的目标位置。

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

    以下示例启用位置跟踪:

    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;