ניתן להשתמש ב-Driver SDK על מנת לשפר את הניווט והמעקב באפליקציה ל'התקדמות והזמנה'. ה-Driver SDK מספק עדכונים לגבי מיקום הרכב ועדכונים לגבי משימות במנוע Fleet לחבילות ולנסיעות לפי דרישה.
בזכות ה-SDK של הנהג, שירותי ה-Flet Engine והשירותים המותאמים אישית שלכם מעדכנים את המיקום והמצב של הרכב. לדוגמה, הרכב יכול להיות ONLINE
או OFFLINE
, ומיקום הרכב משתנה עם התקדמות הנסיעה.
דרישות מערכת מינימליות
במכשיר הנייד צריכה לפעול מערכת Android בגרסה 6.0 (API ברמה 23) ואילך.
הגדרת build וקשרי תלות
גרסאות 4.99 ואילך של Driver SDK זמינות ממאגר 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>
הגדרת הפרויקט
כדי להשתמש ב-SDK של Drive, האפליקציה צריכה לטרגט ל-minSdkVersion
23 ואילך.
כדי להריץ אפליקציה שנוצרה עם Driver SDK, צריך להתקין במכשיר ה-Android את Google Play Services.
הגדרת פרויקט הפיתוח
כדי להגדיר את פרויקט הפיתוח ולקבל מפתח API לפרויקט במסוף Google Cloud:
יוצרים פרויקט חדש במסוף Google Cloud או בוחרים פרויקט קיים לשימוש עם Driver SDK. ממתינים מספר דקות עד שהפרויקט החדש מופיע במסוף Google Cloud.
כדי להפעיל את אפליקציית ההדגמה, לפרויקט צריכה להיות גישה ל-SDK של מפות Google ל-Android. במסוף Google Cloud, בוחרים באפשרות APIs & Services > Library, ולאחר מכן מחפשים את ה-SDK של מפות Google ל-Android ומפעילים אותו.
כדי לקבל מפתח API לפרויקט, לוחצים על APIs & Services > Credentials > Create credentials > API key. במאמר קבלת מפתח API תוכלו לקרוא מידע נוסף על קבלת מפתח API.
הוספת ה-SDK של Drive לאפליקציה
Driver SDK זמין ממאגר Google Maven. המאגר כולל את קובצי Project Object Model (.pom) של ה-SDK ואת קובצי Javadocs. כדי להוסיף את ה-SDK של Drive לאפליקציה:
מוסיפים את התלות הבאה להגדרות של Gradle או Maven, ומחליפים את ה-placeholder
VERSION_NUMBER
בגרסה הרצויה של ה-SDK של Driver.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>
ה-SDK של מנהל ההתקן תלוי ב-Navigation SDK. התלות הזו מוגדרת כך שאם דרושה גרסה ספציפית של Navigation SDK, היא צריכה להיות מוגדרת באופן מפורש בקובץ תצורת ה-build כמו בדוגמה הבאה. השמטת גוש הקוד שהוזכר תאפשר לפרויקט להוריד תמיד את הגרסה האחרונה של ה-API של הניווט בגרסה הראשית. שימו לב שההתנהגויות המשולבות של הגרסאות העדכניות של Driver SDK ו-Navigation SDK עברו בדיקות קפדניות לפני שהושקו.
חשוב לארגן את תצורת התלות של הפיתוח ולפרסם את הסביבות בהתאם.
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
זמין במאמר קבצים של מאפייני גראנד.
כדי לייעל את המשימה הזו, תוכלו להשתמש בפלאגין של Secrets Gradle ל-Android.
כדי להתקין את הפלאגין ולאחסן את מפתח ה-API:
פותחים את הקובץ
build.gradle
ברמה הבסיסית (root) ומוסיפים את הקוד הבא לרכיב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
במפתח ה-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.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>
הכללת הייחוסים הנדרשים באפליקציה
אם השתמשת ב-Drive SDK באפליקציה, עליך לכלול טקסט שיוך ורישיונות קוד פתוח בקטע ההודעות המשפטיות של האפליקציה. מומלץ לכלול את פרטי הייחוס כפריט בתפריט עצמאי או כחלק ממידע כללי.
פרטי הרישיונות מופיעים בקובץ "Third_party_Licenses.txt" בקובץ ה-AAR שאוחזר.
במאמר https://developers.google.com/android/guides/opensource מוסבר איך לכלול הודעות בקוד פתוח.
יחסי תלות
אם אתם משתמשים ב-ProGuard כדי לבצע אופטימיזציה של גרסאות ה-build, יכול להיות שתצטרכו להוסיף את השורות הבאות לקובץ התצורה של ProGuard:
-dontwarn com.google.**
-dontwarn okio.**
רמת ה-API המינימלית הנתמכת היא 23.
אתחול ה-SDK
כדי לאתחל את האובייקט DriverContext
נדרש מזהה ספק (בדרך כלל מזהה הפרויקט ב-Google Cloud). למידע נוסף על הגדרת הפרויקט ב-Google Cloud, קראו את המאמר אימות והרשאה.
לפני השימוש ב-Driver SDK, צריך לאתחל את הניווט 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. כדי לאמת את הבקשות האלה, ה-SDK של Drive יבצע קריאה למכונה 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)
}
}
}
ההטמעה הספציפית הזו משתמשת בלקוח ה-HTTP המובנה של Java כדי לאחזר אסימון בפורמט JSON משרת האימות של המפתח. האסימון נשמר לשימוש חוזר. האסימון מאוחזר מחדש אם האסימון הישן נמצא בטווח של 10 דקות מזמן התפוגה שלו.
בהטמעה עשויה להתבצע פעולות שונות, למשל שימוש בשרשור ברקע כדי לרענן אסימונים.
החריגים ב-AuthTokenFactory
יטופלו כזמניים, אלא אם הם מתרחשים באופן חוזר ונשנה. אחרי מספר ניסיונות, ערכת ה-SDK של Drive תניח שהשגיאה קבועה והיא תפסיק לשלוח עדכונים.
דיווח סטטוס ושגיאות עם StatusListener
מכיוון שה-Drive 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
יסמן את הרכב כלא זמין.
אפשר להגדיר את מצב הרכב בצד השרת (ראו עדכון כלי רכב) או ישירות ב-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
.