Bạn có thể sử dụng SDK Driver để cung cấp tính năng điều hướng và theo dõi nâng cao cho ứng dụng Chuyến đi và Tiến trình đặt hàng. SDK Driver cung cấp thông tin cập nhật về vị trí xe và công việc cho nhóm giải pháp gọi xe và giao hàng theo yêu cầu.
SDK trình điều khiển giúp các dịch vụ của Fleet Engine và dịch vụ tuỳ chỉnh của bạn biết được
vị trí và trạng thái của xe. Ví dụ: xe có thể là ONLINE
hoặc OFFLINE
và vị trí của xe sẽ thay đổi khi chuyến đi diễn ra.
Yêu cầu tối thiểu về hệ thống
Thiết bị di động phải chạy Android 6.0 (API cấp 23) trở lên.
Cấu hình bản dựng và phần phụ thuộc
SDK trình điều khiển phiên bản 4.99 trở lên có trong kho lưu trữ Maven của Google.
Gradle
Thêm đoạn mã sau vào tệp build.gradle
của bạn:
repositories {
...
google()
}
Maven
Thêm đoạn mã sau vào tệp pom.xml
của bạn:
<project>
...
<repositories>
<repository>
<id>google-maven-repository</id>
<url>https://maven.google.com</url>
</repository>
</repositories>
...
</project>
Cấu hình dự án
Để sử dụng SDK trình điều khiển, ứng dụng của bạn phải nhắm đến minSdkVersion
23 trở lên.
Để chạy một ứng dụng được tạo bằng SDK trình điều khiển, thiết bị Android phải cài đặt Dịch vụ Google Play.
Thiết lập dự án phát triển
Cách thiết lập dự án phát triển và lấy khoá API cho dự án trên Google Cloud Console:
Tạo dự án Google Cloud Console mới hoặc chọn dự án hiện có để sử dụng với SDK trình điều khiển. Đợi vài phút cho đến khi dự án mới xuất hiện trên Google Cloud Console.
Để chạy ứng dụng minh hoạ, dự án của bạn phải có quyền truy cập vào SDK Maps dành cho Android. Trong Google Cloud Console, hãy chọn APIs & Services > Library (API và dịch vụ > Thư viện), sau đó tìm kiếm và bật SDK Maps cho Android.
Lấy khoá API cho dự án bằng cách chọn APIs & Services > Credentials > Create credentials > API key (API và Dịch vụ > Thông tin xác thực > Tạo thông tin xác thực > Khoá API). Để biết thêm thông tin về cách lấy khoá API, hãy xem bài viết Lấy khoá API.
Thêm SDK trình điều khiển vào ứng dụng
SDK Trình điều khiển có trong kho lưu trữ Google Maven. Kho lưu trữ bao gồm các tệp Mô hình đối tượng dự án (.pom) của SDK và tài liệu Java. Cách thêm Driver SDK vào ứng dụng:
Thêm phần phụ thuộc sau vào cấu hình Gradle hoặc Maven, thay thế phần giữ chỗ
VERSION_NUMBER
cho phiên bản mong muốn của SDK trình điều khiển.Gradle
Thêm nội dung sau vào
build.gradle
của bạn:dependencies { ... implementation 'com.google.android.libraries.mapsplatform.transportation:transportation-driver:VERSION_NUMBER' }
Maven
Thêm nội dung sau vào
pom.xml
của bạn:<dependencies> ... <dependency> <groupId>com.google.android.libraries.mapsplatform.transportation</groupId> <artifactId>transportation-driver</artifactId> <version>VERSION_NUMBER</version> </dependency> </dependencies>
SDK điều khiển phụ thuộc vào SDK điều hướng, phần phụ thuộc này được định cấu hình theo cách cần có phiên bản cụ thể của SDK điều hướng, cần được xác định rõ ràng trong tệp cấu hình bản dựng như sau. Việc bỏ qua khối mã đã đề cập sẽ cho phép dự án luôn tải phiên bản mới nhất của SDK điều hướng trong phiên bản phát hành chính. Xin lưu ý rằng các hoạt động kết hợp của các phiên bản mới nhất của SDK trình điều khiển và SDK điều hướng đã trải qua quy trình kiểm thử nghiêm ngặt trước khi phát hành.
Sắp xếp cấu hình phần phụ thuộc của môi trường phát triển và phát hành cho phù hợp.
Gradle
Thêm nội dung sau vào
build.gradle
của bạn:dependencies { ... implementation 'com.google.android.libraries.navigation:navigation:5.0.0' }
Maven
Thêm nội dung sau vào
pom.xml
của bạn:<dependencies> ... <dependency> <groupId>com.google.android.libraries.navigation</groupId> <artifactId>navigation</artifactId> <version>5.0.0</version> </dependency> </dependencies>
Thêm khoá API vào ứng dụng
Sau khi thêm SDK trình điều khiển vào ứng dụng, hãy thêm khoá API vào ứng dụng. Bạn phải sử dụng khoá API dự án đã nhận được khi thiết lập dự án phát triển.
Phần này mô tả cách lưu trữ khoá API để ứng dụng của bạn có thể tham chiếu khoá đó một cách an toàn hơn. Bạn không nên kiểm tra khoá API trong hệ thống quản lý phiên bản của mình. Tệp này phải được lưu trữ trong tệp local.properties
, nằm trong thư mục gốc của dự án. Để biết thêm thông tin về tệp local.properties
, hãy xem các tệp thuộc tính Gradle.
Để đơn giản hoá tác vụ này, bạn có thể dùng Trình bổ trợ Bí mật cho Gradle cho Android.
Cách cài đặt trình bổ trợ và lưu trữ khoá API:
Mở tệp
build.gradle
ở cấp độ gốc rồi thêm mã sau vào phần tửdependencies
trongbuildscript
.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") } }
Mở tệp
build.gradle
ở cấp ứng dụng rồi thêm mã sau vào phần tửplugins
.Groovy
id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
Kotlin
id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
Nếu bạn sử dụng Android Studio, hãy đồng bộ hoá dự án với Gradle.
Mở
local.properties
trong thư mục cấp dự án, sau đó thêm mã sau. Thay thếYOUR_API_KEY
bằng khoá API.MAPS_API_KEY=YOUR_API_KEY
Trong tệp
AndroidManifest.xml
, hãy chuyển đếncom.google.android.geo.API_KEY
rồi cập nhật thuộc tínhandroid:value
như sau:<meta-data android:name="com.google.android.geo.API_KEY" android:value="${MAPS_API_KEY}" />
Ví dụ sau đây minh hoạ một tệp kê khai đầy đủ cho một ứng dụng mẫu:
<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>
Bao gồm các thuộc tính bắt buộc trong ứng dụng của bạn
Nếu sử dụng SDK trình điều khiển trong ứng dụng, bạn phải đưa văn bản phân bổ và giấy phép nguồn mở vào mục thông báo pháp lý của ứng dụng. Bạn nên đưa các thuộc tính vào dưới dạng mục trình đơn độc lập hoặc dưới dạng mục trong trình đơn About (Giới thiệu).
Bạn có thể tìm thấy thông tin về giấy phép tại tệp "third_party_ permissions.txt" trong tệp AAR đã huỷ lưu trữ.
Hãy tham khảo https://developers.google.com/android/guides/opensource để biết cách đưa thông báo nguồn mở vào.
Phần phụ thuộc
Nếu sử dụng ProGuard để tối ưu hoá bản dựng, bạn có thể cần thêm các dòng sau vào tệp cấu hình ProGuard:
-dontwarn com.google.**
-dontwarn okio.**
Cấp độ API tối thiểu được hỗ trợ là 23.
Khởi chạy SDK
Bạn cần có mã nhà cung cấp (thường là mã dự án trên Google Cloud) để khởi động đối tượng DriverContext
. Để biết thêm thông tin chi tiết về cách thiết lập Dự án Google Cloud, hãy xem bài viết Xác thực và uỷ quyền.
Trước khi sử dụng SDK trình điều khiển, trước tiên, bạn phải khởi chạy SDK điều hướng. Cách khởi chạy SDK:
Lấy đối tượng
Navigator
từ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 } }, )
Tạo đối tượng
DriverContext
, điền sẵn các trường bắt buộc.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()
Sử dụng đối tượng
DriverContext
để khởi chạy*DriverApi
.Java
RidesharingDriverApi ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext);
Kotlin
val ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext)
Lấy
RidesharingVehicleReporter
từ đối tượng API. (*VehicleReporter
mở rộngNavigationVehicleReporter
.)Java
RidesharingVehicleReporter vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter();
Kotlin
val vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter()
Đang xác thực với AuthTokenFactory
Khi SDK trình điều khiển tạo thông tin cập nhật vị trí, SDK phải gửi những thông tin cập nhật này đến máy chủ Fleet Engine. Để xác thực các yêu cầu này, SDK trình điều khiển sẽ gọi một bản sao AuthTokenFactory
do phương thức gọi cung cấp.
Nhà máy (factory) chịu trách nhiệm tạo mã thông báo xác thực tại thời điểm cập nhật vị trí.
Cách tạo mã thông báo chính xác sẽ tuỳ theo tình huống của từng nhà phát triển. Tuy nhiên, việc triển khai có thể sẽ cần phải:
- tìm nạp mã thông báo xác thực, có thể ở định dạng JSON, từ máy chủ HTTPS
- phân tích cú pháp và lưu mã thông báo vào bộ nhớ đệm
- làm mới mã thông báo khi hết hạn
Để biết thông tin chi tiết về mã thông báo mà máy chủ Fleet Engine dự kiến, hãy xem phần Tạo mã thông báo web JSON (JWT) để uỷ quyền.
Dưới đây là cấu hình triển khai khung của 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)
}
}
}
Cách triển khai cụ thể này sử dụng ứng dụng HTTP Java tích hợp sẵn để tìm nạp một mã thông báo ở định dạng JSON từ máy chủ xác thực của nhà phát triển. Mã thông báo được lưu để sử dụng lại. Mã thông báo được tìm nạp lại nếu trong vòng 10 phút kể từ thời gian hết hạn của mã thông báo cũ.
Phương thức triển khai của bạn có thể hoạt động theo cách khác, chẳng hạn như sử dụng luồng trong nền để làm mới mã thông báo.
Các ngoại lệ trong AuthTokenFactory
sẽ được xem là tạm thời trừ phi các trường hợp này lặp lại. Sau một số lần thử, SDK trình điều khiển sẽ giả định rằng lỗi này là vĩnh viễn và sẽ ngừng tìm cách gửi bản cập nhật.
Báo cáo trạng thái và lỗi với StatusListener
Vì SDK trình điều khiển thực hiện các thao tác ở chế độ nền, nên hãy sử dụng StatusListener
để kích hoạt thông báo khi xảy ra một số sự kiện nhất định, chẳng hạn như lỗi, cảnh báo hoặc thông báo gỡ lỗi. Lỗi có thể chỉ tạm thời (chẳng hạn như BACKEND_CONNECTIVITY_ERROR
) hoặc có thể khiến yêu cầu cập nhật vị trí bị dừng vĩnh viễn (chẳng hạn như VEHICLE_NOT_FOUND
, cho biết có lỗi cấu hình).
Bạn có thể triển khai StatusListener
không bắt buộc như sau:
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.
}
}
Lưu ý về SSL/TLS
Trong nội bộ, việc triển khai SDK trình điều khiển sử dụng SSL/TLS để giao tiếp an toàn với máy chủ Fleet Engine. Các phiên bản Android cũ hơn (API phiên bản 19 trở xuống) có thể yêu cầu bản vá SecurityProvider
để có thể giao tiếp với máy chủ. Bạn nên xem bài viết này để biết thêm thông tin về cách làm việc với SSL trong Android. Bài viết này cũng chứa các mã mẫu để vá trình cung cấp dịch vụ bảo mật.
Bật thông báo cập nhật vị trí
Sau khi có một thực thể *VehicleReporter
, việc bật tính năng cập nhật vị trí sẽ rất đơn giản:
Java
RidesharingVehicleReporter reporter = ...;
reporter.enableLocationTracking();
Kotlin
val reporter = ...
reporter.enableLocationTracking()
Thông tin cập nhật vị trí được gửi định kỳ khi trạng thái của xe là ONLINE
. Xin lưu ý rằng việc gọi reporter.enableLocationTracking()
sẽ không tự động đặt trạng thái xe thành ONLINE
. Bạn phải đặt trạng thái xe một cách rõ ràng.
Theo mặc định, khoảng thời gian báo cáo là 10 giây. Bạn có thể thay đổi khoảng thời gian báo cáo bằng reporter.setLocationReportingInterval(long, TimeUnit)
. Khoảng thời gian tối thiểu được hỗ trợ cho việc cập nhật là 5 giây. Việc cập nhật thường xuyên hơn có thể khiến các yêu cầu và lỗi bị chậm hơn.
Tắt tính năng cập nhật vị trí
Khi người lái xe hoàn tất quá trình chuyển đổi, thông tin cập nhật vị trí có thể được dừng lại và xe được đánh dấu là không có kết nối mạng bằng cách gọi DeliveryVehicleReporter.disableLocationTracking
hoặc RidesharingVehicleReporter.disableLocationTracking
.
Lệnh gọi này sẽ lên lịch cập nhật cuối cùng để giao hàng ngay, cho biết rằng xe hiện không kết nối mạng. Thông tin cập nhật này sẽ không chứa thông tin vị trí của người dùng.
Đặt trạng thái xe
Khi bạn bật tính năng cập nhật vị trí, việc đặt trạng thái xe thành ONLINE
sẽ giúp xe xuất hiện cho các cụm từ tìm kiếm SearchVehicles
. Tương tự, việc đánh dấu một chiếc xe là OFFLINE
sẽ đánh dấu chiếc xe đó là không hoạt động.
Bạn có thể đặt trạng thái xe ở phía máy chủ (xem phần Cập nhật xe) hoặc ngay trong SDK trình điều khiển:
Java
RidesharingVehicleReporter reporter = ...;
reporter.enableLocationTracking();
reporter.setVehicleState(VehicleState.ONLINE);
Kotlin
val reporter = ...
reporter.enableLocationTracking()
reporter.setVehicleState(VehicleState.ONLINE)
Khi thông báo cập nhật vị trí được bật, lệnh gọi đến setVehicleState
sẽ được truyền vào lần cập nhật vị trí tiếp theo.
Việc đánh dấu một xe là ONLINE
khi tính năng theo dõi vị trí không được bật sẽ dẫn đến
IllegalStateException
. Xe có thể được đánh dấu là OFFLINE
khi tính năng theo dõi vị trí chưa được bật hoặc bị tắt một cách rõ ràng. Điều này sẽ dẫn đến việc cập nhật ngay lập tức. Lệnh gọi đến RidesharingVehicleReporter.disableLocationTracking()
sẽ đặt trạng thái của xe thành OFFLINE
.
Lưu ý setVehicleState
sẽ trả về ngay lập tức và quá trình cập nhật sẽ hoàn tất trên luồng cập nhật vị trí. Tương tự như việc xử lý lỗi khi cập nhật thông tin vị trí, các lỗi cập nhật trạng thái xe được truyền bằng cách sử dụng StatusListener
được cung cấp (không bắt buộc) trong DriverContext
.