คุณสามารถใช้ Driver SDK เพื่อมอบการนำทางและการติดตามที่มีประสิทธิภาพยิ่งขึ้นไปยังแอปพลิเคชันการเดินทางและความคืบหน้าในการสั่งซื้อ Driver SDK ช่วยระบุตำแหน่งยานพาหนะและอัปเดตงานของ Solution Fleet Engine บริการรถโดยสารและการนำส่งแบบออนดีมานด์
Driver SDK ทำให้บริการ Fleet Engine และบริการที่กำหนดเองของคุณทราบถึงตำแหน่งและสถานะของรถ ตัวอย่างเช่น ยานพาหนะอาจจะ ONLINE
หรือ OFFLINE
และตำแหน่งของรถจะเปลี่ยนไปเมื่อการเดินทางดำเนินไป
ข้อกำหนดขั้นต่ำของระบบ
อุปกรณ์เคลื่อนที่ต้องใช้ Android 6.0 (API ระดับ 23) ขึ้นไป
การกำหนดค่าบิลด์และการขึ้นต่อกัน
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
23 ขึ้นไป
หากต้องการเรียกใช้แอปที่สร้างด้วย 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 พร้อมให้ใช้งานจากที่เก็บของ Google Maven ที่เก็บจะรวมไฟล์ Project Object Model (.pom) และ Javadocs ของ SDK วิธีเพิ่ม Driver SDK ลงในแอป
เพิ่มทรัพยากร Dependency ต่อไปนี้ในการกำหนดค่า Gradle หรือ Maven ของคุณ โดยแทนที่ตัวยึดตำแหน่ง
VERSION_NUMBER
สำหรับเวอร์ชันที่ต้องการของ Driver SDKGradle
เพิ่มสิ่งต่อไปนี้ใน
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 ไดรเวอร์อาศัย SDK การนำทาง ทรัพยากรประเภทนี้ได้รับการกำหนดค่าในลักษณะที่ว่าหากต้องใช้ Navigation SDK เวอร์ชันใดเวอร์ชันหนึ่ง จะต้องมีกำหนดอย่างชัดเจนในไฟล์การกำหนดค่าบิลด์ดังต่อไปนี้ การละเว้นบล็อกโค้ดดังกล่าวจะทำให้โปรเจ็กต์ดาวน์โหลด Navigation SDK เวอร์ชันล่าสุดภายในเวอร์ชันหลักได้เสมอ โปรดทราบว่าลักษณะการทํางานร่วมกันของ Driver SDK และ Navigation SDK เวอร์ชันล่าสุดได้รับการทดสอบที่เข้มงวดก่อนการเผยแพร่
จัดเรียงการกำหนดค่าทรัพยากร Dependency ของการพัฒนาและปล่อยสภาพแวดล้อมให้สอดคล้องกัน
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 ลงในแอป
เมื่อเพิ่ม Driver 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.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 ในแอป คุณต้องใส่ข้อความระบุแหล่งที่มาและใบอนุญาตโอเพนซอร์สเป็นส่วนหนึ่งของส่วนประกาศทางกฎหมายของแอป คุณควรรวมการระบุแหล่งที่มาเป็นรายการในเมนูอิสระหรือเป็นส่วนหนึ่งของรายการในเมนูเกี่ยวกับ
ดูข้อมูลใบอนุญาตได้ในไฟล์ "third_party_licenses.txt" ในไฟล์ AAR ที่ไม่ได้เก็บถาวร
ดูวิธีรวมประกาศโอเพนซอร์สได้ที่ https://developers.google.com/android/guides/opensource
การอ้างอิง
หากคุณใช้ ProGuard เพื่อเพิ่มประสิทธิภาพบิลด์ คุณอาจต้องเพิ่มบรรทัดต่อไปนี้ลงในไฟล์การกำหนดค่า ProGuard
-dontwarn com.google.**
-dontwarn okio.**
ระดับ API ขั้นต่ำที่รองรับคือ 23
การเริ่มต้น 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 Web Token (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
จะถือว่าเป็นชั่วคราว เว้นแต่จะเกิดขึ้นซ้ำๆ หลังจากพยายามหลายครั้ง Driver SDK จะถือว่าข้อผิดพลาดนี้มีผลถาวรและจะหยุดพยายามส่งการอัปเดต
การรายงานสถานะและข้อผิดพลาดเกี่ยวกับ StatusListener
เนื่องจาก Driver 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
ระบบจะกำหนดเวลาอัปเดตครั้งสุดท้ายให้คุณในการโทรครั้งนี้ ซึ่งบ่งบอกว่ายานพาหนะออฟไลน์อยู่ การอัปเดตนี้จะไม่มีตำแหน่งของผู้ใช้
การตั้งค่าสถานะของพาหนะ
เมื่อเปิดใช้การอัปเดตตำแหน่ง การตั้งสถานะพาหนะเป็น 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
ซึ่งคล้ายกับการจัดการข้อผิดพลาดในการอัปเดตตำแหน่ง