開始使用 iOS 版 Driver SDK

您可以使用 Driver SDK,為行程和訂單進度應用程式提供強化的導航和追蹤功能。Driver SDK 針對隨選乘車和運送服務解決方案機群引擎,提供車輛位置和工作更新。

驅動程式 SDK 可讓 Fleet Engine 服務和您的自訂服務掌握車輛的位置和狀態。舉例來說,車輛可以是 ONLINEOFFLINE,且車輛位置會隨著行程進展而改變。

基本系統需求

  • 行動裝置必須搭載 iOS 14 以上版本。
  • Xcode 15 以上版本。
  • 先備知識

    本指南假設應用程式已實作 Navigation SDK,且 Fleet Engine 後端已設定完成並可供使用。不過,範例程式碼提供了設定 Navigation SDK 的範例。

    您也必須在 Google Cloud 專案中啟用 Maps SDK for iOS,然後取得 API 金鑰

    專案設定

    Swift 套件管理工具

    您可以透過 Swift 套件管理工具安裝驅動程式 SDK。如要新增 SDK,請確認您已移除所有現有的驅動程式 SDK 依附元件。

    如要將 SDK 加入新專案或現有專案,請按照下列步驟操作:

    1. 開啟 Xcode projectworkspace,然後依序前往「File」>「Add Package Dependencies」
    2. 輸入 https://github.com/googlemaps/ios-driver-sdk 做為網址,按下 Enter 鍵提取套件,然後按一下「Add Package」。
    3. 如要安裝特定的 version,請將「依附元件規則」欄位設為其中一個以版本為基礎的選項。如果是新專案,建議您指定最新版本並使用「精確版本」選項。完成後,按一下「新增套件」。
    4. 在「選擇套件產品」視窗中,確認 GoogleRidesharingDriver 會新增至指定的 main 目標。完成後,按一下「新增套件」。
    5. 如要驗證安裝狀態,請前往目標的 General 窗格。在「Frameworks、Library and Embedded Content」中應會顯示已安裝的套件。您也可以查看「Project Navigator」的「Package Dependencies」部分,確認套件及其版本。

    如要更新現有專案的 package,請按照下列步驟操作:

    1. 如果您要從 9.0.0 以下版本升級,必須在升級後移除下列依附元件:GoogleMapsBaseGoogleMapsCoreGoogleMapsM4B。請勿移除 GoogleMaps 的依附元件。詳情請參閱 9.0.0 版本資訊

      在 Xcode 專案設定設定中,找到「Frameworks、Library 和 Embedded Content」。請使用減號(-) 移除下列架構:

      • GoogleMapsBase (僅適用於 9.0.0 以下版本的升級作業)
      • GoogleMapsCore (僅適用於 9.0.0 以下版本的升級作業)
      • GoogleMapsM4B (僅適用於 9.0.0 以下版本的升級作業)
    2. 在 Xcode 中,前往 [檔案] > [套件] > [更新至最新套件版本]。
    3. 如要驗證安裝狀態,請前往「Project Navigator」的「Package Dependencies」部分,檢查套件及其版本。

    如要移除使用 CocoaPods 新增的現有驅動程式 SDK 依附元件,請按照下列步驟操作:

    1. 關閉 Xcode 工作區。開啟終端機並執行下列指令:
      sudo gem install cocoapods-deintegrate cocoapods-clean 
      pod deintegrate 
      pod cache clean --all
    2. 如果您未在 CocoaPods 以外的地方使用 PodfilePodfile.resolved 和 Xcode workspace,請移除這些項目。

    如要移除手動安裝的現有驅動程式 SDK,請按照下列步驟操作:

    1. 在 Xcode 專案設定設定中,找到「Frameworks、Libraries and Embedded Content」,請使用減號(-) 移除下列架構:

      • GoogleRidesharingDriver.xcframework
    2. 從 Xcode 專案的頂層目錄中,移除 GoogleRidesharingDriver 軟體包。

    CocoaPods

    如要使用 CocoaPods 設定 Driver 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,以及這些 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 檔案拖曳到專案「Frameworks、Library」(程式庫) 和「Embedded Content」(嵌入的內容) 下方。系統顯示提示時,視需要選取「Copy items」(複製項目)。

    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. 選擇您的專案 (而非特定目標),然後開啟「Build Settings」分頁。在「Other Linker Flags」部分中,為偵錯和發布版本新增 -ObjC。如果您沒有看到這些設定,請將「Build Settings」列中的篩選器從「Basic」變更為「All」

    新增 Apple 隱私權資訊清單檔案

    Apple 要求在 App Store 上架應用程式,要求取得應用程式隱私權詳細資訊。如需最新資訊和其他資訊,請前往 Apple App Store 隱私權詳細資料頁面

    1. 下載適用於 iOS 的 Driver SDK 隱私權資訊清單套件:GoogleRidesharingDriverPrivacy
    2. 解壓縮檔案以存取 GoogleRidesharingDriverPrivacy.bundle
    3. 使用這些方法,將 GoogleRidesharingDriverPrivacy.bundle 新增至 Xcode 專案導覽器。確認應用程式的目標已勾選「新增至目標」方塊。PrivacyInfo 檔案一經新增,就會顯示在專案導覽工具中,方便你查看。
    4. Xcode 隱私權資訊螢幕擷取畫面
    5. 建立應用程式的封存檔案,並透過封存檔案產生隱私權報告,確認您已新增隱私權資訊清單。

    實作授權和驗證

    當驅動程式應用程式產生更新並傳送至 Fleet Engine 後端時,要求必須包含有效的存取權杖。為了授權及驗證這些要求,驅動程式 SDK 會呼叫符合 GMTDAuthorization 通訊協定的物件。這個物件負責提供必要的存取權杖

    應用程式開發人員可以選擇產生權杖的產生方式,您的實作結果應能夠執行下列操作:

    • 從 HTTPS 伺服器擷取存取權杖 (可能為 JSON 格式)。
    • 剖析及快取權杖。
    • 請在權杖過期時重新整理。

    如要進一步瞭解 Fleet Engine 伺服器預期的權杖,請參閱建立用於授權的 JSON Web Token (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、carID、driverContext 和 accessTokenProvider 建立 GMTDRidesharingDriverAPI 執行個體。providerID 與 Google Cloud 專案 ID 相同。也可以直接從驅動程式 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 會自動傳送位置更新資訊。服務比對相符並將車輛指派給行程後,GMTDVehicleReporter 會在 GMSNavigator 處於導航模式 (如果目的地是透過 setDestinations 設定) 時自動傳送路線更新資訊。

    行程更新期間設定的路徑,與駕駛人在導航工作階段中前往的路線。因此,為了讓旅程共用正常運作,透過 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;