תוכלו להשתמש ב- Consumer SDK כדי ליצור ולהפעיל אפליקציה בסיסית לצרכן שמשולבת בשירותים לקצה העורפי של נסיעות ומשלוחים על פי דרישה. ניתן לך ליצור אפליקציית 'נסיעות' ו'התקדמות בהזמנה', שיכולה להציג נסיעה פעילה, להגיב לעדכוני נסיעה ולטפל בשגיאות בנסיעה.
ל-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 ואילך.
כדי להפעיל אפליקציה שנוצרה עם Consumer SDK, במכשיר Android צריך להיות מותקן Google Play Services.
הגדרת פרויקט הפיתוח
כדי להגדיר את פרויקט הפיתוח ולקבל מפתח API לפרויקט במסוף Google Cloud:
יוצרים פרויקט חדש במסוף Google Cloud או בוחרים פרויקט קיים לשימוש עם Consumer SDK. ממתינים מספר דקות עד שהפרויקט החדש מופיע במסוף Google Cloud.
כדי להפעיל את אפליקציית ההדגמה, לפרויקט צריכה להיות גישה ל-SDK של מפות Google ל-Android. במסוף Google Cloud, בוחרים באפשרות APIs & Services > Library, ולאחר מכן מחפשים את ה-SDK של מפות Google ל-Android ומפעילים אותו.
כדי לקבל מפתח API לפרויקט, לוחצים על APIs & Services > Credentials > Create credentials > API key. במאמר קבלת מפתח API תוכלו לקרוא מידע נוסף על קבלת מפתח API.
הוספת Consumer SDK לאפליקציה שלך
Consumer SDK זמין דרך מאגר Maven פרטי. המאגר כולל את קובצי Project Object Model (.pom) של ה-SDK ואת קובצי Javadocs. כדי להוסיף את Consumer 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, כמו שמתואר בהמשך, כשתושק גרסה חדשה של ה-SDK של מפות Google, ה-SDK של מפות 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
זמין במאמר קבצים של מאפייני גראנד.
כדי לייעל את המשימה הזו, תוכלו להשתמש בפלאגין של 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 של האפליקציה, עליכם לכלול טקסט שיוך ורישיונות קוד פתוח בקטע ההודעות המשפטיות של האפליקציה. מומלץ לכלול את פרטי הייחוס כפריט בתפריט עצמאי או כחלק ממידע כללי.
פרטי הרישיונות מופיעים בקובץ "Third_party_Licenses.txt" בקובץ ה-AAR שאוחזר.
במאמר https://developers.google.com/android/guides/opensource מוסבר איך לכלול הודעות בקוד פתוח.
אימות SDK של צרכן
ה-SDK לצרכן מספק אימות באמצעות אסימוני אינטרנט מסוג JSON. אסימון אינטרנט מסוג JSON (JWT) הוא אסימון גישה מסוג JSON-base שמספק הצהרה אחת או יותר על שירות. לדוגמה, שרת יכול ליצור אסימון שההצהרה שלו היא 'מחובר כאדמין' ולספק אותה ללקוח. לאחר מכן הלקוח יוכל להשתמש באסימון הזה כדי להוכיח שהוא מחובר כאדמין.
Consumer SDK משתמש ב-JSON Web Token שסופק על ידי האפליקציה כדי לתקשר עם Fleet Engine. מידע נוסף זמין במאמר אימות והרשאה של מנוע חיפוש (Fleet Engine).
אסימון ההרשאה חייב לכלול הצהרת tripid:TRIP_ID
בכותרת authorization
של האסימון, כאשר TRIP_ID
הוא מזהה הנסיעה. כך ל-SDK של הצרכן יש גישה לפרטי הנסיעה, כולל מיקום הרכב, המסלול וזמן ההגעה המשוער.
קריאות חוזרות (callback) של אסימון אינטרנט מסוג JSON
ה-SDK של הצרכן רושם קריאה חוזרת של אסימון הרשאה באפליקציה במהלך האתחול. ה-SDK קורא לאפליקציה כדי לקבל אסימון לכל בקשות הרשת שמחייבות הרשאה.
מומלץ מאוד לאסימוני את אסימוני ההרשאה להטמעה של קריאה חוזרת במטמון ולרענן אותם רק אחרי הזמן של expiry
. האסימונים צריכים להיות מונפקים עם תפוגה של שעה אחת.
הקריאה החוזרת (callback) של אסימון ההרשאה מציינת איזה אסימון שירות נדרש
לשירות 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. מידע נוסף על יצירת הפרויקט זמין במדריך למשתמש של Flet Engine.
האפליקציה צריכה להטמיע את 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 v2.0.0 תומך ב-Maps SDK ל-Android מגרסה 18.1.0 ואילך. הוא תומך בבקשות שמציינות את כלי הרינדור המועדף למפות Google. לפרטים, קראו את המאמר כלי ליצירת מפות חדש(הצטרפות).
הוספה של ה-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>
הפעל את ה-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
), כפי שמוצג בדוגמת הקוד הבאה. לאחר מכן, השיטה 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
בשיטה 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 כברירת מחדל מרכזי את המצלמה למיקום המכשיר.
אם יש פעילות פעילה של שיתוף תהליך, כדאי למרכז את המצלמה כדי להתמקד בתהליך ולא במיקום המכשיר.
פתרון מובנה ל-Android SDK לצרכנים: Autocamera
כדי לאפשר לכם להתמקד במסע במקום במיקום המכשיר, ערכת ה-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
מאפשרת רישום של קריאה חוזרת (callback) אחת בלבד, אבל ConsumerGoogleMap
תומך בקריאות חוזרות (callback) עם רשומות כפולות.
הקריאות החוזרות האלה מאפשרות לאפליקציה ולשיתוף הנסיעות לתעד שיחות חוזרות, שנקראות ברצף.
ConsumerController
בעזרת ConsumerController
אפשר לגשת לפונקציונליות של שיתוף נסיעות, כמו מעקב אחר נסיעות, שליטה בסטטוס הנסיעה והגדרת מיקומים.
הגדרה של שיתוף נסיעות
אחרי שהקצה העורפי מתאים לצרכן לרכב, השתמשו ב-JourneySharingSession
כדי להתחיל את התהליך של שיתוף ממשק המשתמש. שיתוף התהליך מציג את מיקום הרכב
והמסלול המתאים. אחרי שמטמיעים את ה-SDK באפליקציה, אפשר להוסיף את הפונקציונליות למעקב אחרי נסיעות, להאזנה לעדכונים ולטיפול בשגיאות.
בהתאם לנוהלים הבאים, ההנחה היא שהשירותים לקצה העורפי קיימים ושהשירותים שלכם להתאמת צרכנים לרכבים פועלים.
רושמים listener על אובייקט
TripModel
כדי לקבל פרטים על הנסיעה, כמו זמן ההגעה המשוער (ETA) והמרחק שצריך לעבור ברכב לפני ההגעה.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 | המועד האחרון לשליחת הבקשה חלף. זה יקרה רק אם מבצע הקריאה החוזרת יגדיר תאריך יעד קצר יותר מברירת המחדל של המועד האחרון שנקבע לשיטה (כלומר, המועד האחרון המבוקש לא מספיק כדי שהשרת יעבד את הבקשה) והבקשה לא הסתיימה בטווח הזמן של המועד האחרון. |
למידע נוסף קראו את המאמר טיפול בשגיאות של Consumer SDK.