面向 Android 的 Consumer SDK 使用入门

您可以使用消费者 SDK 构建和运行已集成的基本消费者应用, 按需乘车和送货解决方案后端服务。您可以创建 行程和订单进度应用,可显示有效行程; 响应行程更新和处理行程错误。

由于消费者 SDK 采用模块化架构,因此您可以使用 并将它们集成到 Fleet Engine 提供的后端服务、 Google Maps Platform 的 API 和附加 API。

最低系统要求

移动设备必须搭载 Android 6.0 版 (API 级别 23)或更高版本。

构建和依赖项配置

使用方 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>

项目配置

要使用 Android Consumer SDK,您的应用必须 minSdkVersion 23 或更高版本。

若要运行使用消费者 SDK 构建的应用,Android 设备必须具有 Google Play 服务 已安装。

设置您的开发项目

设置您的开发项目并获取 API 密钥 在 Google Cloud 控制台中为项目指定权限:

  1. 创建新的 Google Cloud 控制台项目,或者选择一个现有项目以供使用 使用消费者 SDK。等待几分钟,直到 新项目即会显示在 Google Cloud 控制台中。

  2. 为了运行演示版应用,您的项目必须有权访问 Maps SDK 。在 Google Cloud 控制台中,选择 API 和服务 >库,然后针对 Android。

  3. 通过以下方式获取项目的 API 密钥: API 和服务 >凭据 >创建凭据 >API 密钥。 如需详细了解如何获取 API 密钥,请参阅 获取 API 密钥

将消费者 SDK 添加到您的应用

消费者 SDK 可通过专用 Maven 制品库获取。通过 代码库包括 SDK 的项目对象模型 (.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 配置中,注意要将 所需使用方 SDK 版本的 VERSION_NUMBER 占位符。

    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. 使用方 SDK 依赖于 Maps SDK。此依赖项在 确保 Maps SDK 版本没有在 使用新版地图时,将构建配置文件如下所示 SDK 发布后,消费者 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 密钥

将消费者 SDK 添加到您的应用后,请将 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,则必须添加 应用的法律声明中的署名文本和开源许可 部分。最好将提供方说明作为独立的菜单项或 (位于关于菜单项中)。

您可以在“third_party_licenses.txt”中找到许可信息。文件 已取消归档的 AAR 文件。

请参阅 https://developers.google.com/android/guides/opensource

使用方 SDK 身份验证

使用方 SDK 使用 JSON Web 令牌提供身份验证。 JSON Web 令牌 (JWT) 是一种基于 JSON 格式的访问令牌, 一个或多个对服务的声明。例如,服务器可以生成 具有声明“以管理员身份登录”的令牌并提供 。然后,客户端可以使用该令牌来证明 它以管理员身份登录。

使用方 SDK 使用应用提供的 JSON Web 令牌 与 Fleet Engine 进行通信如需了解详情,请参阅舰队引擎身份验证和授权

授权令牌的声明中必须包含 tripid:TRIP_ID 声明。 authorization 标头,其中 TRIP_ID 是行程 ID。这使得 通过 SDK 获取行程详情,包括车辆位置、路线和预计到达时间。

JSON Web 令牌回调

使用方 SDK 注册授权令牌回调 在初始化期间与应用共享数据。SDK 调用应用 为需要授权的所有网络请求获取令牌。

我们强烈建议您在回调实现缓存授权 令牌,并仅在 expiry 时间过后刷新它们。令牌应 的有效期为一小时。

授权令牌回调指定需要哪个服务令牌 (针对 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
}

Maps SDK 和地图渲染程序

使用方 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>

先初始化 Maps SDK,然后再初始化使用方 SDK

Application 或启动 Activity 类中,调用 MapsInitializer.initialize() 并等待渲染器请求结果,然后再初始化 使用方 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()
      }
    })
  }

创建界面

您可以使用 ConsumerMapFragmentConsumerMapView,即可为您的 Google Cloud 应用 应用。ConsumerMapFragment 可用于定义 使用 Google 地图 Fragment,而 ConsumerMapView 允许您使用 View。拼车 在 ConsumerMapViewConsumerMapFragment,您可以根据情况选择 无论是 View 还是 Fragment 更适合您的应用。

添加了对 API 19 (KitKat) 和矢量可绘制对象的支持

如果您的应用设计需要支持 API 19 (KitKat) 设备和矢量可绘制对象, 将以下代码添加到您的 Activity 中。此代码扩展了 AppCompatActivity,以使用 消费者 SDK 中的矢量可绘制对象。

Java

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

// ...

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

Kotlin

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

// ...

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

添加地图 fragment 或视图

您可以创建用于在 Android fragment 中显示旅程分享的地图 或视图,您可以在应用布局 XML 文件(位于 /res/layout)。然后,Fragment(或视图)提供对历程的访问权限 共享地图,您的应用可以访问和修改该地图。该地图还提供了 ConsumerController 的句柄,可让应用控制和 自定义旅程分享体验。

行程分享地图和控制器

您可以将旅程共享地图定义为 fragment(使用 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

该视图可以在 fragment 或 activity 中使用,具体定义如 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()。在 除回调参数外,还需要包含回调参数,或 fragment 和 GoogleMapOptions(可以为 null),其中包含配置 MapView 属性。activity 或 fragment 基类必须是 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,
    )
  }
}

fragment 中的 MapView 与上述针对 MapView 的示例(在 只不过该片段会扩充包含 fragment 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 内置的默认“我的位置”按钮会将相机置于设备位置中央。

如果有正在进行的“旅程分享”会话,您可能需要将摄像头置于画面中央 将注意力集中在旅程上,而不是放在设备位置上。

Android 版消费者 SDK 内置解决方案:AutoCamera

为了让您专注于行程而不是设备位置, 消费者 SDK 提供 AutoCamera 功能, 默认处于启用状态相机会缩放,以聚焦于行程分享路线 下一个行程航点。

AutoCamera

自定义相机行为

如果您需要进一步控制相机行为,可以停用或启用 使用 ConsumerController.setAutoCameraEnabled() 自动相机。

此时,ConsumerController.getCameraUpdate() 会返回建议的摄像头边界。然后,您可以将此 CameraUpdate 作为参数提供给 GoogleMap.moveCamera()GoogleMap.animateCamera()

使用拼车服务和地图

如需在您的应用中支持拼车和地图互动,您需要具备访问权限 至 ConsumerGoogleMapConsumerControllerConsumerMapFragmentConsumerMapView 均异步返回 “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,
  }
)

ConsumerGoogleMap

ConsumerGoogleMapGoogleMap 类。它让您的应用能够 与地图交互的 API,等效于 GoogleMap。使用消费者地图可让您的应用和约车服务 以便与同一底层 GoogleMap 无缝互动。例如: GoogleMap 仅允许注册一个回调,但 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)
    

停止分享行程

确保在不再需要行程共享时停止共享,例如在宿主 activity 被销毁时。停止历程共享还会停止对 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 说明
400 INVALID_ARGUMENT 客户指定的行程名称无效。通过 行程名称必须遵循格式 providers/{provider_id}/trips/{trip_id}provider_id 必须是 该服务提供商拥有的 Cloud 项目。
401 未经过身份验证 由于以下原因,请求未通过身份验证: JWT 令牌无效。此错误将会发生 如果 JWT 令牌签名时没有行程 ID 或 JWT 令牌已过期。
403 PERMISSION_DENIED 客户没有足够的 权限。如果 JWT 存在 令牌无效,则客户端没有 权限,或者尚未对 API 启用 客户端项目JWT 令牌可能是 或者令牌有行程签名 ID 与所请求的行程 ID 不符。
429 RESOURCE_EXHAUSTED 资源配额为零或者 的流量超过了限制。
503 无法观看 服务不可用。通常,服务器 服务中断。
504 DEADLINE_EXCEEDED 超出请求时限。这将 只在调用方设置了截止时限的情况下才会发生 ,它的长度要短于该方法的默认值 截止时间(即请求的截止时间不是 服务器足以处理 而请求未完成 。

如需了解详情,请参阅 使用方 SDK 错误处理