您可以使用驱动程序 SDK 提供增强的导航和跟踪功能 行程和订单进度应用驱动程序 SDK 提供 对按需乘车和送货解决方案舰队引擎的更新车辆位置和任务。
驱动程序 SDK 可让 Fleet Engine 服务和自定义服务保持感知
车辆的位置和状态信息。例如,车辆可以是 ONLINE
或 OFFLINE
,且车辆位置会随着行程的进行而变化。
最低系统要求
移动设备必须搭载 Android 6.0 (API 级别 23)或更高版本。
构建和依赖项配置
Google Maven 制品库中提供驱动程序 SDK 4.99 版及更高版本。
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>
项目配置
如需使用驱动程序 SDK,您的应用必须
minSdkVersion
23 或更高版本。
要运行使用驱动程序 SDK 构建的应用,Android 设备必须具有 Google Play 服务 已安装。
设置您的开发项目
设置您的开发项目并获取 API 密钥 在 Google Cloud 控制台中为项目指定权限:
创建新的 Google Cloud 控制台项目,或者选择一个现有项目以供使用 驱动程序 SDK。等待几分钟,直到 新项目即会显示在 Google Cloud 控制台中。
为了运行演示版应用,您的项目必须有权访问 Maps SDK 。在 Google Cloud 控制台中,选择 API 和服务 >库,然后针对 Android。
通过以下方式获取项目的 API 密钥: API 和服务 >凭据 >创建凭据 >API 密钥。 如需详细了解如何获取 API 密钥,请参阅 获取 API 密钥。
将驱动程序 SDK 添加到您的应用
驱动程序 SDK 可从 Google Maven 制品库中获取。通过 代码库包括 SDK 的项目对象模型 (.pom) 文件和 Javadocs。如需将驱动程序 SDK 添加到您的应用,请执行以下操作:
将以下依赖项添加到您的 Gradle 或 Maven 配置中,注意要将 所需驱动程序 SDK 版本的
VERSION_NUMBER
占位符。Gradle
将以下内容添加到
build.gradle
中:dependencies { ... implementation 'com.google.android.libraries.mapsplatform.transportation:transportation-driver:VERSION_NUMBER' }
Maven
将以下内容添加到
pom.xml
中:<dependencies> ... <dependency> <groupId>com.google.android.libraries.mapsplatform.transportation</groupId> <artifactId>transportation-driver</artifactId> <version>VERSION_NUMBER</version> </dependency> </dependencies>
驱动程序 SDK 依赖于 Navigation SDK,此依赖项在下面的代码中配置 如果需要特定版本的 Navigation SDK 在 build 配置文件中明确定义,如下所示: 省略上述代码块将使项目始终能够下载 主要发布版本中最新版本的 Navigation SDK。 请注意,最新版本的驱动程序 SDK 和 Navigation SDK 在发布之前经过了严格的测试。
安排开发和版本的依赖项配置 环境
Gradle
将以下内容添加到
build.gradle
中:dependencies { ... implementation 'com.google.android.libraries.navigation:navigation:5.0.0' }
Maven
将以下内容添加到
pom.xml
中:<dependencies> ... <dependency> <groupId>com.google.android.libraries.navigation</groupId> <artifactId>navigation</artifactId> <version>5.0.0</version> </dependency> </dependencies>
向您的应用添加 API 密钥
将驱动程序 SDK 添加到您的应用后,请将 API 密钥添加到您的应用中。您 必须使用您在创建 API 时获取的项目 API 密钥, 设置您的开发项目。
本部分介绍了如何存储 API 密钥,以提高其安全性
由您的应用引用您不应将 API 密钥签入您的版本
控制系统它应存储在 local.properties
文件中,即
位于项目的根目录下。如需详细了解
local.properties
文件,请参阅
Gradle 属性文件。
为了简化此任务,您可以使用 Android 版 Secrets Gradle 插件。
如需安装此插件并存储您的 API 密钥,请执行以下操作:
打开根级
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") } }
打开应用级
build.gradle
文件,并将以下代码添加到plugins
元素。Groovy
id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
Kotlin
id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
如果您使用 Android Studio 将项目与 Gradle 同步。
在项目级目录中打开
local.properties
,然后添加 代码。将YOUR_API_KEY
替换为您的 API 密钥。MAPS_API_KEY=YOUR_API_KEY
在
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.driverapidemo">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_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 。
依赖项
如果您使用 ProGuard 执行以下操作: 优化构建时,可能需要将以下几行代码添加到 ProGuard 配置文件:
-dontwarn com.google.**
-dontwarn okio.**
支持的最低 API 级别为 23。
初始化 SDK
必须提供提供方 ID(通常是 Google Cloud 项目 ID)才能
初始化 DriverContext
对象。如需详细了解如何设置
Google Cloud 项目,请参阅
身份验证和授权。
在使用驱动程序 SDK 之前,您必须先初始化 Navigation SDK。要初始化 SDK,请执行以下操作:
从
NavigationApi
获取Navigator
对象。Java
NavigationApi.getNavigator( this, // Activity new NavigationApi.NavigatorListener() { @Override public void onNavigatorReady(Navigator navigator) { // Keep a reference to the Navigator (used to configure and start nav) this.navigator = navigator; } } );
Kotlin
NavigationApi.getNavigator( this, // Activity object : NavigatorListener() { override fun onNavigatorReady(navigator: Navigator) { // Keep a reference to the Navigator (used to configure and start nav) this@myActivity.navigator = navigator } }, )
创建一个用于填充必填字段的
DriverContext
对象。Java
DriverContext driverContext = DriverContext.builder(application) .setProviderId(providerId) .setVehicleId(vehicleId) .setAuthTokenFactory(authTokenFactory) .setNavigator(navigator) .setRoadSnappedLocationProvider( NavigationApi.getRoadSnappedLocationProvider(application)) .build();
Kotlin
val driverContext = DriverContext.builder(application) .setProviderId(providerId) .setVehicleId(vehicleId) .setAuthTokenFactory(authTokenFactory) .setNavigator(navigator) .setRoadSnappedLocationProvider(NavigationApi.getRoadSnappedLocationProvider(application)) .build()
使用
DriverContext
对象初始化*DriverApi
。Java
RidesharingDriverApi ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext);
Kotlin
val ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext)
从 API 对象获取
RidesharingVehicleReporter
。 (*VehicleReporter
扩展了NavigationVehicleReporter
。)Java
RidesharingVehicleReporter vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter();
Kotlin
val vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter()
使用 AuthTokenFactory
进行身份验证
当驱动程序 SDK 生成位置信息更新时,
它必须将这些更新
Fleet Engine 服务器为了对这些请求进行身份验证,
驱动程序 SDK 将调用调用方提供的
AuthTokenFactory
的实例。
工厂负责在以下位置生成身份验证令牌:
更新时间。
生成令牌的具体方式取决于每个开发者的具体情况。 不过,实现可能需要:
- 从 HTTPS 服务器提取身份验证令牌(可能是 JSON 格式)
- 解析并缓存令牌
- 在令牌过期时刷新令牌
如需详细了解 Fleet Engine 服务器预期的令牌,请参阅 创建用于授权的 JSON 网络令牌 (JWT)。
以下是 AuthTokenFactory
的框架实现:
Java
class JsonAuthTokenFactory implements AuthTokenFactory {
private String token; // initially null
private long expiryTimeMs = 0;
// This method is called on a thread whose only responsibility is to send
// location updates. Blocking is OK, but just know that no location updates
// can occur until this method returns.
@Override
public String getToken(AuthTokenContext authTokenContext) {
if (System.currentTimeMillis() > expiryTimeMs) {
// The token has expired, go get a new one.
fetchNewToken(authTokenContext.getVehicleId());
}
return token;
}
private void fetchNewToken(String vehicleId) {
String url =
new Uri.Builder()
.scheme("https")
.authority("yourauthserver.example")
.appendPath("token")
.appendQueryParameter("vehicleId", vehicleId)
.build()
.toString();
try (Reader r = new InputStreamReader(new URL(url).openStream())) {
com.google.gson.JsonObject obj
= com.google.gson.JsonParser.parseReader(r).getAsJsonObject();
token = obj.get("Token").getAsString();
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 10 minutes from that time.
expiryTimeMs -= 10 * 60 * 1000;
} catch (IOException e) {
// It's OK to throw exceptions here. The StatusListener you passed to
// create the DriverContext class will be notified and passed along the failed
// update warning.
throw new RuntimeException("Could not get auth token", e);
}
}
}
Kotlin
class JsonAuthTokenFactory : AuthTokenFactory() {
private var token: String = ""
private var expiryTimeMs: Long = 0
// This method is called on a thread whose only responsibility is to send
// location updates. Blocking is OK, but just know that no location updates
// can occur until this method returns.
override fun getToken(context: AuthTokenContext): String {
if (System.currentTimeMillis() > expiryTimeMs) {
// The token has expired, go get a new one.
fetchNewToken(authTokenContext.getVehicleId())
}
return token
}
fun fetchNewToken(vehicleId: String) {
val url =
Uri.Builder()
.scheme("https")
.authority("yourauthserver.example")
.appendPath("token")
.appendQueryParameter("vehicleId", vehicleId)
.build()
.toString()
try {
val reader = InputStreamReader(URL(url).openStream())
reader.use {
val obj = com.google.gson.JsonParser.parseReader(r).getAsJsonObject()
token = obj.get("ServiceToken").getAsString()
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 10 minutes from that time.
expiryTimeMs -= 10 * 60 * 1000
}
} catch (e: IOException) {
// It's OK to throw exceptions here. The StatusListener you passed to
// create the DriverContext class will be notified and passed along the failed
// update warning.
throw RuntimeException("Could not get auth token", e)
}
}
}
这一特定实现使用内置的 Java HTTP 客户端提取 从开发者身份验证服务器获取 JSON 格式的令牌。令牌为 以便重复使用如果旧令牌不超过 10 分钟,则重新获取令牌 过期时间。
您的实现可能会以不同的方式执行操作,例如使用后台线程 刷新令牌。
除非发生,否则 AuthTokenFactory
中的异常将被视为暂时异常
。多次尝试后,驱动程序 SDK
会假设
错误是永久性的,并且会停止尝试发送更新。
StatusListener
的状态和 Error Reporting
由于驱动程序 SDK 在
后台运行时,使用 StatusListener
在发生特定情况时触发通知
比如错误、警告或调试消息。错误可能是
它们是暂时性的(例如 BACKEND_CONNECTIVITY_ERROR
),也可能是
会导致位置信息更新永久停止(如 VEHICLE_NOT_FOUND
、
表示出现配置错误)。
您可以提供如下所示的可选 StatusListener
实现:
Java
class MyStatusListener implements StatusListener {
/** Called when background status is updated, during actions such as location reporting. */
@Override
public void updateStatus(
StatusLevel statusLevel, StatusCode statusCode, String statusMsg) {
// Status handling stuff goes here.
// StatusLevel may be DEBUG, INFO, WARNING, or ERROR.
// StatusCode may be DEFAULT, UNKNOWN_ERROR, VEHICLE_NOT_FOUND,
// BACKEND_CONNECTIVITY_ERROR, or PERMISSION_DENIED.
}
}
Kotlin
class MyStatusListener : StatusListener() {
/** Called when background status is updated, during actions such as location reporting. */
override fun updateStatus(statusLevel: StatusLevel, statusCode: StatusCode, statusMsg: String) {
// Status handling stuff goes here.
// StatusLevel may be DEBUG, INFO, WARNING, or ERROR.
// StatusCode may be DEFAULT, UNKNOWN_ERROR, VEHICLE_NOT_FOUND,
// BACKEND_CONNECTIVITY_ERROR, or PERMISSION_DENIED.
}
}
SSL/TLS 注意事项
在内部,驱动程序 SDK 实现使用
使用 SSL/TLS 安全地进行通信
与 Fleet Engine 服务器相关联。旧版 Android(API 版本 19 或
可能需要 SecurityProvider
补丁才能与
服务器。您应该会看到
文章
。这篇文章还
包含用于修补安全提供程序的代码示例。
启用位置信息更新
拥有 *VehicleReporter
实例后,启用位置信息更新
简单明了:
Java
RidesharingVehicleReporter reporter = ...;
reporter.enableLocationTracking();
Kotlin
val reporter = ...
reporter.enableLocationTracking()
当车辆处于以下状态时,系统会定期发送位置信息更新
ONLINE
。请注意,调用 reporter.enableLocationTracking()
不会
自动将车辆状态设置为 ONLINE
。您必须
设置车辆状态。
默认情况下,报告间隔为 10 秒。报告间隔可以
用 reporter.setLocationReportingInterval(long, TimeUnit)
更改。通过
支持的最小更新间隔为 5 秒。更新频率可能会更高
会导致请求速度变慢和错误
停用位置更新
换档完成后,系统可以停止位置信息更新,
已通过电话将车辆标记为离线
DeliveryVehicleReporter.disableLocationTracking
或
RidesharingVehicleReporter.disableLocationTracking
。
此调用将导致安排一个最终更新立即传送, 表示车辆处于离线状态。此更新不会包含 位置。
设置车辆状态
启用位置信息更新后,将车辆状态设置为 ONLINE
会
使车辆支持 SearchVehicles
查询;同样地,将
车辆设置为 OFFLINE
会将车辆标记为不可用。
您可以选择在服务器端设置车辆状态(请参阅更新 车辆), 或直接在驱动程序 SDK 中运行以下命令:
Java
RidesharingVehicleReporter reporter = ...;
reporter.enableLocationTracking();
reporter.setVehicleState(VehicleState.ONLINE);
Kotlin
val reporter = ...
reporter.enableLocationTracking()
reporter.setVehicleState(VehicleState.ONLINE)
启用位置信息更新后,对 setVehicleState
的调用将在
下一次位置信息更新。
在未启用位置信息跟踪功能的情况下,将车辆标记为ONLINE
会导致
在 IllegalStateException
中。在以下情况下,车辆可以标记为OFFLINE
:
尚未启用或明确停用位置跟踪功能。这会导致
立即更新。对
RidesharingVehicleReporter.disableLocationTracking()
将会
将车辆状态设为 OFFLINE
。
请注意,setVehicleState
会立即返回,并且会在
位置更新线程。类似于对位置更新的错误处理
更新车辆状态的操作是使用可选的
在 DriverContext
中设置的 StatusListener
。