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

Consumer SDK for Android のスタートガイド

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

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

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

最小システム要件

モバイル デバイスが Android 5.0(API レベル 21)以降を実行している必要があります。

Prerequisites

輸送と物流の Android SDK は、Artifact Registry Maven リポジトリに公開されます。リポジトリには、SDK のプロジェクト オブジェクト モデル(.pom)ファイルとオフライン Javadocs が含まれています。

アクセス権の取得

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

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

ローカルでの開発

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

gcloud

gcloud auth login

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

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

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

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

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

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

構成

ユーザーまたはサービスの認証情報を自動的に検出するように Maven または Gradle を構成します。

Gradle

プロジェクト ルート モジュール build.gradle ファイルではなく、アプリ モジュールの build.gradle ファイルに追加します。

plugins {
  id "com.google.cloud.artifactregistry.gradle-plugin" version "2.1.5"
}
repositories {
  maven {
    url "artifactregistry://us-west2-maven.pkg.dev/gmp-artifacts/transportation"
  }
}

Maven

pom.xml に次の行を追加します。

<repositories>
  <repository>
    <id>gmp-artifacts</id>
    <url>artifactregistry://us-west2-maven.pkg.dev/gmp-artifacts/transportation</url>
    <releases>
      <enabled>true</enabled>
    </releases>
  </repository>
</repositories>
<build>
  <extensions>
    <extension>
      <groupId>com.google.cloud.artifactregistry</groupId>
      <artifactId>artifactregistry-maven-wagon</artifactId>
      <version>2.1.5</version>
    </extension>
  </extensions>
</build>

アクセスの確認については、Java パッケージの管理をご覧ください。

Project Configuration

Consumer SDK for Android を使用するには、アプリで minSdkVersion 19 以降をターゲットにする必要があります。

Consumer SDK を使用してビルドされたアプリを実行するには、Android デバイスに Google Play 開発者サービスがインストールされている必要があります。

開発プロジェクトを設定する

開発プロジェクトを設定して、Google Cloud Console でプロジェクトの API キーを取得するには:

  1. Consumer SDK で使用する Google Cloud Console プロジェクトを新規作成するか、既存のプロジェクトを選択します。新しいプロジェクトが Google Cloud Console に表示されるまで数分待ちます。

  2. デモアプリを実行するには、プロジェクトに Maps SDK for Android へのアクセス権が付与されている必要があります。Google Cloud Console で、[API とサービス] > [ライブラリ] を選択し、Maps SDK for Android を検索して有効にします。

  3. プロジェクトの API キーを取得するには、[API とサービス] > [認証情報] > [認証情報を作成] > [API キー] を選択します。API キーの取得について詳しくは、API キーを取得するをご覧ください。

コンシューマ SDK をアプリに追加する

Consumer SDK は、専用の Maven リポジトリを介して入手できます。リポジトリには、SDK の Project Object Model(.pom)ファイルと Javadocs が含まれています。コンシューマ SDK をアプリに追加するには:

  1. アクセス権の取得の説明に従って、ホスト Maven リポジトリにアクセスするように環境を設定します。

    settings.gradle で依存関係の一元管理を構成している場合は、次のように無効にします。

    • settings.gradle の次のコードブロックを削除します。

      import org.gradle.api.initialization.resolve.RepositoriesMode
      dependencyResolutionManagement {
          repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
          repositories {
              google()
              mavenCentral()
          }
      }
      
  2. Gradle または Maven 構成に以下の依存関係を追加します。VERSION_NUMBER プレースホルダは、目的のバージョンの SDK に置き換えてください。

    Gradle

    build.gradle に次の行を追加します。

    dependencies {
      ...
      implementation 'com.google.android.libraries.mapsplatform.transportation:transportation-consumer:VERSION_NUMBER'
    }
    

    Maven

    pom.xml に次の行を追加します。

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.mapsplatform.transportation</groupId>
        <artifactId>transportation-consumer</artifactId>
        <version>VERSION_NUMBER</version>
      </dependency>
    </dependencies>
    

アプリに API キーを追加する

コンシューマ SDK をアプリに追加したら、API キーをアプリに追加します。開発プロジェクトを設定したときに取得したプロジェクト API キーを使用する必要があります。

このセクションでは、アプリでより安全に参照できるように API キーを保存する方法について説明します。API キーをバージョン管理システムにチェックインしないでください。これは、プロジェクトのルート ディレクトリにある local.properties ファイルに保存する必要があります。local.properties ファイルの詳細については、Gradle プロパティ ファイルをご覧ください。

このタスクを効率化するには、Android 用 Secrets Gradle プラグインを使用します。

プラグインをインストールして API キーを保存するには:

  1. ルートレベルの build.gradle ファイルを開き、buildscript の下にある dependencies 要素に次のコードを追加します。

    Groovy

    buildscript {
        dependencies {
            // ...
            classpath "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.0"
        }
    }
    

    Kotlin

    buildscript {
        dependencies {
            // ...
            classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.0")
        }
    }
    
  2. アプリレベルの build.gradle ファイルを開き、次のコードを plugins 要素に追加します。

    Groovy

    id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
    

    Kotlin

    id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
    
  3. Android Studio を使用する場合は、プロジェクトを Gradle と同期します。

  4. プロジェクト レベルのディレクトリで local.properties を開き、次のコードを追加します。YOUR_API_KEY は、API キーに置き換えます。

    MAPS_API_KEY=YOUR_API_KEY
    
  5. AndroidManifest.xml ファイルで com.google.android.geo.API_KEY に移動し、android:value 属性を次のように更新します。

    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="${MAPS_API_KEY}" />
    

次の例は、サンプルアプリの完全なマニフェストを示しています。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.consumerapidemo">
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/_AppTheme">

        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="${MAPS_API_KEY}" />

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

必須の帰属情報をアプリに含める

アプリでコンシューマ SDK を使用する場合は、アプリの法的通知セクションの一部として、アトリビューション テキストとオープンソース ライセンスを含める必要があります。アトリビューションは、独立したメニュー項目として、または [概要] メニュー項目の一部として含めることをおすすめします。

必要なアトリビューション テキストとオープンソース ライセンスは、ライドシェアリング コンシューマ SDK の zip ファイルで確認できます。

  • NOTICE.txt
  • LICENSES.txt

コンシューマ SDK の認証

Consumer SDK では、JSON Web Token を使用して認証を行います。JSON Web Token(JWT)は、サービスに対して 1 つ以上のクレームを提供する JSON ベースのアクセス トークンです。たとえば、サーバーは「管理者としてログインしている」というクレームを持つトークンを生成し、それをクライアントに提供できます。クライアントはそのトークンを使用して、管理者としてログインしていることを証明できます。

コンシューマ SDK は、アプリケーションが提供する JSON ウェブトークンを使用して Fleet Engine と通信します。詳細については、Fleet Engine の認証と認可をご覧ください。

認証トークンを使用すると、次の Fleet Engine サービスにアクセスできます。

  • TripService - 車両の位置情報、ルート、到着予定時刻など、旅程の詳細にコンシューマ SDK がアクセスできるようにします。トリップ サービスの認証トークンは、トークンの authorization ヘッダーに tripid:TRIP_ID クレームを含める必要があります。TRIP_ID はルート ID です。
  • VehicleService - 車両密度レイヤを表示し、到着地点の到着予定時刻を推定するために、車両の移動した車両の場所に関する情報をコンシューマ SDK に提供します。コンシューマ SDK はファジングされた位置情報のみを使用するため、車両サービスの認証トークンに vehicleid クレームは必要ありません。

JSON Web Token コールバック

コンシューマ SDK は、初期化時に認証トークンをコールバックに登録します。SDK はアプリケーションを呼び出して、承認が必要なすべてのネットワーク リクエストのトークンを取得します。

コールバックの実装では、認証トークンをキャッシュし、expiry 時間が経過した場合にのみ更新することを強くおすすめします。トークンは、1 時間の有効期限で発行する必要があります。

認証トークン コールバックは、TripService サービスに必要なサービス トークンを指定します。また、コンテキストに必要な tripId も提供されます。

次のコード例は、認証トークンのコールバックを実装する方法を示しています。

Java

class JsonAuthTokenFactory implements AuthTokenFactory {

  private static final String TOKEN_URL =
      "https://yourauthserver.example/token";

  private static class CachedToken {
    String tokenValue;
    long expiryTimeMs;
    String tripId;
  }

  private CachedToken token;

  /*
  * This method is called on a background thread. Blocking is OK. However, be
  * aware that no information can be obtained from Fleet Engine until this
  * method returns.
  */
  @Override
  public String getToken(AuthTokenContext context) {
    // If there is no existing token or token has expired, go get a new one.
    String tripId = context.getTripId();
    if (tripId == null) {
      throw new RuntimeException("Trip ID is missing from AuthTokenContext");
    }
    if (token == null || System.currentTimeMillis() > token.expiryTimeMs ||
        !tripId.equals(token.tripId)) {
      token = fetchNewToken(tripId);
    }
    return token.tokenValue;
  }

  private static CachedToken fetchNewToken(String tripId) {
    String url = TOKEN_URL + "/" + tripId;
    CachedToken token = new CachedToken();

    try (Reader r = new InputStreamReader(new URL(url).openStream())) {
      com.google.gson.JsonObject obj
          = com.google.gson.JsonParser.parseReader(r).getAsJsonObject();

      token.tokenValue = obj.get("ServiceToken").getAsString();
      token.expiryTimeMs = obj.get("TokenExpiryMs").getAsLong();

      /*
      * The expiry time could be an hour from now, but just to try and avoid
      * passing expired tokens, we subtract 5 minutes from that time.
      */
      token.expiryTimeMs -= 5 * 60 * 1000;
    } catch (IOException e) {
      /*
      * It's OK to throw exceptions here. The error listeners will receive the
      * error thrown here.
      */
      throw new RuntimeException("Could not get auth token", e);
    }
    token.tripId = tripId;

    return token;
  }
}

Kotlin

class JsonAuthTokenFactory : AuthTokenFactory() {

  private var token: CachedToken? = null

  /*
  * This method is called on a background thread. Blocking is OK. However, be
  * aware that no information can be obtained from Fleet Engine until this
  * method returns.
  */
  override fun getToken(context: AuthTokenContext): String {
    // If there is no existing token or token has expired, go get a new one.
    val tripId = 
      context.getTripId() ?: 
        throw RuntimeException("Trip ID is missing from AuthTokenContext")

    if (token == null || System.currentTimeMillis() > token.expiryTimeMs ||
        tripId != token.tripId) {
      token = fetchNewToken(tripId)
    }

    return token.tokenValue
  }

  class CachedToken(
    var tokenValue: String? = "", 
    var expiryTimeMs: Long = 0,
    var tripId: String? = "",
  )

  private companion object {
    const val TOKEN_URL = "https://yourauthserver.example/token"

    fun fetchNewToken(tripId: String) {
      val url = "$TOKEN_URL/$tripId"
      val token = CachedToken()

      try {
        val reader = InputStreamReader(URL(url).openStream())

        reader.use {
          val obj = com.google.gson.JsonParser.parseReader(r).getAsJsonObject()

          token.tokenValue = obj.get("ServiceToken").getAsString()
          token.expiryTimeMs = obj.get("TokenExpiryMs").getAsLong()

          /*
          * The expiry time could be an hour from now, but just to try and avoid
          * passing expired tokens, we subtract 5 minutes from that time.
          */
          token.expiryTimeMs -= 5 * 60 * 1000
        }
      } catch (e: IOException) {
        /*
        * It's OK to throw exceptions here. The error listeners will receive the
        * error thrown here.
        */
        throw RuntimeException("Could not get auth token", e)
      }

      token.tripId = tripId

      return token
    }
  }
}

API を初期化する

この手順は、適切なサービスとコンシューマ SDK が有効になっていることを前提としています。

ConsumerApi インスタンスを取得する

コンシューマ SDK を使用するには、アプリで非同期的に ConsumerApi を初期化する必要があります。API はシングルトンです。 初期化メソッドは AuthTokenFactory を受け取ります。ファクトリは必要に応じて、ユーザー用に新しい JWT トークンを生成します。

providerId は、Google Cloud プロジェクトのプロジェクト ID です。プロジェクトの作成方法については、Fleet Engine ユーザーガイドをご覧ください。

アプリに AuthTokenFactory を実装する必要があります。詳細については、コンシューマ SDK 認証をご覧ください。

Java

Task<ConsumerApi> consumerApiTask = ConsumerApi.initialize(
    this, "myProviderId", authTokenFactory);

consumerApiTask.addOnSuccessListener(
  consumerApi -> this.consumerApi = consumerApi);

Kotlin

val consumerApiTask =
  ConsumerApi.initialize(this, "myProviderId", authTokenFactory)

consumerApiTask?.addOnSuccessListener { consumerApi: ConsumerApi ->
  this@YourActivity.consumerApi = consumerApi
}

ユーザー インターフェースを作成する

アプリケーションのユーザー インターフェースは、ConsumerMapFragment または ConsumerMapView を使用して作成できます。ConsumerMapFragment では Fragment を使用して地図を定義でき、ConsumerMapView では View を使用できます。ライドシェア機能は ConsumerMapViewConsumerMapFragment で同じであるため、ViewFragment のどちらがアプリに適しているかに基づいて、いずれかを選択できます。

API 19(KitKat)とベクター型ドローアブルのサポートを追加

アプリ設計で API 19(KitKat)デバイスとベクター型ドローアブルのサポートが必要な場合は、アクティビティに次のコードを追加します。このコードは、コンシューマ SDK で AppCompatActivity を拡張して、ベクター型ドローアブルを使用します。

Java

// ...
import android.support.v7.app.AppCompatActivity;

// ...

public class ConsumerTestActivity extends AppCompatActivity {
  // ...
}

Kotlin

// ...
import android.support.v7.app.AppCompatActivity

// ...

class ConsumerTestActivity : AppCompatActivity() {
  // ...
}

地図のフラグメントまたはビューを追加する

アプリ レイアウトの XML ファイル(/res/layout にあります)で定義した Android フラグメントまたはビューにジャーニー共有を表示する地図を作成します。次に、フラグメント(またはビュー)は、アプリがアクセスして変更できるジャーニー共有マップへのアクセスを提供します。この地図により、ConsumerController でハンドルも提供され、アプリでジャーニー共有のエクスペリエンスを制御、カスタマイズできます。

移動経路マップとコントローラ

次のコード共有次に示すように、ジャーニー共有マップをフラグメント(ConsumerMapFragment を使用)またはビュー(ConsumerMapView を使用)として定義します。次に、onCreate() メソッドは getConsumerGoogleMapAsync(callback) を呼び出します。これにより、コールバックで非同期に ConsumerGoogleMap が返されます。その後、ConsumerGoogleMap を使用してジャーニーを共有し、アプリの要件に応じて更新できます。

ConsumerMapFragment

次のコード例に示すように、アプリ レイアウト XML ファイルでフラグメントを定義します。

<fragment
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:name="com.google.android.libraries.mapsplatform.transportation.consumer.view.ConsumerMapFragment"
    android:id="@+id/consumer_map_fragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

getConsumerGoogleMapAsync() の呼び出しは、onCreate() メソッドから行う必要があります。

Java

public class SampleAppActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {

    // Find the ConsumerMapFragment.
    ConsumerMapFragment consumerMapFragment =
        (ConsumerMapFragment) fragmentManager.findFragmentById(R.id.consumer_map_fragment);

    // Initiate the callback that returns the map.
    if (consumerMapFragment != null) {
      consumerMapFragment.getConsumerGoogleMapAsync(
          new ConsumerMapReadyCallback() {
            // The map returned in the callback is used to access the ConsumerController.
            @Override
            public void onConsumerMapReady(@NonNull ConsumerGoogleMap consumerGoogleMap) {
              ConsumerController consumerController = consumerGoogleMap.getConsumerController();
            }
          });
    }
  }

}

Kotlin

class SampleAppActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    // Find the ConsumerMapFragment.
    val consumerMapFragment =
      fragmentManager.findFragmentById(R.id.consumer_map_fragment) as ConsumerMapFragment

    consumerMapFragment.getConsumerGoogleMapAsync(
      object : ConsumerMapReadyCallback() {
        override fun onConsumerMapReady(consumerGoogleMap: ConsumerGoogleMap) {
          val consumerController = consumerGoogleMap.getConsumerController()!!
        }
      }
    )
  }
}
ConsumerMapView

このビューは、XML ファイルの定義に従って、フラグメントまたはアクティビティで使用できます。

<com.google.android.libraries.mapsplatform.transportation.consumer.view.ConsumerMapView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/consumer_map_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

getConsumerGoogleMapAsync() の呼び出しは onCreate() から行う必要があります。コールバック パラメータに加えて、含まれるアクティビティまたはフラグメントと、MapView の構成属性を含む null の GoogleMapOptions が必要です。アクティビティまたはフラグメントの基本クラスは、それぞれライフサイクルへのアクセスを提供するため、FragmentActivity またはサポート Fragment のいずれかである必要があります。

Java

public class SampleAppActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    ConsumerMapView mapView = findViewById(R.id.consumer_map_view);

    if (mapView != null) {
      mapView.getConsumerGoogleMapAsync(
          new ConsumerMapReadyCallback() {
            // The map returned in the callback is used to access the ConsumerController.
            @Override
            public void onConsumerMapReady(@NonNull ConsumerGoogleMap consumerGoogleMap) {
              ConsumerController consumerController = consumerGoogleMap.getConsumerController();
            }
          }, this, null);
    }
  }

}

Kotlin

class SampleAppActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    val mapView = findViewById(R.id.consumer_map_view) as ConsumerMapView

    mapView.getConsumerGoogleMapAsync(
      object : ConsumerMapReadyCallback() {
        // The map returned in the callback is used to access the ConsumerController.
        override fun onConsumerMapReady(consumerGoogleMap: ConsumerGoogleMap) {
          val consumerController = consumerGoogleMap.getConsumerController()!!
        }
      },
      /* fragmentActivity= */ this,
      /* googleMapOptions= */ null,
    )
  }
}

フラグメントの MapView は、アクティビティ内の上記の MapView の例と同じですが、フラグメントの onCreateView() メソッドに MapView を含むレイアウトがインフレートする点が異なります。

Java

public class MapViewInFragment extends Fragment {

  @Override
  public View onCreateView(
      @NonNull LayoutInflater layoutInflater,
      @Nullable ViewGroup viewGroup,
      @Nullable Bundle bundle) {
    return layoutInflater.inflate(R.layout.consumer_map_view, viewGroup, false);
  }

}

Kotlin

class MapViewInFragment : Fragment() {
  override fun onCreateView(
    layoutInflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?,
  ): View {
    return layoutInflater.inflate(R.layout.consumer_map_view, viewGroup, false)
  }
}

旅路に合わせてカメラのズームを調整する

Maps SDK に組み込まれているデフォルトの現在地ボタンでは、デバイスの現在地がカメラの中央に配置されます。

アクティブなジャーニー共有セッションがある場合は、デバイスの位置情報ではなく、ジャーニーにカメラを向けることをおすすめします。

一般ユーザー向け SDK for Android 組み込みソリューション: AutoCamera

そのため、デバイスの位置情報ではなく、操作に集中できるように、Consumer SDK には、デフォルトで有効になっている AutoCamera 機能が用意されています。移動経路と次のルートの地点にズームしてズームします。

自動カメラ

カメラの動作をカスタマイズする

カメラの動作をより詳細に制御する必要がある場合は、ConsumerController.setAutoCameraEnabled() を使用して自動カメラを有効または無効にできます。

ConsumerController.getCameraUpdate() は、その時点における推奨カメラ境界を返します。この CameraUpdate を引数として GoogleMap.moveCamera() または GoogleMap.animateCamera() に指定できます。

ライドシェアリングと地図にアクセス

アプリでライドシェアリングと地図操作をサポートするには、ConsumerGoogleMapConsumerController へのアクセス権が必要です。ConsumerMapFragmentConsumerMapView はどちらも ConsumerMapReadyCallback で非同期に ConsumerGoogleMap を返します。ConsumerGoogleMap は、getConsumerController() から ConsumerController を返します。ConsumerGoogleMapConsumerController には、次のようにアクセスできます。

Java

private ConsumerGoogleMap consumerGoogleMap;
private ConsumerController consumerController;
private ConsumerMapView consumerMapView;

consumerMapView.getConsumerGoogleMapAsync(
    new ConsumerMapReadyCallback() {
      @Override
      public void onConsumerMapReady(@NonNull ConsumerGoogleMap consumerMap) {
        consumerGoogleMap = consumerMap;
        consumerController = consumerMap.getConsumerController();
      }
    },
    this, null);

Kotlin

var consumerGoogleMap: ConsumerGoogleMap
var consumerController: ConsumerController
val consumerMapView = findViewById(R.id.consumer_map_view) as ConsumerMapView

consumerMapView.getConsumerGoogleMapAsync(
  object : ConsumerMapReadyCallback() {
    override fun onConsumerMapReady(consumerMap: ConsumerGoogleMap) {
      consumerGoogleMap = consumerMap
      consumerController = consumerMap.getConsumerController()
    },
    /* fragmentActivity= */ this,
    /* googleMapOptions= */ null,
  }
)

コンシューマ Google マップ

ConsumerGoogleMapGoogleMap クラスのラッパークラスです。これにより、アプリは GoogleMap と同等の API を使用して地図を操作できるようになります。コンシューマ マップを使用すると、アプリと配車サービスが同じ基盤となる Google マップとシームレスにやり取りできます。たとえば、GoogleMap は 1 つのコールバック登録のみを許可しますが、ConsumerGoogleMap はデュアル登録されたコールバックをサポートします。これらのコールバックを使用すると、アプリとライドシェアリングで、順次に呼び出されるコールバックを登録できます。

コンシューマ コントローラ

ConsumerController では、ルートのモニタリング、ルートのステータスの管理、位置情報の設定など、ライドシェアリング機能を利用できます。

経路の共有を設定する

バックエンドが自動車とユーザーをマッチングしたら、JourneySharingSession を使用してユーザー インターフェースの共有を開始します。移動経路を共有すると、一致する車両の位置情報とルートが表示されます。アプリに SDK を実装すると、ルートのモニタリング、更新のリッスン、エラーの処理のための機能を追加できます。次の手順では、バックエンド サービスが実行されており、消費者と車両をマッチングするためのサービスが稼働していることを前提としています。

  1. TripModel オブジェクトにリスナーを登録して、到着予定時刻や到着前に車両が移動する必要のある距離など、ルートの詳細情報を取得します。

    Java

    // Create a TripModel instance for listening to updates to the trip specified by this trip name.
    String tripName = ...;
    TripModelManager tripModelManager = consumerApi.getTripModelManager();
    TripModel tripModel = tripModelManager.getTripModel(tripName);
    
    // Create a JourneySharingSession instance based on the TripModel.
    JourneySharingSession session = JourneySharingSession.createInstance(tripModel);
    
    // Add the JourneySharingSession instance on the map for updating the UI.
    consumerController.showSession(session);
    
    // Register for trip update events.
    tripModel.registerTripCallback(new TripModelCallback() {
      @Override
      public void onTripETAToNextWaypointUpdated(
          TripInfo tripInfo, @Nullable Long timestampMillis) {
        // ...
      }
    
      @Override
      public void onTripActiveRouteRemainingDistanceUpdated(
          TripInfo tripInfo, @Nullable Integer distanceMeters) {
        // ...
      }
    
      // ...
    });
    

    Kotlin

    // Create a TripModel instance for listening to updates to the trip specified by this trip name.
    val tripName = "tripName"
    val tripModelManager = consumerApi.getTripModelManager()
    val tripModel = tripModelManager.getTripModel(tripName)
    
    // Create a JourneySharingSession instance based on the TripModel.
    val session = JourneySharingSession.createInstance(tripModel)
    
    // Add the JourneySharingSession instance on the map for updating the UI.
    consumerController.showSession(session)
    
    // Register for trip update events.
    tripModel.registerTripCallback(
      object : TripModelCallback() {
        override fun onTripETAToNextWaypointUpdated(
          tripInfo: TripInfo,
          timestampMillis: Long?,
        ) {
          // ...
        }
    
        override fun onTripActiveRouteRemainingDistanceUpdated(
          tripInfo: TripInfo,
          distanceMeters: Int?,
        ) {
          // ...
        }
    
      // ...
    })
    
  2. TripModelOptions を使ってルートを設定します。

    Java

    // Set refresh interval to 2 seconds.
    TripModelOptions tripOptions =
        TripModelOptions.builder().setRefreshIntervalMillis(2000).build();
    tripModel.setTripModelOptions(tripOptions);
    

    Kotlin

    // Set refresh interval to 2 seconds.
    val tripOptions = TripModelOptions.builder().setRefreshIntervalMillis(2000).build()
    tripModel.setTripModelOptions(tripOptions)
    

ジャーニーの共有を停止

ホスト アクティビティが破棄された場合など、不要になった共有の停止は停止してください。プロセスの共有を停止すると、Fleet Engine へのネットワーク リクエストも停止し、メモリリークを防止できます。

次のサンプルコードは、ジャーニーの共有を停止する方法を示しています。

Java

public class MainActivity extends AppCompatActivity
    implements ConsumerViewModel.JourneySharingListener  {

  // Class implementation

  @Override
  protected void onDestroy() {
    super.onDestroy();

    if (journeySharingSession != null) {
      journeySharingSession.stop();
    }
  }
}

Kotlin

class SampleAppActivity : AppCompatActivity(), ConsumerViewModel.JourneySharingListener {

  // Class implementation

  override fun onDestroy() {
    super.onDestroy()

    journeySharingSession?.stop()
  }
}

ルートエラーの処理

onTripRefreshError メソッドは、ルートのモニタリング中に発生したエラーを表示します。コンシューマ SDK エラーのマッピングは、Google Cloud Platform で確立されているものと同じ HTTP/RPC ガイドラインに従います。ルート モニタリング中に表示される一般的なエラーには、次のようなものがあります。

HTTP RPC 説明
400 INVALID_ARGUMENT 顧客が無効なルート名を指定しました。トリップ名は providers/{provider_id}/trips/{trip_id} の形式にする必要があります。provider_id は、サービス プロバイダが所有する Cloud プロジェクトの ID にする必要があります。
401 未認証 JWT トークンが無効なため、リクエストが認証されていません。このエラーは、JWT トークンがトリップ ID なしで署名されているか、JWT トークンの有効期限が切れている場合に発生します。
403 PERMISSION_DENIED(実行拒否) クライアントに十分な権限がありません。このエラーは、JWT トークンが無効、クライアントに権限がない、またはクライアント プロジェクトで API が有効になっていない場合に発生します。JWT トークンが不足しているか、トークンが、リクエストされたルート ID と一致しないルート ID で署名されている可能性があります。
429 RESOURCE_EXHAUSTED リソースの割り当てがゼロであるか、トラフィック率が上限を超えています。
503 使用不可 サービス利用不可。通常、サーバーはダウンしています。
504 DEADLINE_EXCEEDED(期限超過) リクエスト期限を超えました。これは、呼び出し元がメソッドのデフォルトの期限よりも短い期限を設定している場合(つまり、要求された期限がサーバーでリクエストを処理するのに十分な量ではない場合)、リクエストが期限内に完了しなかった場合にのみ発生します。

詳細については、Consumer SDK のエラー処理をご覧ください。