תוכלו להשתמש ב-SDK לצרכנים כדי ליצור ולהפעיל אפליקציה בסיסית לצרכנים שמשולבת עם שירותים לקצה העורפי של 'נסיעות ומשלוחים' על פי דרישה. אתם יכולים ליצור אפליקציה של נסיעה והתקדמות בהזמנה שיכולה להציג נסיעה פעילה, להגיב לעדכוני נסיעה ולטפל בשגיאות בנסיעה.
מכיוון של- Consumer SDK יש ארכיטקטורה מודולרית, תוכלו להשתמש בחלקי ה-API שבהם אתם רוצים להשתמש באפליקציה הספציפית שלכם ולשלב אותם בממשקי API משלכם, בשירותים לקצה העורפי שמסופקים על ידי Fleet Engine, וגם בממשקי API של הפלטפורמה של מפות Google.
דרישות מערכת מינימליות
במכשיר הנייד צריכה לפעול מערכת Android בגרסה 6.0 (API ברמה 23) ואילך.
הגדרת build ויחסי תלות
גרסאות 1.99.0 ואילך של 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 לצרכנים ל-Android, האפליקציה צריכה לטרגט ל-minSdkVersion
בגרסה 23 ואילך.
כדי להריץ אפליקציה שנוצרה באמצעות ה-SDK לצרכנים, צריך להתקין במכשיר ה-Android את Google Play Services.
הגדרת פרויקט פיתוח
כדי להגדיר את פרויקט הפיתוח ולקבל מפתח API לפרויקט במסוף Google Cloud:
יוצרים פרויקט חדש במסוף Google Cloud או בוחרים פרויקט קיים לשימוש עם ה-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 לצרכנים לאפליקציה
ה-SDK לצרכנים זמין דרך מאגר Maven פרטי. המאגר כולל את קובצי Project Object Model (.pom) של ה-SDK ואת Javadocs. כדי להוסיף את ה-SDK לצרכנים לאפליקציה:
מגדירים את הסביבה כדי לגשת למאגר Maven המארח, כמו שמתואר בקטע הקודם.
אם הצהרת על הגדרה מרוכזת של ניהול תלות ב-
settings.gradle
, צריך להשבית אותה באופן הבא.מסירים את בלוק הקוד הבא ב-
settings.gradle
:import org.gradle.api.initialization.resolve.RepositoriesMode dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() } }
מוסיפים את התלות הבאה להגדרות של Gradle או Maven, ומחליפים את ה-placeholder הזה
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 לצרכן תלויה ב-SDK של מפות Google. התלות הזו מוגדרת כך שאם גרסת ה-SDK של מפות Google לא מוגדרת במפורש בקובץ תצורת build, כמו בדוגמה הבאה, כשתושק גרסה חדשה של מפות Google, ה-SDK לצרכנים ממשיך להשתמש בגרסה המינימלית הנתמכת של SDK של מפות Google הנדרשת על ידה.
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 לאפליקציה
אחרי שמוסיפים לאפליקציה את ה-SDK לצרכנים, מוסיפים את מפתח ה-API לאפליקציה. עליכם להשתמש במפתח ה-API של הפרויקט שקיבלתם כשהגדרתם את פרויקט הפיתוח.
בקטע הזה מוסבר איך לאחסן את מפתח ה-API כדי שהאפליקציה תוכל להפנות אליו בצורה מאובטחת יותר. אל תבדקו את מפתח ה-API במערכת ניהול הגרסאות שלכם. צריך לאחסן אותו בקובץ local.properties
, שנמצא בתיקיית השורש של הפרויקט. למידע נוסף על הקובץ local.properties
ראו קובצי מאפייני Gradle.
כדי לייעל את המשימה הזו, אפשר להשתמש בפלאגין של 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.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>
לכלול את הייחוסים הנדרשים באפליקציה
אם אתם משתמשים ב-SDK לצרכנים באפליקציה שלכם, אתם צריכים לכלול את טקסט השיוך (Attribution) ורישיונות קוד פתוח כחלק מהקטע 'הודעות משפטיות' של האפליקציה. מומלץ לכלול את הקרדיטים האלה כאפשרות עצמאית בתפריט או כחלק מפריט בתפריט מידע כללי.
ניתן למצוא את פרטי הרישיונות בקובץ 'third_party_Licenses.txt' בקובץ ה-AAR מהארכיון.
במאמר https://developers.google.com/android/guides/opensource מוסבר איך מוסיפים הודעות בנושא קוד פתוח.
אימות SDK של צרכן
ה-SDK לצרכן מספק אימות באמצעות אסימוני אינטרנט JSON. אסימון אינטרנט מסוג JSON (JWT) הוא אסימון גישה מבוסס JSON שמספק הצהרה אחת או יותר על שירות. לדוגמה, שרת יכול ליצור אסימון עם ההצהרה 'מחובר כאדמין' ולספק אותו ללקוח. לאחר מכן הלקוח יוכל להשתמש באסימון הזה כדי להוכיח שהוא מחובר כאדמין.
הצרכן של SDK משתמש באסימון האינטרנט מסוג JSON שמסופק על ידי האפליקציה כדי לתקשר עם Fleet Engine. למידע נוסף, ראו אימות והרשאה של מנוע חיפוש.
אסימון ההרשאה חייב לכלול הצהרת tripid:TRIP_ID
בכותרת authorization
של האסימון, כאשר TRIP_ID
הוא מזהה הנסיעה. כך תהיה ל-SDK גישה לפרטי הנסיעה, כולל המיקום של הרכב, המסלול וזמן ההגעה המשוער.
קריאה חוזרת (callback) של אסימון אינטרנט מסוג JSON
במהלך האתחול, ה-SDK של הצרכן רושם באפליקציה קריאה חוזרת (callback) של אסימון הרשאה. ה-SDK קורא לאפליקציה לקבל אסימון לכל בקשות הרשת שמחייבות הרשאה.
מומלץ מאוד שאסימון ההרשאה של הטמעת הקריאה החוזרת (callback) יהיה זמין במטמון, ולרענן אותם רק אחרי המועד של expiry
. האסימונים צריכים להיות עם תפוגה של שעה אחת.
הקריאה החוזרת של אסימון ההרשאה מציינת איזה אסימון שירות צריך בשביל השירות 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. מידע נוסף על יצירת הפרויקט זמין במדריך למשתמש של כלל המכשירים בארגון.
באפליקציה שלכם צריך להטמיע את 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
}
SDK של מפות Google וכלים לעיבוד מפות
Consumer SDK גרסה 2.x.x תומך ב-SDK של מפות Google ל-Android גרסה 18.1.0 ואילך. הטבלה שבהמשך מציגה סיכום של כלי הרינדור שמוגדר כברירת מחדל לפי גרסת ה-SDK של מפות Google ויכולת התמיכה של שני כלי הרינדור. אבל אם אתם צריכים להשתמש בכלי הישן לרינדור, תוכלו לציין אותו באופן מפורש באמצעות MapsInitializer.initialize()
.
גרסת SDK של מפות Google | תמיכה בכלי לרינדור העדכני ביותר | תמיכה בכלי לרינדור מדור קודם | כלי לעיבוד שמוגדר כברירת מחדל |
---|---|---|---|
גרסה 18.1.0 ומטה | כן | כן | דור קודם* |
V18.2.0 | כן | כן | פורסמו לאחרונה |
* לאחר ההשקה של הכלי החדש לעיבוד מפות Google, הכלי האחרון לרינדור יוגדר כברירת מחדל.
הוספת SDK של מפות כתלות
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>
אתחול ה-SDK של מפות Google לפני הפעלת ה-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) ולפריטים גרפיים וקטוריים
אם עיצוב האפליקציה דורש תמיכה במכשירי 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
), כפי שמוצג בדוגמת הקוד הבאה. ה-method onCreate()
אמורה להפעיל את getConsumerGoogleMapAsync(callback)
, שמחזירה את ConsumerGoogleMap
באופן אסינכרוני בקריאה החוזרת. אחר כך משתמשים ב-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()
צריכה להגיע מה-method 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()
. בנוסף לפרמטר הקריאה החוזרת, היא מחייבת את הפעילות או המקטע שמכילים את הפעילות ואת 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
במקטע זהה לדוגמה שלמעלה לגבי MapView
בפעילות, אבל המקטע מנפח את הפריסה שכוללת את MapView
ב-method 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)
}
}
כוונון זום המצלמה כדי להתמקד במסע
ברירת המחדל של לחצן המיקום שלי שמובנית ב-SDK של מפות Google ממרכזת את המצלמה במיקום המכשיר.
אם יש סשן פעיל של שיתוף מסלול, כדאי למרכז את המצלמה כדי להתמקד בתהליך במקום במיקום המכשיר.
פתרון SDK מובנה לצרכן ב-Android: Auto Camera
כדי לאפשר לכם להתמקד בתהליך במקום במיקום המכשיר, ה-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
. השימוש במפת הצרכנים מאפשר לאפליקציה ולשיתוף הנסיעות ליצור אינטראקציה חלקה עם אותה מפה בסיסית של Google. לדוגמה, הפקודה GoogleMap
מאפשרת רישום של קריאה חוזרת רק פעם אחת, אבל ConsumerGoogleMap
תומך בקריאות חוזרות (callbacks) רשומות כפולות.
הקריאות החוזרות האלה מאפשרות לאפליקציה ולשיתוף הנסיעה כדי לרשום קריאות חוזרות, שנקראות ברצף.
ConsumerController
ל-ConsumerController
יש גישה לפונקציות של שיתוף נסיעות, כמו מעקב אחר נסיעות, שליטה בסטטוס הנסיעה והגדרת מיקומים.
הגדרה של שיתוף הנסיעות
אחרי ההתאמה בין הקצה העורפי לבין הרכב בין הצרכן לבין הרכב, משתמשים ב-JourneySharingSession
כדי להתחיל את התהליך של שיתוף ממשק המשתמש. בשיתוף הנסיעה רואים את המיקום והמסלול התואמים של הרכב. אחרי שמטמיעים את ה-SDK באפליקציה, אפשר להוסיף
פונקציונליות למעקב אחרי נסיעות, להאזנה לעדכונים ולטיפול בשגיאות.
במסגרת הנוהלים הבאים, ההנחה היא שהשירותים לקצה העורפי קיימים ושהשירותים שלכם להתאמה לצרכנים לרכבים פועלים.
ניתן לרשום מאזינים על אובייקט
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 | הכנסה לקליק | תיאור |
---|---|---|
400 | INVALID_ARGUMENT | הלקוח ציין שם נסיעה לא חוקי. שם הנסיעה צריך להיות בפורמט providers/{provider_id}/trips/{trip_id} .
הערך provider_id חייב להיות המזהה של הפרויקט ב-Cloud שבבעלות ספק השירות. |
401 | לא מאומת | הבקשה לא אומתה כי אסימון JWT לא תקין. השגיאה הזו תתרחש אם אסימון ה-JWT נחתם ללא מזהה נסיעה או אם פג התוקף של אסימון ה-JWT. |
403 | PERMISSION_DENIED | ללקוח אין הרשאה מספקת. השגיאה הזו מתקבלת כשאסימון ה-JWT לא תקין, אם ללקוח אין הרשאה או שה-API לא מופעל בפרויקט הלקוח. יכול להיות שאסימון ה-JWT חסר או שהוא חתום עם מזהה נסיעה שלא תואם למזהה הנסיעה המבוקש. |
429 | RESOURCE_EXHAUSTED | מכסת המשאבים היא אפס או שקצב תעבורת הנתונים חורג מהמגבלה. |
503 | UNAVAILABLE | השירות לא זמין. בדרך כלל השרת מושבת. |
504 | DEADLINE_EXCEEDED | המועד האחרון של הבקשה עבר. זה יקרה רק אם המתקשר יגדיר מועד אחרון שקצר ממועד ברירת המחדל שנקבע כברירת מחדל לשיטה (כלומר, המועד האחרון המבוקש לא מספיק לטיפול בבקשה), והבקשה לא הסתיימה במסגרת המועד האחרון. |
מידע נוסף זמין במאמר טיפול בשגיאות ב-SDK לצרכנים.