คุณสามารถใช้ SDK ไดรเวอร์เพื่อให้การนำทางและการติดตามขั้นสูงไปยังแอปพลิเคชันความคืบหน้าในการเดินทางและคำสั่งซื้อ Driver SDK จะให้ข้อมูลอัปเดตตำแหน่งของยานพาหนะและงานสำหรับ Fleet Engine โซลูชันการโดยสารและการนำส่งแบบออนดีมานด์
Driver SDK จะทำให้บริการ Fleet Engine และบริการที่คุณกำหนดเองทราบถึงตำแหน่งและสถานะของรถ ตัวอย่างเช่น ยานพาหนะอาจเป็น ONLINE
หรือ OFFLINE
และตำแหน่งยานพาหนะจะเปลี่ยนไปตามการเดินทาง
ข้อกำหนดขั้นต่ำของระบบ
อุปกรณ์เคลื่อนที่ต้องใช้ Android 5.0 (API ระดับ 21) ขึ้นไป
การกำหนดค่า Maven
Driver SDK เวอร์ชัน 4.99 ขึ้นไปจะพร้อมใช้งานผ่านที่เก็บ 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>
การกำหนดค่าโปรเจ็กต์
หากต้องการใช้ Driver SDK แอปของคุณต้องกำหนดเป้าหมายเป็น
minSdkVersion
21 ขึ้นไป
หากต้องการเรียกใช้แอปที่สร้างด้วย Driver SDK อุปกรณ์ Android ต้องติดตั้ง บริการ Google Play ไว้แล้ว
ตั้งค่าโปรเจ็กต์การพัฒนาของคุณ
หากต้องการตั้งค่าโปรเจ็กต์การพัฒนาและรับคีย์ API สำหรับโปรเจ็กต์ใน Google Cloud Console ให้ทำดังนี้
สร้างโปรเจ็กต์ Google Cloud Console ใหม่หรือเลือกโปรเจ็กต์ที่มีอยู่เพื่อใช้กับ Driver SDK รอสักครู่จนกว่าโปรเจ็กต์ใหม่จะแสดงใน Google Cloud Console
หากต้องการเรียกใช้แอปเดโม โปรเจ็กต์ต้องมีสิทธิ์เข้าถึง Maps SDK สำหรับ Android ใน Google Cloud Console ให้เลือก API และบริการ > ไลบรารี จากนั้นค้นหาและเปิดใช้ Maps SDK สำหรับ Android
รับคีย์ API สำหรับโปรเจ็กต์โดยเลือก API และบริการ > ข้อมูลเข้าสู่ระบบ > สร้างข้อมูลเข้าสู่ระบบ > คีย์ API ดูข้อมูลเพิ่มเติมเกี่ยวกับการรับคีย์ API ได้ที่รับคีย์ API
เพิ่ม Driver SDK ในแอปของคุณ
Driver SDK พร้อมให้ใช้งานผ่านที่เก็บ Maven ส่วนตัว ที่เก็บประกอบด้วยไฟล์ Project Object Model (.pom) และ Javadocs ของ SDK วิธีเพิ่ม Driver SDK ลงในแอป
เพิ่มทรัพยากร Dependency ต่อไปนี้ในการกำหนดค่า Gradle หรือ Maven ของคุณ โดยแทนที่ตัวยึดตำแหน่ง
VERSION_NUMBER
สำหรับเวอร์ชัน SDK ของไดรเวอร์ที่ต้องการ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>
เพิ่มคีย์ API ลงในแอป
เมื่อเพิ่ม Driver SDK ในแอปแล้ว ให้เพิ่มคีย์ API ลงในแอป คุณต้องใช้คีย์ API ของโปรเจ็กต์ที่ได้มาเมื่อตั้งค่าโปรเจ็กต์การพัฒนาซอฟต์แวร์
ส่วนนี้อธิบายวิธีจัดเก็บคีย์ API เพื่อให้แอปอ้างอิงได้อย่างปลอดภัยยิ่งขึ้น คุณไม่ควรตรวจสอบคีย์ API ในระบบควบคุมเวอร์ชัน ซึ่งควรจัดเก็บไฟล์ไว้ในไฟล์ local.properties
ซึ่งอยู่ในไดเรกทอรีรากของโปรเจ็กต์ ดูข้อมูลเพิ่มเติมเกี่ยวกับไฟล์ local.properties
ได้ที่ไฟล์พร็อพเพอร์ตี้ Gradle
หากต้องการปรับปรุงงานนี้ ให้ใช้ปลั๊กอินข้อมูลลับ 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.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>
ใส่แอตทริบิวต์ที่จำเป็นในแอป
หากใช้ Driver SDK ในแอป คุณต้องใส่ข้อความระบุแหล่งที่มาและใบอนุญาตโอเพนซอร์สเป็นส่วนหนึ่งของส่วนประกาศทางกฎหมายของแอป คุณควรรวมการระบุแหล่งที่มาเป็นรายการในเมนูอิสระหรือเป็นส่วนหนึ่งของรายการในเมนูเกี่ยวกับ
คุณสามารถดูข้อความระบุแหล่งที่มาและใบอนุญาตโอเพนซอร์สที่ต้องการในไฟล์ ZIP ของ Driver SDK ดังนี้
NOTICE.txt
LICENSES.txt
การอ้างอิง
หากคุณใช้ ProGuard เพื่อเพิ่มประสิทธิภาพบิลด์ คุณอาจต้องเพิ่มบรรทัดต่อไปนี้ลงในไฟล์การกำหนดค่า ProGuard
-dontwarn com.google.**
-dontwarn okio.**
ระดับ API ขั้นต่ำที่รองรับคือ 21
การเริ่มต้น SDK
คุณต้องระบุรหัสผู้ให้บริการ (โดยปกติจะเป็นรหัสโปรเจ็กต์ Google Cloud) เพื่อเริ่มต้นออบเจ็กต์ DriverContext
ดูรายละเอียดเพิ่มเติมเกี่ยวกับการตั้งค่าโปรเจ็กต์ Google Cloud ได้ที่การตรวจสอบสิทธิ์และการให้สิทธิ์
ก่อนที่จะใช้ Driver SDK ขั้นแรก คุณต้องเริ่มต้น Navigation SDK ก่อน วิธีเริ่มต้น SDK
รับออบเจ็กต์
Navigator
จากNavigationApi
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)
รับ
RidesharingVehicleReporter
จากออบเจ็กต์ API (*VehicleReporter
ขยายเวลาNavigationVehicleReporter
)Java
RidesharingVehicleReporter vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter();
Kotlin
val vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter()
กำลังตรวจสอบสิทธิ์กับ AuthTokenFactory
เมื่อ Driver SDK สร้างการอัปเดตตำแหน่ง จะต้องส่งการอัปเดตเหล่านี้ไปยังเซิร์ฟเวอร์ Fleet Engine ในการตรวจสอบสิทธิ์คำขอเหล่านี้ Driver SDK จะเรียกใช้อินสแตนซ์ AuthTokenFactory
จากผู้โทร
โรงงานมีหน้าที่สร้างโทเค็นการตรวจสอบสิทธิ์ ณ เวลาอัปเดตตำแหน่ง
วิธีสร้างโทเค็นจะแตกต่างกันไปตามสถานการณ์ของนักพัฒนาซอฟต์แวร์แต่ละราย อย่างไรก็ตาม อาจต้องดำเนินการต่อไปนี้
- เรียกโทเค็นการตรวจสอบสิทธิ์ซึ่งอาจอยู่ในรูปแบบ JSON จากเซิร์ฟเวอร์ HTTPS
- แยกวิเคราะห์และแคชโทเค็น
- รีเฟรชโทเค็นเมื่อหมดอายุ
โปรดดูรายละเอียดของโทเค็นที่เซิร์ฟเวอร์ 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
เนื่องจาก 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
การใช้ Driver SDK ภายในจะใช้ SSL/TLS เพื่อสื่อสารกับเซิร์ฟเวอร์ Fleet Engine อย่างปลอดภัย เวอร์ชันเก่าของ Android (API เวอร์ชัน 19 หรือต่ำกว่า) อาจต้องใช้แพตช์ SecurityProvider
เพื่อสื่อสารกับเซิร์ฟเวอร์ได้ โปรดดูบทความนี้สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการทำงานกับ SSL ใน Android บทความนี้ยังมีตัวอย่างโค้ดสำหรับการแพตช์ผู้ให้บริการด้านความปลอดภัยด้วย
การเปิดใช้การอัปเดตตำแหน่ง
เมื่อคุณมีอินสแตนซ์ *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
การโทรครั้งนี้จะทำให้มีกำหนดเวลาอัปเดตครั้งสุดท้าย 1 ครั้งเพื่อให้นำส่งได้ทันที ซึ่งหมายความว่ารถยนต์ออฟไลน์อยู่ การอัปเดตนี้จะไม่มีตำแหน่งของผู้ใช้
การตั้งค่าสถานะของรถ
เมื่อเปิดใช้การอัปเดตตำแหน่ง การตั้งค่าสถานะของรถเป็น ONLINE
จะทำให้ยานพาหนะพร้อมใช้งานสำหรับการค้นหา SearchVehicles
ในทำนองเดียวกัน การทำเครื่องหมายยานพาหนะเป็น OFFLINE
จะทำเครื่องหมายยานพาหนะว่าไม่พร้อมใช้งาน
คุณมีตัวเลือกในการตั้งค่าสถานะรถยนต์ที่ฝั่งเซิร์ฟเวอร์ (ดูอัปเดตยานพาหนะ) หรือใน Driver 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
จะส่งคืนทันทีและระบบจะอัปเดตในชุดข้อความการอัปเดตตำแหน่ง เช่นเดียวกับการจัดการข้อผิดพลาดเกี่ยวกับการอัปเดตตำแหน่ง ข้อผิดพลาดในการอัปเดตสถานะของรถจะถูกเผยแพร่โดยใช้ StatusListener
ที่ไม่บังคับซึ่งตั้งค่าใน DriverContext