On-demand Rides and Deliveries Solution is currently available only to select partners.

Consumer SDK for iOS スタートガイド

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

Consumer SDK を使用して、オンデマンド配車および配達ソリューションのバックエンド サービスと統合した基本的なコンシューマー アプリをビルドして実行できます。有効なルートを表示する、ルートの更新情報に対応する、ルートのエラーを処理する、ルートと注文の進行状況アプリを作成できます。

コンシューマー SDK はモジュール式アーキテクチャであるため、特定のアプリに必要な API のパーツを使用し、独自の API、Fleet Engine が提供するバックエンド サービス、Google Maps Platform の追加の API と統合できます。

最小システム要件

モバイル デバイスが iOS 12 以降を実行している必要があります。

プロジェクト構成

コンシューマ SDK は、手動で、または CocoaPods を使用して構成できます。

CocoaPods を使用

CocoaPods を使用して Consumer SDK を構成するには、次の項目が必要です。

  • CocoaPods ツール: このツールをインストールするには、ターミナルを開いて次のコマンドを実行します。

    sudo gem install cocoapods
    

    詳しくは、CocoaPods スタートガイドをご覧ください。

  • Google アクセスリストのデベロッパー アカウント。SDK の Pod リポジトリは一般公開されません。Pod にアクセスするには、Google カスタマー エンジニアに連絡してください。エンジニアが、開発用アカウントをアクセスリストに追加し、認証用の Cookie を設定します。

プロジェクトがアクセスリストに追加されると、Pod にアクセスできるようになります。

  1. Consumer SDK 用の Podfile を作成し、それを使用して API とその依存関係をインストールします。まず、プロジェクト ディレクトリに Podfile という名前のファイルを作成します。このファイルは、プロジェクトの依存関係を定義します。次に、Podfile を編集して依存関係を追加します。依存関係が含まれている例を次に示します。

    source "https://cpdc-eap.googlesource.com/ridesharing-consumer-sdk"
    source "https://github.com/CocoaPods/Specs.git"
    
    target 'YOUR_APPLICATION_TARGET_NAME_HERE' do
      pod 'GoogleRidesharingConsumer'
    end
    
  2. Podfile を保存します。ターミナルを開き、Podfile を含むディレクトリに移動します。

    cd <path-to-project>
    
  3. Pod のインストール コマンドを実行します。これにより、Podfile で指定された API と、必要な依存関係がインストールされます。

    pod install
    
  4. Xcode を閉じてから、プロジェクトの .xcworkspace ファイルを開く(ダブルクリック)して、Xcode を起動します。後でプロジェクトを開くには、.xcworkspace ファイルを使用します。

手動で構成する

コンシューマ SDK を手動で構成するには:

  1. Maps SDK for iOS をインストールする

    ライドシェアリング フレームワークを使用するには、Maps SDK for iOS(GoogleMaps フレームワーク)が必要です。Maps SDK for iOS のインストールについて詳しくは、Maps SDK for iOS スタートガイドをご覧ください。

  2. ライドシェアリングのフレームワークとリソースを追加する

    1. 受け取ったソースファイル(ridesharing_consumer_ios.zip)を解凍します。

    2. Xcode を起動し、既存のプロジェクトを開くか、新しいプロジェクトを作成します。

    3. プロジェクト ナビゲータからプロジェクトを選択し、アプリケーションのターゲットを選択します。

    4. [Build Phases] タブを開き、[Link Binary with Libraries] 内でプラス記号ボタン(+)をクリックします。

    5. [その他を追加] をクリックして、ライドシェアリングのフレームワークを選択します。

    6. ライドシェアリングのフレームワーク ディレクトリからライドシェアリングのフレームワークを選択GoogleRidesharingConsumer.framework

  3. リソースの追加

    1. Xcode でプロジェクトの [Build Phases] を開き、[Copy Bundle Resources] 内でプラス記号ボタン(+)をクリックします。

    2. [その他を追加] をクリックして、ライドシェアリングのフレームワークを選択します。

    3. ライドシェアリングのフレームワーク ディレクトリから、次のファイルを選択します。

      • GoogleRidesharingConsumer.framework/Resources/GoogleRidesharingConsumer.bundle

      • gRPCCertificates.bundle(プロジェクトですでに gRPC を使用している場合は必須ではありません)。

    4. [ファイルの追加オプションを選択する] で、[必要に応じてアイテムをコピー] をオンにします。

アプリケーションの統合

認証トークンを提供

コンシューマー アプリが Fleet Engine にルートの更新をリクエストする場合、リクエストに有効なアクセス トークンを含める必要があります。これらのリクエストを認可して認証するために、コンシューマ SDK は GMTCAuthorization プロトコルに準拠したオブジェクトを呼び出します。オブジェクトは、必要なアクセス トークンを提供する役割を担います。

アプリ デベロッパーは、トークンの生成方法を選択できます。この実装では、次の機能を提供する必要があります。

  • HTTPS サーバーからアクセス トークン(場合によっては JSON 形式)を取得します。
  • トークンを解析してキャッシュに保存します。
  • 有効期限が切れたらトークンを更新します。

Fleet Engine サーバーが想定するトークンの詳細については、認可用の JSON ウェブトークン(JWT)の作成をご覧ください。

プロバイダ ID は Google Cloud プロジェクト ID と同じです。詳細については、Fleet Engine スタートガイドをご覧ください。

次の例では、アクセス トークン プロバイダを実装します。

Swift

/*
 * SampleAccessTokenProvider.swift
 */
import GoogleRidesharingConsumer

private let providerURL = "INSERT_YOUR_TOKEN_PROVIDER_URL"

class SampleAccessTokenProvider: NSObject, GMTCAuthorization {
  private struct AuthToken {
    // The cached trip token.
    let token: String
    // Keep track of when the token expires for caching.
    let expiration: TimeInterval
    // Keep track of the trip ID the cached token is for.
    let tripID: String
  }

  enum AccessTokenError: Error {
    case missingAuthorizationContext
    case missingData
  }

  private var authToken: AuthToken?

  func fetchToken(
    with authorizationContext: GMTCAuthorizationContext?,
    completion: @escaping GMTCAuthTokenFetchCompletionHandler
  ) {
    // Get the trip ID from the authorizationContext. This is set by the Consumer SDK.
    guard let authorizationContext = authorizationContext else {
      completion(nil, AccessTokenError.missingAuthorizationContext)
      return
    }
    let tripID = authorizationContext.tripID

    // If appropriate, use the cached token.
    if let authToken = authToken,
      authToken.expiration > Date.now.timeIntervalSince1970 && authToken.tripID == tripID
    {
      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 tripTokenKey = "TRIP_TOKEN_KEY"
      let tokenExpirationKey = "TOKEN_EXPIRATION"
      guard let data = data,
        let fetchData = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
        let token = fetchData[tripTokenKey] as? String,
        let expiration = fetchData[tokenExpirationKey] as? Double
      else {
        completion(nil, AccessTokenError.missingData)
        return
      }

      strongSelf.authToken = AuthToken(token: token, expiration: expiration, tripID: tripID)
      completion(token, nil)
    }
    task.resume()
  }
}

Objective-C

/*
 * SampleAccessTokenProvider.h
 */
#import <Foundation/Foundation.h>
#import <GoogleRidesharingConsumer/GoogleRidesharingConsumer.h>

NS_ASSUME_NONNULL_BEGIN

@interface SampleAccessTokenProvider : NSObject <GMTCAuthorization>

@end

NS_ASSUME_NONNULL_END

/*
 * SampleAccessTokenProvider.m
 */
#import "SampleAccessTokenProvider.h"
#import "GoogleRidesharingConsumer/GoogleRidesharingConsumer.h"

static NSString *const PROVIDER_URL = @"INSERT_YOUR_TOKEN_PROVIDER_URL";

// SampleAccessTokenProvider.m
@implementation SampleAccessTokenProvider {
  // The cached token with claims to the current trip.
  NSString *_cachedTripToken;
  // Keep track of the Trip ID the cached token is for.
  NSString *_lastKnownTripID;
  // Keep track of when tokens expire for caching.
  NSTimeInterval _tokenExpiration;
}

- (void)fetchTokenWithContext:(nullable GMTCAuthorizationContext *)authorizationContext
                   completion:(nonnull GMTCAuthTokenFetchCompletionHandler)completion {
  // Get the trip ID from the authorizationContext. This is set by the Consumer SDK.
  NSString *tripID = authorizationContext.tripID;

  // Clear cached trip token if trip ID has changed.
  if (![_lastKnownTripID isEqual:tripID]) {
    _tokenExpiration = 0.0;
    _cachedTripToken = nil;
  }
  _lastKnownTripID = tripID;

  // Clear cached tripToken if it has expired.
  if ([[NSDate date] timeIntervalSince1970] > _tokenExpiration) {
    _cachedTripToken = nil;
  }

  // If appropriate, use the cached token.
  if (_cachedTripToken) {
    completion(_cachedTripToken, 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 *tripTokenKey = @"TRIP_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->_cachedTripToken = JSONResponse[tripTokenKey];
          completion(JSONResponse[tripTokenKey], 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

アプリケーションの初期化

Swift

/*
 * AppDelegate.swift
 */
import GoogleRidesharingConsumer
import GoogleMaps

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

  func application(_ application: UIApplication,
      didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Register your API key for GMSServices.
    GMSServices.provideAPIKey(yourMapsAPIKey)

    // Set the instance of the SampleAccessTokenProvider.
    GMTCServices.setAccessTokenProvider(SampleAccessTokenProvider(), providerID: yourProviderID)

    // Other initialization code ...
    return true
  }
}

Objective-C

/*
 * AppDelegate.m
 */
#import <GoogleMaps/GoogleMaps.h>
#import <GoogleRidesharingConsumer/GoogleRidesharingConsumer.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  //Register your API key for GMSServices.
  [GMSServices provideAPIKey:yourMapsAPIKey];

  //Set the instance of the AccessTokenFactory.
  [GMTCServices setAccessTokenProvider:[[SampleAccessTokenProvider alloc] init]
                            providerID:yourProviderID];

  // Other initialization code ...
  return YES;
}

@end

地図表示の統合

地図表示を初期化する

次の例は、GMTCMapView を初期化する方法を示しています。

Swift

/*
 * MapViewController.swift
 */
class ViewController: UIViewController, GMTCMapViewDelegate {
  private var rideSharingMap: GMTCMapView?

  override func viewDidLoad() {
    super.viewDidLoad()

    self.rideSharingMap = GMTCMapView(frame: UIScreen.main.bounds)
    self.rideSharingMap.delegate = self
    self.rideSharingMap?.settings.myLocationButton = true
    self.view.addSubview(self.rideSharingMap!)
    ...
  }

Objective-C

/*
 * MapViewController.h
 */
@interface MapViewController : UIViewController<GMTCMapViewDelegate>
...
@end

/*
 * MapViewController.m
 */
@implementation MapViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  ...
  self.mapView = [[GMTCMapView alloc] init];
  self.mapView.settings.myLocationButton = YES;
  self.mapView.delegate = self;
  ...
}

...

@end

地図表示イベントを処理する

次の例は、ユーザーの状態のイベントを処理するデリゲートの実装方法を示しています。

Swift

func mapViewDidInitialize(_ mapview: GMTCMapView) {
  // Handle the update to the state of the map view to browsing.
}

func mapView(_ mapView: GMSMapView, didTapConsumerMarker mapMarker: GMSMarker, markerType: GMTCMapViewMarkerType) -> Bool {
  // Handle the mapView marker was tapped.
}

Objective-C

/*
 * MapViewController.m
 */
#pragma mark - GMTCMapViewDelegate implementation

// Handle state update of map view.
- (void)mapViewDidInitializeCustomerState:(GMTCMapView *)mapview {
  // Handle the update to the state of the map view to browsing.
}

- (void)mapView:(GMSMapView *)mapView
    didTapConsumerMarker:(nonnull GMSMarker *)mapMarker
              markerType:(GMTCMapViewMarkerType)markerType {
  // Handle the mapView marker was tapped.
}

ジャーニーの共有

ビューの読み込み時に新しいルートを開始

次の例は、ビューが読み込まれた直後にジャーニーの共有を開始する方法を示しています。ViewController から降車や乗車場所などのユーザー入力をすべて収集してから、新しい ViewController を作成してプロセスを直接共有できます。

Swift

/*
 * MapViewController.swift
 */
override func viewDidLoad() {
  super.viewDidLoad()
  ...
  self.mapView = GMTCMapView(frame: UIScreen.main.bounds)
  self.mapView.delegate = self
  self.view.addSubview(self.mapView)
}

func mapViewDidInitializeCustomerState(_: GMTCMapView) {
  self.mapView.pickupLocation = self.selectedPickupLocation
  self.mapView.dropoffLocation = self.selectedDropoffLocation

  self.startConsumerMatchWithLocations(
    pickupLocation: self.mapView.pickupLocation!,
    dropoffLocation: self.mapView.dropoffLocation!
  ) { [weak self] (tripName, error) in
    guard let strongSelf = self else { return }
    if error != nil {
      // print error message.
      return
    }
    let tripService = GMTCServices.shared().tripService
    // Create a tripModel instance for listening the update of the trip
    // specified by this trip name.
    let tripModel = tripService.tripModel(forTripName: tripName)
    // Create a journeySharingSession instance based on the tripModel
    let journeySharingSession = GMTCJourneySharingSession(tripModel: tripModel)
    // Add the journeySharingSession instance on the mapView for UI updating.
    strongSelf.mapView.show(journeySharingSession)
    // Register for the trip update events.
    tripModel.register(strongSelf)

    strongSelf.currentTripModel = tripModel
    strongSelf.currentJourneySharingSession = journeySharingSession
    strongSelf.hideLoadingView()
  }

  self.showLoadingView()
}

Objective-C

/*
 * MapViewController.m
 */
- (void)viewDidLoad {
  [super viewDidLoad];
  ...
  self.mapView = [[GMTCMapView alloc] init];
  self.mapView.delegate = self;
  [self.view addSubview:self.mapView];
}

// Handle the callback when the GMTCMapView did initialized.
- (void)mapViewDidInitializeCustomerState:(GMTCMapView *)mapview {
  self.mapView.pickupLocation = self.selectedPickupLocation;
  self.mapView.dropoffLocation = self.selectedDropoffLocation;

  __weak __typeof(self) weakSelf = self;
  [self startTripBookingWithPickupLocation:self.selectedPickupLocation
                           dropoffLocation:self.selectedDropoffLocation
                                completion:^(NSString *tripName, NSError *error) {
                                  __typeof(self) strongSelf = weakSelf;
                                  GMTCTripService *tripService = [GMTCServices sharedServices].tripService;
                                  // Create a tripModel instance for listening to updates to the trip specified by this trip name.
                                  GMTCTripModel *tripModel = [tripService tripModelForTripName:tripName];
                                  // Create a journeySharingSession instance based on the tripModel.
                                  GMTCJourneySharingSession *journeySharingSession =
                                    [[GMTCJourneySharingSession alloc] initWithTripModel:tripModel];
                                  // Add the journeySharingSession instance on the mapView for updating the UI.
                                  [strongSelf.mapView showMapViewSession:journeySharingSession];
                                  // Register for trip update events.
                                  [tripModel registerSubscriber:self];

                                  strongSelf.currentTripModel = tripModel;
                                  strongSelf.currentJourneySharingSession = journeySharingSession;
                                  [strongSelf hideLoadingView];
                                }];
    [self showLoadingView];
}

アクティブなルートをキャンセル

次の例は、現在アクティブなルートをリセットする方法を示しています。

Swift

/*
 * MapViewController.swift
 */
func cancelCurrentActiveTrip() {
  // Stop the tripModel
  self.currentTripModel.unregisterSubscriber(self)

  // Remove the journey sharing session from the mapView's UI stack.
  self.mapView.hide(journeySharingSession)
}

Objective-C

/*
 * MapViewController.m
 */
- (void)cancelCurrentActiveTrip {
  // Stop the tripModel
  [self.currentTripModel unregisterSubscriber:self];

  // Remove the journey sharing session from the mapView's UI stack.
  [self.mapView hideMapViewSession:journeySharingSession];
}

ルートの更新情報を聞く

次の例は、tripModel コールバックを登録する方法を示しています。

Swift

/*
 * MapViewController.swift
 */
override func viewDidLoad() {
  super.viewDidLoad()
  // Register for trip update events.
  self.currentTripModel.register(self)
}

Objective-C

/*
 * MapViewController.m
 */
- (void)viewDidLoad {
  [super viewDidLoad];
  // Register for trip update events.
  [self.currentTripModel registerSubscriber:self];
  ...
}

次の例は、tripModel コールバックの登録をキャンセルする方法を示しています。

Swift

/*
 * MapViewController.swift
 */
deinit {
  self.currentTripModel.unregisterSubscriber(self)
}

Objective-C

/*
 * MapViewController.m
 */
- (void)dealloc {
  [self.currentTripModel unregisterSubscriber:self];
  ...
}

次の例は、ルートの状態が更新された場合のコールバックを処理するための GMTCTripModelSubscriber プロトコルを実装する方法を示しています。

Swift

/*
 * MapViewController.swift
 */
func tripModel(_: GMTCTripModel, didUpdate trip: GMTSTrip?, updatedPropertyFields: GMTSTripPropertyFields) {
  // Update the UI with the new `trip` data.
  self.updateUI(with: trip)
}

func tripModel(_: GMTCTripModel, didUpdate tripStatus: GMTSTripStatus) {
  // Handle trip status did change.
}

func tripModel(_: GMTCTripModel, didUpdateActiveRouteRemainingDistance activeRouteRemainingDistance: Int32) {
  // Handle remaining distance of active route did update.
}

func tripModel(_: GMTCTripModel, didUpdateActiveRoute activeRoute: [GMTSLatLng]?) {
  // Handle trip active route did update.
}

func tripModel(_: GMTCTripModel, didUpdate vehicleLocation: GMTSVehicleLocation?) {
  // Handle vehicle location did update.
}

func tripModel(_: GMTCTripModel, didUpdatePickupLocation pickupLocation: GMTSTerminalLocation?) {
  // Handle pickup location did update.
}

func tripModel(_: GMTCTripModel, didUpdateDropoffLocation dropoffLocation: GMTSTerminalLocation?) {
  // Handle drop off location did update.
}

func tripModel(_: GMTCTripModel, didUpdatePickupETA pickupETA: TimeInterval) {
  // Handle the pickup ETA did update.
}

func tripModel(_: GMTCTripModel, didUpdateDropoffETA dropoffETA: TimeInterval) {
  // Handle the drop off ETA did update.
}

func tripModel(_: GMTCTripModel, didUpdateRemaining remainingWaypoints: [GMTSTripWaypoint]?) {
  // Handle updates to the pickup, dropoff or intermediate destinations of the trip.
}

func tripModel(_: GMTCTripModel, didFailUpdateTripWithError error: Error?) {
  // Handle the error.
}

func tripModel(_: GMTCTripModel, didUpdateIntermediateDestinations intermediateDestinations: [GMTSTerminalLocation]?) {
  // Handle the intermediate destinations being updated.
}

func tripModel(_: GMTCTripModel, didUpdateActiveRouteTraffic activeRouteTraffic: GMTSTrafficData?) {
  // Handle trip active route traffic being updated.
}

Objective-C

/*
 * MapViewController.m
 */
#pragma mark - GMTCTripModelSubscriber implementation

- (void)tripModel:(GMTCTripModel *)tripModel
            didUpdateTrip:(nullable GMTSTrip *)trip
    updatedPropertyFields:(enum GMTSTripPropertyFields)updatedPropertyFields {
  // Update the UI with the new `trip` data.
  [self updateUIWithTrip:trip];
  ...
}

- (void)tripModel:(GMTCTripModel *)tripModel didUpdateTripStatus:(enum GMTSTripStatus)tripStatus {
  // Handle trip status did change.
}

- (void)tripModel:(GMTCTripModel *)tripModel
    didUpdateActiveRouteRemainingDistance:(int32_t)activeRouteRemainingDistance {
   // Handle remaining distance of active route did update.
}

- (void)tripModel:(GMTCTripModel *)tripModel
    didUpdateActiveRoute:(nullable NSArray<GMTSLatLng *> *)activeRoute {
  // Handle trip active route did update.
}

- (void)tripModel:(GMTCTripModel *)tripModel
    didUpdateVehicleLocation:(nullable GMTSVehicleLocation *)vehicleLocation {
  // Handle vehicle location did update.
}

- (void)tripModel:(GMTCTripModel *)tripModel
    didUpdatePickupLocation:(nullable GMTSTerminalLocation *)pickupLocation {
  // Handle pickup location did update.
}

- (void)tripModel:(GMTCTripModel *)tripModel
    didUpdateDropoffLocation:(nullable GMTSTerminalLocation *)dropoffLocation {
  // Handle drop off location did update.
}

- (void)tripModel:(GMTCTripModel *)tripModel didUpdatePickupETA:(NSTimeInterval)pickupETA {
  // Handle the pickup ETA did update.
}

- (void)tripModel:(GMTCTripModel *)tripModel
    didUpdateRemainingWaypoints:(nullable NSArray<GMTSTripWaypoint *> *)remainingWaypoints {
  // Handle updates to the pickup, dropoff or intermediate destinations of the trip.
}

- (void)tripModel:(GMTCTripModel *)tripModel didUpdateDropoffETA:(NSTimeInterval)dropoffETA {
  // Handle the drop off ETA did update.
}

- (void)tripModel:(GMTCTripModel *)tripModel didFailUpdateTripWithError:(nullable NSError *)error {
  // Handle the error.
}

- (void)tripModel:(GMTCTripModel *)tripModel
    didUpdateIntermediateDestinations:
        (nullable NSArray<GMTSTerminalLocation *> *)intermediateDestinations {
  // Handle the intermediate destinations being updated.
}

- (void)tripModel:(GMTCTripModel *)tripModel
    didUpdateActiveRouteTraffic:(nullable GMTSTrafficData *)activeRouteTraffic {
  // Handle trip active route traffic being updated.
}

エラー処理

tripModel を定期購入し、エラーが発生した場合は、デリゲート API tripModel:didFailUpdateTripWithError: を実装することで tripModel のコールバックを取得できます。Fleet Engine が Google Cloud Error Standard に準拠するエラー メッセージを生成しました。エラー メッセージの詳細な定義とすべてのエラーコードについては、Google Cloud のエラーに関するドキュメントをご覧ください。

具体的には、ルートをモニタリングするには、有効な認証トークンを指定する必要があります。トークンの期限切れなど、有効な認証情報がない場合は 401 UNAUTHENTICATED が発生します。呼び出し元に特定の API を呼び出す権限がない場合(たとえば、コンシューマ ロールを持つユーザーが updateTrip の呼び出しを試行した場合)、JWT トークンに有効な Vehicle_id / trip_id がない場合、403 PERMISSION_DENIED が発生します。

詳しくは、Consumer SDK Error Handling をご覧ください。

UI のカスタマイズ

カスタムのポリライン UI オプションを取得/設定する

次の例は、ポリラインにカスタム UI オプションを設定する方法を示しています。

Swift

/** MapViewController.swift */

func updatePolylineUIOptions() {
  // The polyline type that you would like to set custom UI options for.
  let customizablePolylineType = GMTCPolylineType.activeRoute

  let polylineStyleOptions = GMTCMutablePolylineStyleOptions()
  polylineStyleOptions.strokeWidth = 8.0
  polylineStyleOptions.strokeColor = .blue
  polylineStyleOptions.isVisible = true
  polylineStyleOptions.zIndex = 1000
  polylineStyleOptions.isGeodesic = true
  let coordinator = self.mapView.consumerMapStyleCoordinator
  coordinator.setPolylineStyleOptions(polylineStyleOptions, polylineType:customizablePolylineType)
}

Objective-C

/** MapViewController.m */

- (void)updatePolylineUIOptions {
  // The polyline type that you would like to set custom UI options for.
  GMTCPolylineType customizablePolylineType = GMTCPolylineTypeActiveRoute;

  GMTCMutablePolylineStyleOptions *polylineStyleOptions =
      [[GMTCMutablePolylineStyleOptions alloc] init];
  polylineStyleOptions.strokeWidth = 8.0;
  polylineStyleOptions.strokeColor = [UIColor blueColor];
  polylineStyleOptions.isVisible = YES;
  polylineStyleOptions.zIndex = 1000;
  polylineStyleOptions.isGeodesic = YES;
  [[_mapView consumerMapStyleCoordinator] setPolylineStyleOptions:polylineStyleOptions
                                                polylineType:customizablePolylineType];
}

カスタム マーカー UI オプションの取得/設定

次の例は、マーカーのカスタム UI オプションを設定する方法を示しています。

Swift

/** MapViewController.swift */

func updateMarkerUIOptions() {
  let customizableMarkerType = GMTCCustomizableMarkerType.tripVehicle
  let markerStyleOptions = GMTCMutableMarkerStyleOptions()
  markerStyleOptions.groundAnchor = groundAnchor
  markerStyleOptions.isVisible = true
  markerStyleOptions.icon = icon
  markerStyleOptions.zIndex = 100
  markerStyleOptions.isFlat = false
  let coordinator = self.mapView.consumerMapStyleCoordinator
  coordinator.setMarkerStyleOptions(markerStyleOptions, markerType: customizableMarkerType)
}

Objective-C

/** MapViewController.m */

- (void)updateMarkerUIOptions {
  // The marker type that you would like to set custom UI options for.
  GMTCCustomizableMarkerType customizableMarkerType = GMTCCustomizableMarkerTypeTripVehicle;

  GMTCMutableMarkerStyleOptions *markerStyleOptions =
      [[GMTCMutableMarkerStyleOptions alloc] init];
  markerStyleOptions.groundAnchor = groundAnchor;
  markerStyleOptions.isVisible = YES;
  markerStyleOptions.icon = icon;
  markerStyleOptions.zIndex = 100;
  markerStyleOptions.isFlat = NO;

  [[_mapView consumerMapStyleCoordinator] setMarkerStyleOptions:markerStyleOptions markerType:customizableMarkerType];
}

カメラのズームの調整

Maps SDK for iOS の現在地ボタンでは、ユーザーの現在地がカメラの中心に配置されます。

アクティブなジャーニー共有セッションがある場合は、ユーザーの現在地だけでなく、ジャーニーに集中するようにカメラの中心を設定できます。

Consumer SDK に用意されている自動カメラ機能は、デフォルトで有効になっています。カメラが経路の共有経路と次のルートの地点にズームします。

自動カメラ

カメラの動作をより細かく制御する必要がある場合は、allowCameraAutoUpdate プロパティを使用して自動カメラ機能を有効または無効にできます。

カメラのカスタマイズについて詳しくは、Maps SDK for iOS のカメラの移動をご覧ください。