您可以使用 Consumer SDK 建構及執行與隨選乘車和外送解決方案後端服務整合的基本消費者應用程式。您可以建立「行程」和「訂單進度」應用程式,用於顯示進行中的行程、回應行程更新,以及處理行程錯誤。
由於 Consumer SDK 採用模組化架構,因此您可以使用想要用於特定應用程式的 API 部分,並整合到自己的 API、Fleet Engine 提供的後端服務,以及 Google 地圖平台新增的 API。
基本系統需求
行動裝置必須搭載 Android 6.0 (API 級別 23) 以上版本。
建構和依附元件設定
您可透過 Google Maven 存放區使用 Consumer SDK 1.99.0 以上版本。先前使用的私人存放區管道已淘汰。
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 以上版本。
如要執行透過 Consumer SDK 建構的應用程式,Android 裝置必須安裝 Google Play 服務。
設定開發專案
如要在 Google Cloud 控制台上設定開發專案,並取得專案的 API 金鑰,請按照下列步驟操作:
建立新的 Google Cloud 控制台專案,或選取現有專案,以便搭配 Consumer SDK 使用。請稍待幾分鐘,直到新專案顯示在 Google Cloud 控制台上。
如要執行試用版應用程式,專案必須具備 Maps SDK for Android 的存取權。在 Google Cloud 控制台中,選取「API 和服務」>「程式庫」,然後搜尋並啟用 Maps SDK for Android。
選取「APIs & Services」(API 和服務) >「Credentials」(憑證) >「Create credentials」(建立憑證) >「API key」(API 金鑰),取得專案的 API 金鑰。如要進一步瞭解如何取得 API 金鑰,請參閱「取得 API 金鑰」一文。
在應用程式中加入 Consumer SDK
Consumer SDK 可透過私人 Maven 存放區取得。存放區包含 SDK 的專案物件模型 (.pom) 檔案和 Javadocs。如要在應用程式中加入 Consumer SDK,請按照下列步驟操作:
按照上一節所述,設定環境以存取主機的 Maven 存放區。
如果您已在
settings.gradle
中宣告集中式依附元件管理設定,請按照下列步驟操作。移除
settings.gradle
中的下列程式碼區塊:import org.gradle.api.initialization.resolve.RepositoriesMode dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() } }
將以下依附元件新增至 Gradle 或 Maven 設定,將
VERSION_NUMBER
預留位置替換成所需的 Consumer 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>
Consumer SDK 仰賴 Maps SDK。設定這個依附元件時,如果以下建構設定檔「並未」在建構設定檔中明確定義 Maps SDK 版本,那麼當新版 Maps SDK 發布時,Consumer 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 屬性檔案一文。
您可以使用 Secrets Gradle Plugin for Android 來簡化這項工作。
如要安裝這個外掛程式並儲存 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.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,請務必將作者資訊文字和開放原始碼授權納入應用程式的法律聲明一節。建議您將歸因資訊納入獨立的選單項目,或做為「About」選單項目的一部分。
您可以在未封存 AAR 檔案的「third_party_licenses.txt」檔案中找到授權資訊。
如要瞭解如何納入開放原始碼通知,請參閱 https://developers.google.com/android/guides/opensource。
消費者 SDK 驗證
Consumer SDK 使用 JSON Web Token 提供驗證。JSON Web Token (JWT) 是一種 JSON 基礎存取權杖,可針對服務提供一或多項憑證附加資訊。例如,伺服器可以產生具有「以管理員身分登入」聲明的權杖,並將該憑證提供給用戶端。接著,用戶端就能使用該權杖,證明以管理員身分登入。
Consumer SDK 會使用應用程式提供的 JSON Web Token 與 Fleet Engine 通訊。詳情請參閱 Fleet Engine 驗證與授權。
授權權杖必須在權杖的 authorization
標頭中加入 tripid:TRIP_ID
憑證附加資訊,其中 TRIP_ID
是行程 ID。如此一來,消費端 SDK 就能存取行程詳細資料,包括車輛位置、路線和預計到達時間。
JSON Web Token 回呼
Consumer SDK 會在初始化期間,向應用程式註冊授權權杖回呼。SDK 會呼叫應用程式,針對所有需要授權的網路要求取得權杖。
強烈建議您執行回呼實作快取授權權杖,並只在 expiry
時間過後更新這些權杖。權杖的效期應為一小時。
授權權杖回呼會指定 TripService
服務所需的服務權杖。這個 API 也會提供背景資訊所需的 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 使用手冊。
應用程式應按照 Consumer 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 18.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
。ConsumerMapView
和 ConsumerMapFragment
皆使用共乘功能,因此您可以根據應用程式較適合採用 View
或 Fragment
進行選擇。
新增對 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() {
// ...
}
新增地圖片段或檢視畫面
您可以建立用於顯示分享行程分享的地圖的 Android 片段或檢視畫面 (位於 /res/layout
的應用程式版面配置 XML 檔案內)。接著,片段 (或檢視區塊) 會提供旅程共用地圖的存取權,供應用程式存取及修改。地圖也提供 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()
。除了回呼參數之外,它還需要內含活動或片段的 GoogleMapOptions
(可以是空值),以及包含 MapView
的設定屬性。由於活動或片段的基本類別必須是 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 內建預設「我的位置」按鈕,會將相機置於裝置位置中心。
如果有執行中的旅程分享工作階段,建議您將攝影機畫面置中,而非裝置位置。
Android 專用的 Consumer SDK for Android 內建解決方案:AutoCamera
為讓您專注於旅程而非裝置位置資訊,Consumer SDK 提供預設啟用的 AutoCamera 功能。鏡頭會放大,將焦點放在旅程分享路線和下一個行程路線控點。
自訂相機行為
如果您需要進一步控管相機行為,可以使用 ConsumerController.setAutoCameraEnabled() 停用或啟用自動相機。
ConsumerController.getCameraUpdate() 目前會傳回目前建議的相機邊界。然後您便可以提供此 CameraUpdate
做為引數,給 GoogleMap.moveCamera() 或 GoogleMap.animateCamera()。
存取代僱駕駛服務與地圖
如要在應用程式中支援共乘和地圖互動功能,您需要存取 ConsumerGoogleMap
和 ConsumerController
。ConsumerMapFragment
和 ConsumerMapView
都會以非同步方式傳回 ConsumerMapReadyCallback
中的 ConsumerGoogleMap
。ConsumerGoogleMap
會從 getConsumerController()
傳回 ConsumerController
。您可以按照下列方式存取 ConsumerGoogleMap
和 ConsumerController
。
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
ConsumerGoogleMap
是 GoogleMap
類別的包裝函式類別。該應用程式可讓您使用與 GoogleMap
相等的 API 與地圖互動。使用消費者地圖,您的應用程式和共乘服務就能與相同的基礎 Google 地圖完美互動。例如,GoogleMap
僅允許註冊單一回呼,但 ConsumerGoogleMap
支援雙註冊回呼。這些回呼可讓應用程式和共乘服務註冊依序呼叫的回呼。
ConsumerController
ConsumerController
可讓您存取共乘功能,例如監控行程、控制行程狀態和設定位置。
設定旅程分享
後端比對消費者與車輛後,請使用 JourneySharingSession
啟動歷程共用使用者介面。歷程分享功能會顯示相符的車輛位置和路線。在應用程式中實作 SDK 後,您可以新增用於監控行程、監聽更新及處理錯誤的功能。下列程序假設後端服務已經就緒,且用於比對消費者與車輛的服務運作正常。
在
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?, ) { // ... } // ... })
使用
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 必須是服務供應商擁有的雲端專案 ID。 |
401 | 未驗證 | JWT 權杖無效,因此無法驗證要求。若簽署的 JWT 權杖沒有行程 ID,或是 JWT 權杖已過期,就會發生這個錯誤。 |
403 | PERMISSION_DENIED | 用戶端權限不足。如果 JWT 憑證無效、用戶端沒有權限,或用戶端專案未啟用 API,就會發生這個錯誤。JWT 權杖可能遺失,或權杖簽署的行程 ID 與要求的行程 ID 不符。 |
429 | RESOURCE_EXHAUSTED | 資源配額為 0 或流量頻率超出限制 |
503 | 無法提供 | 服務無法使用,伺服器通常會停止運作。 |
504 | DEADLINE_EXCEEDED | 已超出要求期限。只有在呼叫端設定的期限短於方法的預設期限 (例如,要求的期限不夠讓伺服器處理要求),且要求未在期限內完成時,才會發生上述情況。 |
詳情請參閱「消費者 SDK 錯誤處理」。