คุณสามารถใช้ Consumer SDK เพื่อสร้างและเรียกใช้แอปผู้บริโภคพื้นฐานที่ผสานรวมเข้ากับบริการแบ็กเอนด์ของโซลูชันบริการโดยสารและการนำส่งแบบออนดีมานด์ คุณสามารถสร้างแอปการเดินทางและความคืบหน้าของคำสั่งซื้อที่สามารถแสดงการเดินทางที่ใช้งานอยู่ ตอบกลับการอัปเดตการเดินทาง และจัดการข้อผิดพลาดในการเดินทางได้
เนื่องจาก Consumer SDK มีสถาปัตยกรรมแบบแยกส่วน คุณจึงสามารถใช้ส่วนต่างๆ ของ API ที่ต้องการใช้กับแอปใดแอปหนึ่ง และผสานรวมเข้ากับ API ของคุณเอง บริการแบ็กเอนด์จาก Fleet Engine และ API เพิ่มเติมของ Google Maps Platform
ข้อกำหนดขั้นต่ำของระบบ
อุปกรณ์เคลื่อนที่ต้องใช้ 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>
การกำหนดค่าโปรเจ็กต์
หากต้องการใช้ Consumer SDK สำหรับ Android แอปของคุณต้องกําหนดเป้าหมายเป็น minSdkVersion
23 ขึ้นไป
หากต้องการเรียกใช้แอปที่สร้างด้วย Consumer SDK อุปกรณ์ Android จะต้องมี บริการ Google Play ติดตั้งไว้
ตั้งค่าโปรเจ็กต์การพัฒนา
วิธีตั้งค่าโปรเจ็กต์การพัฒนาและรับคีย์ API สำหรับโปรเจ็กต์ใน Google Cloud Console มีดังนี้
สร้างโปรเจ็กต์ Google Cloud Console ใหม่หรือเลือกโปรเจ็กต์ที่มีอยู่เพื่อใช้กับ Consumer SDK รอสักครู่จนกว่าโปรเจ็กต์ใหม่จะปรากฏใน Google Cloud Console
หากต้องการเรียกใช้แอปเดโม โปรเจ็กต์ของคุณต้องมีสิทธิ์เข้าถึง Maps SDK สำหรับ Android ใน Google Cloud Console ให้เลือก API และบริการ > ไลบรารี จากนั้นค้นหาและเปิดใช้ Maps SDK สำหรับ Android
รับคีย์ API สำหรับโปรเจ็กต์โดยเลือก API และบริการ > ข้อมูลเข้าสู่ระบบ > สร้างข้อมูลเข้าสู่ระบบ > คีย์ API ดูข้อมูลเพิ่มเติมเกี่ยวกับการรับคีย์ API ได้ที่รับคีย์ API
เพิ่ม SDK ของผู้บริโภคลงในแอปของคุณ
Consumer SDK พร้อมให้ใช้งานผ่านที่เก็บส่วนตัวของ Maven ที่เก็บจะรวมไฟล์ Project Object Model (.pom) และ Javadocs ของ SDK วิธีเพิ่ม SDK ของผู้บริโภคลงในแอป
ตั้งค่าสภาพแวดล้อมของคุณเพื่อเข้าถึงที่เก็บของโฮสต์ Maven ตามที่อธิบายไว้ในส่วนก่อนหน้า
หากคุณประกาศการกำหนดค่าการจัดการทรัพยากร Dependency แบบรวมศูนย์ใน
settings.gradle
ให้ปิดใช้ดังนี้นำโค้ดบล็อกต่อไปนี้ใน
settings.gradle
ออก:import org.gradle.api.initialization.resolve.RepositoriesMode dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() } }
เพิ่มทรัพยากร Dependency ต่อไปนี้ในการกำหนดค่า 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>
SDK ของผู้บริโภคจะขึ้นอยู่กับ Maps SDK ทรัพยากร Dependency นี้จะกำหนดค่าในลักษณะที่ว่าหากไม่ได้กำหนดเวอร์ชันของ 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 สำหรับ Android เพื่อปรับปรุงงานนี้ให้มีประสิทธิภาพยิ่งขึ้น
วิธีติดตั้งปลั๊กอินและจัดเก็บคีย์ API
เปิดไฟล์
build.gradle
ระดับรากและเพิ่มโค้ดต่อไปนี้ลงในองค์ประกอบdependencies
ภายใต้buildscript
ดึงดูด
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
ดึงดูด
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
ด้วยคีย์ APIMAPS_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 ที่สมบูรณ์สำหรับแอปตัวอย่าง
<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 ในแอป คุณต้องใส่ข้อความระบุแหล่งที่มาและใบอนุญาตโอเพนซอร์สไว้ในส่วนประกาศทางกฎหมายของแอป คุณควรรวมการระบุแหล่งที่มาเป็นรายการในเมนูอิสระหรือเป็นส่วนหนึ่งของรายการในเมนูเกี่ยวกับ
ดูข้อมูลใบอนุญาตได้ในไฟล์ "third_party_licenses.txt" ในไฟล์ AAR ที่ไม่ได้เก็บถาวร
ดูวิธีรวมประกาศโอเพนซอร์สได้ที่ https://developers.google.com/android/guides/opensource
การตรวจสอบสิทธิ์ SDK ของผู้บริโภค
Consumer SDK มีการตรวจสอบสิทธิ์โดยใช้ JSON Web Token JSON Web Token (JWT) เป็นโทเค็นเพื่อการเข้าถึง JSON-base ที่มีการอ้างสิทธิ์อย่างน้อย 1 รายการในบริการ ตัวอย่างเช่น เซิร์ฟเวอร์อาจสร้างโทเค็นที่อ้างว่า "เข้าสู่ระบบในฐานะผู้ดูแลระบบ" และส่งโทเค็นนั้นให้กับไคลเอ็นต์ จากนั้นไคลเอ็นต์จะใช้โทเค็นดังกล่าวเพื่อพิสูจน์ว่ามีการเข้าสู่ระบบในฐานะผู้ดูแลระบบ
Consumer SDK ใช้ JSON Web Token ที่แอปพลิเคชันมีให้เพื่อสื่อสารกับ Fleet Engine ดูข้อมูลเพิ่มเติมที่การตรวจสอบสิทธิ์และการให้สิทธิ์ของ Fleet Engine
โทเค็นการให้สิทธิ์ต้องมีการอ้างสิทธิ์ tripid:TRIP_ID
ในส่วนหัว authorization
ของโทเค็น โดยที่ TRIP_ID
คือรหัสการเดินทาง ซึ่งจะช่วยให้ผู้บริโภค SDK เข้าถึงรายละเอียดการเดินทาง เช่น ตำแหน่งของรถ เส้นทาง และเวลาถึงโดยประมาณได้
Callback ของ JSON Web Token
Consumer SDK จะลงทะเบียน Callback ของโทเค็นการให้สิทธิ์กับแอปพลิเคชันในระหว่างการเริ่มต้น SDK จะเรียกแอปพลิเคชัน ให้รับโทเค็นสำหรับคำขอเครือข่ายทั้งหมดที่ต้องมีการให้สิทธิ์
ขอแนะนำให้ใช้โทเค็นการให้สิทธิ์ของแคชการใช้งาน Callback และรีเฟรชโทเค็นดังกล่าวเมื่อเวลาผ่านไป expiry
แล้วเท่านั้น คุณควรออกโทเค็นที่มีวันหมดอายุ 1 ชั่วโมง
การเรียกกลับของโทเค็นการให้สิทธิ์จะระบุโทเค็นบริการที่จำเป็นสำหรับบริการ TripService
และยังมี tripId
ที่จำเป็นสำหรับบริบทด้วย
ตัวอย่างโค้ดต่อไปนี้สาธิตวิธีใช้ Callback โทเค็นการให้สิทธิ์
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
หากต้องการใช้ Consumer SDK แอปของคุณต้องเริ่มต้น ConsumerApi
แบบไม่พร้อมกัน API เป็นแบบเดี่ยว
วิธีการเริ่มต้นใช้ AuthTokenFactory
โรงงานจะสร้างโทเค็น JWT ใหม่ให้ผู้ใช้เมื่อจำเป็น
providerId
คือรหัสโปรเจ็กต์ของโปรเจ็กต์ Google Cloud ดูคู่มือผู้ใช้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 และ Maps
SDK สำหรับผู้บริโภคเวอร์ชัน 2.x.x รองรับ Maps SDK สำหรับ Android เวอร์ชัน 18.1.0 ขึ้นไป ตารางด้านล่างจะสรุปตัวแสดงผลเริ่มต้นตามเวอร์ชัน Maps SDK และการรองรับของโหมดแสดงภาพทั้ง 2 แบบ เราขอแนะนำให้ใช้ตัวแสดงผลเวอร์ชันล่าสุด แต่หากต้องการใช้โหมดแสดงภาพเดิม คุณสามารถระบุอย่างชัดแจ้งโดยใช้ MapsInitializer.initialize()
เวอร์ชันของ Maps SDK | รองรับโหมดแสดงภาพล่าสุด | รองรับตัวแสดงผลแบบเดิม | ตัวแสดงผลเริ่มต้น |
---|---|---|---|
เวอร์ชัน 18.1.0 และเวอร์ชันที่ต่ำกว่า | ได้ | ได้ | เดิม* |
V18.2.0 | ได้ | ได้ | ล่าสุด |
* การเปิดตัว Maps Renderer ใหม่จะใช้โหมดแสดงภาพล่าสุดเป็นค่าเริ่มต้น
เพิ่ม Maps SDK เป็นทรัพยากร Dependency
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 ก่อนเริ่มต้น Consumer 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) และ Vector แบบถอนออกได้
หากการออกแบบแอปกำหนดให้รองรับอุปกรณ์ API 19 (KitKat) และการดึงเวกเตอร์แบบเวกเตอร์ ให้เพิ่มโค้ดต่อไปนี้ลงในกิจกรรม โค้ดนี้ขยาย AppCompatActivity
เพื่อใช้เวกเตอร์ที่ถอนออกได้ใน SDK ของผู้บริโภค
Java
// ...
import android.support.v7.app.AppCompatActivity;
// ...
public class ConsumerTestActivity extends AppCompatActivity {
// ...
}
Kotlin
// ...
import android.support.v7.app.AppCompatActivity
// ...
class ConsumerTestActivity : AppCompatActivity() {
// ...
}
เพิ่มส่วนย่อยหรือมุมมองแผนที่
คุณสร้างแผนที่เพื่อแสดงการแชร์การเดินทางในส่วน Android หรือมุมมอง ซึ่งคุณกำหนดไว้ในไฟล์ XML ของเลย์เอาต์แอปพลิเคชัน (อยู่ใน /res/layout
) จากนั้นส่วนย่อย (หรือมุมมอง) จะให้สิทธิ์เข้าถึงแผนที่การแชร์เส้นทางซึ่งแอปเข้าถึงและแก้ไขได้ แผนที่ยังมีแฮนเดิล ConsumerController
ซึ่งช่วยให้แอปของคุณควบคุมและปรับแต่งประสบการณ์การแชร์การเดินทางได้
แผนที่และตัวควบคุมสำหรับแชร์เส้นทาง
คุณกําหนดแผนที่การแชร์เส้นทางเป็นส่วนย่อย (โดยใช้ ConsumerMapFragment
) หรือเป็นมุมมอง (โดยใช้ ConsumerMapView
) ดังที่แสดงในตัวอย่างโค้ดต่อไปนี้ จากนั้นเมธอด onCreate()
ของคุณควรเรียกใช้ getConsumerGoogleMapAsync(callback)
ซึ่งแสดงผล ConsumerGoogleMap
แบบไม่พร้อมกันใน Callback จากนั้นใช้ 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()
นอกเหนือจากพารามิเตอร์ Callback แล้ว จำเป็นต้องใช้กิจกรรมหรือ Fragment ที่มี และ GoogleMapOptions
(ซึ่งอาจเป็น Null) ที่มีแอตทริบิวต์การกำหนดค่าสำหรับ 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
ใน Fragment จะเหมือนกับตัวอย่างข้างต้นสำหรับ MapView
ในกิจกรรม เว้นแต่ว่า Fragment จะเพิ่มเลย์เอาต์ที่มี MapView
ในเมธอด Fragment onCreateView()
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 สำหรับโซลูชันในตัวของ Android: กล้องอัตโนมัติ
Consumer SDK มีฟีเจอร์กล้องอัตโนมัติที่เปิดใช้โดยค่าเริ่มต้นเพื่อช่วยให้คุณมุ่งเน้นไปที่การเดินทางแทนตำแหน่งของอุปกรณ์ กล้องจะซูมเพื่อโฟกัสที่เส้นทางที่แชร์การเดินทางและจุดอ้างอิงของการเดินทางถัดไป
การปรับแต่งลักษณะการทำงานของกล้อง
หากต้องการควบคุมลักษณะการทำงานของกล้องได้มากขึ้น ให้ปิดหรือเปิดใช้กล้องอัตโนมัติโดยใช้ ConsumerController.setAutoCameraEnabled()
ConsumerController.getCameraUpdate() แสดงผลขอบเขตกล้องที่แนะนำในขณะนั้น จากนั้นคุณจะระบุ CameraUpdate
นี้เป็นอาร์กิวเมนต์ให้กับ
GoogleMap.moveCamera() หรือ GoogleMap.animateCamera() ได้
เข้าถึงบริการร่วมเดินทางและแผนที่
หากต้องการรองรับบริการร่วมเดินทางและการโต้ตอบบนแผนที่ในแอปพลิเคชันของคุณ คุณต้องมีสิทธิ์เข้าถึง ConsumerGoogleMap
และ ConsumerController
ทั้ง ConsumerMapFragment
และ ConsumerMapView
จะแสดง ConsumerGoogleMap
แบบไม่พร้อมกันใน ConsumerMapReadyCallback
ConsumerGoogleMap
ส่งคืน ConsumerController
จาก getConsumerController()
คุณจะเข้าถึง 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
คือคลาส Wrapper สำหรับคลาส GoogleMap
แอปดังกล่าวให้สามารถโต้ตอบกับแผนที่โดยใช้ API ที่เทียบเท่ากับ GoogleMap
การใช้แผนที่ผู้บริโภคช่วยให้แอปและบริการร่วมเดินทางของคุณโต้ตอบกับ GoogleMap เดียวกันได้อย่างราบรื่น ตัวอย่างเช่น GoogleMap
อนุญาตให้ลงทะเบียน Callback เพียงครั้งเดียว แต่ ConsumerGoogleMap
รองรับ Callback ที่ลงทะเบียนแบบคู่
Callback เหล่านี้อนุญาตให้แอปและการแชร์รถโดยสารสามารถลงทะเบียน Callback ซึ่งเราเรียกใช้ตามลำดับ
ConsumerController
ConsumerController
มอบการเข้าถึงฟังก์ชันการทำงานของการแชร์การเดินทาง เช่น การตรวจสอบการเดินทาง การควบคุมสถานะการเดินทาง และการตั้งค่าตำแหน่ง
ตั้งค่าการแชร์เส้นทาง
หลังจากแบ็กเอนด์จับคู่ผู้บริโภคกับยานพาหนะแล้ว ให้ใช้ JourneySharingSession
เพื่อเริ่มอินเทอร์เฟซผู้ใช้สำหรับการแชร์เส้นทาง การแชร์เส้นทางจะแสดงตำแหน่งและเส้นทางของยานพาหนะที่ตรงกัน หลังจากใช้ SDK ในแอปแล้ว คุณจะเพิ่มฟังก์ชันสำหรับตรวจสอบการเดินทาง ฟังอัปเดต และจัดการข้อผิดพลาดได้
ขั้นตอนต่อไปนี้จะสมมติว่ามีบริการแบ็กเอนด์ทำงานอยู่ และบริการของคุณสำหรับการจับคู่ผู้บริโภคกับยานพาหนะนั้นทำงานได้
ลงทะเบียน Listener ในออบเจ็กต์
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
จะแสดงข้อผิดพลาดที่เกิดขึ้นระหว่างการตรวจสอบการเดินทาง
การแมปข้อผิดพลาด SDK ของผู้บริโภคเป็นไปตามหลักเกณฑ์ HTTP/RPC เดียวกันกับที่กําหนดขึ้นสําหรับ Google Cloud Platform
ข้อผิดพลาดที่พบบ่อยที่เกิดขึ้นระหว่างการตรวจสอบการเดินทางมีดังนี้
HTTP | RPC | คำอธิบาย |
---|---|---|
400 | INVALID_ARGUMENT | ไคลเอ็นต์ระบุชื่อการเดินทางไม่ถูกต้อง ชื่อการเดินทางต้องเป็นไปตามรูปแบบ providers/{provider_id}/trips/{trip_id}
provider_id ต้องเป็นรหัสของโปรเจ็กต์ระบบคลาวด์ของผู้ให้บริการ |
401 | ไม่มีการตรวจสอบสิทธิ์ | คำขอไม่ได้รับการตรวจสอบสิทธิ์ เนื่องจากโทเค็น JWT ไม่ถูกต้อง ข้อผิดพลาดนี้จะเกิดขึ้นหากมีการลงชื่อโทเค็น JWT โดยไม่มีรหัสทริป หรือโทเค็น JWT หมดอายุ |
403 | PERMISSION_DENIED | ไคลเอ็นต์มีสิทธิ์ไม่เพียงพอ ข้อผิดพลาดนี้เกิดขึ้นหากโทเค็น JWT ไม่ถูกต้อง ไคลเอ็นต์ไม่มีสิทธิ์ หรือไม่ได้เปิดใช้ API สำหรับโปรเจ็กต์ไคลเอ็นต์ โทเค็น JWT อาจหายไปหรือลงนามโทเค็นด้วยรหัสการเดินทางที่ไม่ตรงกับรหัสการเดินทางที่ขอ |
429 | RESOURCE_EXHAUSTED | โควต้าทรัพยากรอยู่ที่ 0 หรือปริมาณการเข้าชมเกินขีดจำกัด |
503 | UNAVAILABLE | ไม่พร้อมให้บริการ เซิร์ฟเวอร์มักขัดข้อง |
504 | DEADLINE_EXCEEDED | เกินกำหนดเวลาในการส่งคำขอแล้ว กรณีนี้จะเกิดขึ้นเฉพาะในกรณีที่ผู้โทรตั้งกำหนดเวลาที่สั้นกว่ากำหนดเวลาเริ่มต้นของวิธีการ (กล่าวคือ กำหนดเวลาที่ขอไม่มากพอที่เซิร์ฟเวอร์จะดำเนินการตามคำขอ) และคำขอไม่เสร็จสมบูรณ์ภายในกำหนดเวลา |
ดูข้อมูลเพิ่มเติมได้ที่การจัดการข้อผิดพลาดของ SDK ของผู้บริโภค