ラスト ワンマイルのフリート ソリューションは現在、一部のお客様のみご利用いただけます。詳しくは、営業担当者までお問い合わせください。

Driver SDK for iOS スタートガイド

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

Driver SDK は、ドライバアプリに統合するライブラリです。ドライバの場所、ルート、残りの距離、ETA は、フリート エンジンによって更新されます。また、Navigation SDK と統合されているため、ドライバーにターンバイターン方式のナビゲーション指示が提供されます。

最小システム要件

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

Prerequisites

このガイドでは、アプリに Navigation SDK がすでに実装され、Fleet Engine バックエンドが設定され、利用可能であることを前提としています。ただし、このサンプルコードでは Navigation SDK をセットアップする方法の例を示します。

また、Google Cloud プロジェクトで Maps SDK for iOS を有効にし、API キーを取得する必要があります。

アクセスの取得

Google Workspace を使用している場合は、オンボーディング時に google-maps-platform-sdk-users@workspacedomain.com などのワークスペース グループを作成し、Google に名前を指定します。これはおすすめの方法です。 次に、ワークスペースが許可リストに追加され、適切な CocoaPods リポジトリへのアクセスが許可されます。アクセス権を必要とするユーザーのメールアドレスとサービス アカウントのメールアドレスがこのリストに含まれていることを確認します。

組織で Workspace グループを作成できない場合は、これらのアーティファクトにアクセスする必要があるユーザーとサービス アカウントのメールアドレスのリストを Google に送信します。

ローカルでの開発

ローカル開発では、Cloud SDK でログインするだけで十分です。

gcloud

gcloud auth login

ログインに使用するメールアドレスは、Workspace グループのメンバーである必要があります。

自動化(ビルドシステムまたは継続的インテグレーション)

ベスト プラクティスに従って自動化ホストを設定します。

  • プロセスが Google Cloud 環境内で実行されている場合は、自動認証情報検出を使用します。

  • それ以外の場合は、ホストのファイル システムの安全な場所にサービス アカウント キー ファイルを保存し、GOOGLE_APPLICATION_CREDENTIALS 環境変数を適切に設定します。

認証情報に関連付けられたサービス アカウントのメールアドレスは、Workspace Goup のメンバーである必要があります。

Project Configuration

Driver SDK は CocoaPods を使用して設定できます。

CocoaPods を使用

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

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

    sudo gem install cocoapods
    

    詳細については、CocoaPods スタートガイドをご覧ください。

  • Google アクセスリストに記載されている開発用アカウント。この SDK の Pod リポジトリは公開ソースではありません。この Pod にアクセスするには、Google カスタマー エンジニアにお問い合わせください。エンジニアが、開発用アカウントをアクセスリストに追加し、認証用に Cookie を設定します。

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

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

    source "https://cpdc-eap.googlesource.com/ridesharing-driver-sdk.git"
    source "https://cpdc-eap.googlesource.com/geo-nav-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 ファイルを使用してプロジェクトを開く必要があります。

認可と認証を実装する

ドライバアプリで更新を生成し、Fleet Engine バックエンドに送信する場合、リクエストに有効なアクセス トークンを含める必要があります。これらのリクエストを認可して認証するため、Driver SDK は GMTDAuthorization プロトコルに準拠したオブジェクトを呼び出します。オブジェクトは、必要なアクセス トークンを提供する役割を担います。

トークンの生成方法はアプリ デベロッパーが選択します。実装では、次の処理を行う必要があります。

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

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

プロバイダ ID は Google Cloud プロジェクト ID と同じです。詳しくは、Fleet Engine Deliveries API ユーザーガイドをご覧ください。

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

#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 {
  if (!completion) {
    NSAssert(NO, @"%s encountered an unexpected nil completion.", __PRETTY_FUNCTION__);
    return;
  }

  // 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 vehicle token 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

DeliveryDriverAPI インスタンスを作成する

GMTDDeliveryVehicleReporter インスタンスを取得するには、まず、providerID、vehicleID、driverContext、accessTokenProvider を使用して GMTDDeliveryDriverAPI インスタンスを作成する必要があります。providerID は、Google Cloud プロジェクト ID と同じです。そのため、ドライバ API から直接 GMTDDeliveryVehicleReporter インスタンスにアクセスできます。

次の例では、GMTDDeliveryDriverAPI インスタンスを作成します。

#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];

  GMTDDeliveryDriverAPI *deliveryDriverAPI = [[GMTDDeliveryDriverAPI alloc] initWithDriverContext:driverContext];
}

必要に応じて、VehicleReporter イベントをリッスンする

GMTDDeliveryVehicleReporter は、locationTrackingEnabled が YES の場合、定期的に車両を更新します。こうした定期的な更新に対応するには、GMTDVehicleReporterListener プロトコルに準拠し、任意のオブジェクトを GMTDDeliveryVehicleReporter イベントに登録します。

次のイベントを処理できます。

  • vehicleReporter:didSucceedVehicleUpdate

    バックエンド サービスが車両の位置情報と状態の更新を受信したことをドライバ アプリに通知します。

  • vehicleReporter:didFailVehicleUpdate:withError

    車両の更新に失敗したことをリスナーに通知します。位置情報の追跡が有効になっている限り、GMTDDeliveryVehicleReporter は引き続き最新のデータを Fleet Engine バックエンドに送信します。

次の例では、これらのイベントを処理します。

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 IMPLEMENTED HAVE THE SAMPLE CODE UP TO THIS STEP.
  [ridesharingDriverAPI.vehicleReporter addListener:self];
}

- (void)vehicleReporter:(GMTDDeliveryVehicleReporter *)vehicleReporter didSucceedVehicleUpdate:(GMTDVehicleUpdate *)vehicleUpdate {
  // Handle update succeeded.
}

- (void)vehicleReporter:(GMTDDeliveryVehicleReporter *)vehicleReporter didFailVehicleUpdate:(GMTDVehicleUpdate *)vehicleUpdate withError:(NSError *)error {
  // Handle update failed.
}

@end

位置情報の記録を有効にする

位置情報のトラッキングを有効にするには、GMTDDeliveryVehicleReporterlocationTrackingEnabledYES に設定します。そうすると、GMTDDeliveryVehicleReporter が位置情報の更新を自動的に送信します。GMSNavigator がナビゲーション モード(setDestinations でデスティネーションが設定されている)で、locationTrackingEnabledYES に設定されている場合、GMTDDeliveryVehicleReporter はルートと到着予定時刻の更新も自動的に送信します。

これらの更新中に設定されたルートは、ドライバーがナビゲーション セッション中に移動したルートと同じになります。したがって、配送追跡が正しく機能するには、-setDestinations:callback: を介して設定された地点が Fleet Engine バックエンドで設定された目的地と一致している必要があります。

次の例では、位置情報トラッキングを有効にしています。

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 IMPLEMENTED HAVE THE SAMPLE CODE UP TO THIS STEP.
  deliveryDriverAPI.vehicleReporter.locationTrackingEnabled = YES;
}

@end

デフォルトではレポート間隔は 10 秒ですが、レポート間隔は locationUpdateInterval で変更できます。サポートされている最小更新間隔は 1 秒です。指定できる更新間隔は最大 60 秒です。更新を頻繁に行うと、リクエストやエラーが遅くなる可能性があります。

位置情報の更新を無効にする

アプリは、車両の位置情報の更新を無効にできます。たとえば、ドライバーのシフトが終了したら、アプリで locationTrackingEnabledNO に設定できます。

  _vehicleReporter.locationTrackingEnabled = NO