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

Consumer SDK を使用して、オンデマンド配車と配達ソリューションのバックエンド サービスと統合された基本的な一般ユーザー向けアプリを構築して実行できます。アクティブなルートの表示、ルート更新情報への応答、ルートエラーの処理を行う、移動状況と注文状況のアプリを作成できます。

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

最小システム要件

モバイル デバイスに Android 6.0(API レベル 23)以降が搭載されている必要があります。

ビルドと依存関係の構成

Consumer SDK バージョン 1.99.0 以降は、Google Maven リポジトリを使用して利用できます。以前に使用した非公開リポジトリ チャネルは非推奨になりました。

Gradle

次のコードを build.gradle ファイルに追加します。

repositories {
    ...
    google()
}

Maven

次のコードを pom.xml ファイルに追加します。

<project>
  ...
  <repositories>
    <repository>
      <id>google-maven-repository</id>
      <url>https://maven.google.com</url>
    </repository>
  </repositories>
  ...
</project>

Project Configuration

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

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

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

Google Cloud コンソールで開発プロジェクトを設定し、そのプロジェクトの API キーを取得するには:

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

  2. デモアプリを実行するには、プロジェクトが Maps SDK for Android にアクセスできる必要があります。Google Cloud コンソールで、[API とサービス] > [ライブラリ] を選択し、Maps SDK for Android を検索して有効にします。

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

アプリに Consumer SDK を追加する

Consumer SDK は非公開の Maven リポジトリから入手できます。リポジトリには、SDK のプロジェクト オブジェクト モデル(.pom)ファイルと Javadocs が含まれています。Consumer 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>
    
  3. Consumer SDK は Maps SDK に依存しています。この依存関係は、以下のように、Maps SDK のバージョンがビルド構成ファイルで明示的に定義されていない場合、Maps SDK の新しいバージョンがリリースされたときに、サポートされている Maps SDK の最小バージョンを使用し続けます

    Gradle

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

    dependencies {
      ...
      implementation 'com.google.android.gms:play-services-maps:18.1.0'
    }
    

    Maven

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

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.gms</groupId>
        <artifactId>play-services-maps</artifactId>
        <version>18.1.0</version>
      </dependency>
    </dependencies>
    

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

Consumer 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>

必要な帰属情報をアプリに含める

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

ライセンス情報は、アーカイブ解除された AAR ファイルの「third_party_licenses.txt」ファイルで確認できます。

オープンソースの通知を含める方法については、https://developers.google.com/android/guides/opensource をご覧ください。

コンシューマ SDK 認証

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

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

認証トークンでは、トークンの authorization ヘッダーに tripid:TRIP_ID クレームを含める必要があります。ここで、TRIP_ID はルート ID です。これにより、Consumer SDK は車両の位置、ルート、到着予定時刻などのルートの詳細にアクセスできるようになります。

JSON Web Token のコールバック

Consumer 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 を初期化する

以下の手順を行う前に、適切なサービスと Consumer SDK が有効になっていることを前提としています。

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

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

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

消費者 SDK 認証で説明されているように、アプリに AuthTokenFactory を実装する必要があります。

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
}

Maps SDK とマップレンダラ

Consumer SDK v2.x.x は、Maps SDK for Android v18.1.0 以降をサポートしています。次の表は、Maps SDK バージョン別のデフォルトのレンダラと、両方のレンダラのサポート状況をまとめたものです。最新のレンダラを使用することをおすすめしますが、以前のレンダラを使用する必要がある場合は、MapsInitializer.initialize() を使用して明示的に指定できます。

Maps SDK のバージョン 最新のレンダラのサポート 従来のレンダラのサポート デフォルトのレンダラ
V18.1.0 以前 レガシー*
V18.2.0 最新

* 新しい地図レンダラのロールアウトに伴い、「最新のレンダラ」がデフォルトです。

Maps SDK を依存関係として追加する

Gradle

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

dependencies {
  //...
  implementation "com.google.android.gms:play-services-maps:VERSION_NUMBER"
}

Maven

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

 <dependencies>
   ...
   <dependency>
     <groupId>com.google.android.gms</groupId>
     <artifactId>play-services-maps</artifactId>
     <version>18.1.0</version>
   </dependency>
 </dependencies>

Consumer SDK を初期化する前に Maps SDK を初期化する

Application または起動用の Activity クラスで、MapsInitializer.initialize() を呼び出し、レンダラのリクエスト結果を待ってから、Consumer SDK を初期化します。

java

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  initViews();

  MapsInitializer.initialize(getApplicationContext(), Renderer.LATEST,
      new OnMapsSdkInitializedCallback() {
        @Override
        public void onMapsSdkInitialized(Renderer renderer) {
          switch (renderer) {
            case LATEST:
              Log.i("maps_renderer", "LATEST renderer");
              break;
            case LEGACY:
              Log.i("maps_renderer", "LEGACY renderer");
              break;
          }

          initializeConsumerSdk();
        }
      });
}

Kotlin

fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  setContentView(R.layout.main)
  initViews()

  MapsInitializer.initialize(
    getApplicationContext(), Renderer.LATEST,
    object : OnMapsSdkInitializedCallback() {
      fun onMapsSdkInitialized(renderer: Renderer?) {
        when (renderer) {
          LATEST -> Log.i("maps_renderer", "LATEST renderer")
          LEGACY -> Log.i("maps_renderer", "LEGACY renderer")
        }
        initializeConsumerSdk()
      }
    })
  }

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

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

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

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

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 の設定属性を含む GoogleMapOptions(null でも可)が必要です。アクティビティまたはフラグメントの基本クラスは、ライフサイクルへのアクセスを提供するため、それぞれ 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 は、フラグメントの onCreateView() メソッドに MapView を含むレイアウトをインフレートする点を除き、アクティビティ内の 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 に組み込まれているデフォルトの現在地ボタンは、デバイスの位置にカメラを合わせます。

アクティブな移動経路の共有セッションがある場合は、デバイスの位置情報ではなく、移動経路を中心にカメラを合わせることができます。

Consumer SDK for Android の組み込みソリューション: AutoCamera

デバイスの位置情報ではなくジャーニーに集中できるように、Consumer SDK には、デフォルトで有効になっている AutoCamera 機能が用意されています。移動経路の共有経路と次の停車地点にフォーカスが合わせ、カメラがズームします。

AutoCamera

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

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

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

ライドシェアリングや地図を利用できる

アプリでライドシェアリングと地図の操作をサポートするには、ConsumerGoogleMapConsumerController にアクセスする必要があります。ConsumerMapFragmentConsumerMapView はどちらも非同期的に ConsumerMapReadyCallbackConsumerGoogleMap を返します。ConsumerGoogleMapgetConsumerController() から 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,
  }
)

ConsumerGoogleMap

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

ConsumerController

ConsumerController は、ルートのモニタリング、ルート状況の管理、場所の設定などのライド シェアリング機能へのアクセスを提供します。

ジャーニーの共有を設定する

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

  1. TripModel オブジェクトにリスナーを登録すると、ETA(到着予定時刻)や車両が到着前に走行する必要がある距離など、ルートに関する詳細を取得できます。

    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 メソッドは、ルートのモニタリング中に発生したエラーを表示します。Consumer 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 リクエスト期限を超えました。これは、呼び出し元が、メソッドのデフォルトの期限よりも短い期限を設定し(すなわち、リクエストされた期限ではサーバーがリクエストを処理するのに十分ではない)、リクエストがその期限内に完了しなかった場合にのみ発生します。

詳細については、コンシューマ SDK のエラー処理をご覧ください。