תחילת העבודה עם SDK SDK ל-Android

ניתן להשתמש ב-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:

  1. יוצרים פרויקט חדש במסוף Google Cloud או בוחרים פרויקט קיים לשימוש לצרכנים ב-SDK. צריך להמתין כמה דקות עד שהפרויקט החדש יופיע במסוף Google Cloud.

  2. כדי להפעיל את אפליקציית ההדגמה, לפרויקט שלך צריכה להיות גישה ל-SDK של מפות Google ל-Android. במסוף Google Cloud, ממשקי API שירותים > לספרייה ולאחר מכן לחפש ולהפעיל את ה-SDK של מפות Google עבור Android.

  3. כדי לקבל מפתח API לפרויקט, בוחרים באפשרות ממשקי API שירותים > פרטי כניסה > יצירת פרטי כניסה > מפתח API. מידע נוסף על קבלת מפתח API זמין במאמר קבלת מפתח API

הוספת ה-SDK לצרכנים לאפליקציה

ה-SDK לצרכנים זמין דרך מאגר Maven פרטי. מאגר כולל את קובצי Project Object Model (.pom) ואת Javadocs של ה-SDK. כדי להוסיף את ה-SDK לצרכנים לאפליקציה:

  1. מגדירים את הסביבה כדי לגשת למאגר Maven המארח, כפי שמתואר ב בקטע הקודם.

    אם הצהרת על הגדרה מרוכזת של ניהול תלות ב- settings.gradle, אפשר להשבית אותה לפי ההוראות שבהמשך.

    • מסירים את בלוק הקוד הבא ב-settings.gradle:

      import org.gradle.api.initialization.resolve.RepositoriesMode
      dependencyResolutionManagement {
          repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
          repositories {
              google()
              mavenCentral()
          }
      }
      
  2. מוסיפים את התלות הבאה להגדרות של 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>
    
  3. ערכת ה-SDK לצרכן תלויה ב-SDK של מפות Google. התלות הזאת מוגדרת אם גרסת ה-SDK של מפות Google לא מוגדרת במפורש את קובץ תצורת build כמו בדוגמה הבאה, כשגרסה חדשה של מפות Google ההשקה של ה-SDK, ערכת ה-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:

  1. פותחים את קובץ 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")
        }
    }
    
  2. עליך לפתוח את הקובץ build.gradle ברמת האפליקציה ולהוסיף את הקוד הבא אל רכיב plugins.

    מגניב

    id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
    

    Kotlin

    id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
    
  3. אם משתמשים ב-Android Studio, לסנכרן את הפרויקט עם Gradle

  4. פותחים את local.properties בספרייה ברמת הפרויקט ומוסיפים את באמצעות הקוד הבא. מחליפים את YOUR_API_KEY במפתח ה-API שלכם.

    MAPS_API_KEY=YOUR_API_KEY
    
  5. בקובץ 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 שמספק אסימון או יותר תלונות על שירות מסוים. לדוגמה, שרת יכול ליצור אסימון עם ההצהרה 'מחובר כאדמין' ונספק ללקוח. לאחר מכן הלקוח יכול להשתמש באסימון הזה כדי להוכיח הוא מחובר כאדמין.

Consumer SDK משתמש ב-JSON Web Token שסופק על ידי האפליקציה כדי לתקשר עם 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

כדי להשתמש ב-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() ולהמתין לתוצאת בקשת הרינדור לפני האתחול 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 באופן אסינכרוני בקריאה החוזרת (callback). לאחר מכן משתמשים ב-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() צריכה להגיע מ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() method.

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 לצרכן מספקת תכונה של מצלמה אוטומטית מופעלת כברירת מחדל. המצלמה משנה את מרחק התצוגה כדי להתמקד במסלול לשיתוף הנסיעה אל ציון הדרך הבא בנסיעה.

AutoCamera

התאמה אישית של התנהגות המצלמה

אם דרושה לך שליטה רבה יותר על התנהגות המצלמה, ניתן להשבית או להפעיל המצלמה האוטומטית באמצעות 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 יש תמיכה בקריאות חוזרות (callbacks) רשומות כפולות. הקריאות החוזרות האלה מאפשרות לאפליקציה ולשיתוף הנסיעות לרשום את הקריאה החוזרת, שנקראים ברצף.

ConsumerController

האפליקציה ConsumerController מספקת גישה לפונקציות של שיתוף נסיעות, כמו מעקב אחר נסיעות, שליטה בסטטוס הנסיעה והגדרת מיקומים.

הגדרה של שיתוף הנסיעות

אחרי שהקצה העורפי מתאים בין צרכן לבין רכב, צריך להשתמש ב-JourneySharingSession כדי להתחיל את תהליך השיתוף של ממשק המשתמש. בשיתוף התהליך מוצגת ההתאמה המיקום והמסלול של הרכב. אחרי הטמעת ה-SDK באפליקציה, אפשר להוסיף הפונקציונליות למעקב אחרי נסיעות, להאזנה לעדכונים ולטיפול בשגיאות. במסגרת ההליכים הבאים, ההנחה היא שהשירותים לקצה העורפי נמצאים השירותים להתאמה של צרכנים עם כלי רכב פעילים.

  1. רישום אוזן באובייקט 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?,
        ) {
          // ...
        }
    
      // ...
    })
    
  2. הגדרת הנסיעה באמצעות 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 חייב להיות המזהה של פרויקט בענן בבעלות ספק השירות.
401 לא מאומת הבקשה לא אומתה עקב אסימון JWT לא חוקי. השגיאה הזו תתבצע אם אסימון ה-JWT חתום ללא נסיעה או אסימון ה-JWT.
403 PERMISSION_DENIED לא מספיק ללקוח הרשאה. השגיאה הזו מתקבלת אם ה-JWT האסימון לא חוקי, ללקוח אין או שה-API לא הופעל עבור בפרויקט הלקוח. אסימון ה-JWT יכול להיות חסר או שהאסימון חתום עם נסיעה מזהה שלא תואם למזהה הנסיעה המבוקש.
429 RESOURCE_EXHAUSTED מכסת המשאבים היא אפס או הקצב מתנועת הגולשים חורגת מהמגבלה.
503 UNAVAILABLE השירות לא זמין. בדרך כלל השרת מושבתת.
504 DEADLINE_EXCEEDED המועד האחרון של הבקשה עבר. הפעולה הזו תגרור מתרחשת רק אם המתקשר מגדיר מועד אחרון שהוא קצר יותר מברירת המחדל של השיטה המועד האחרון (כלומר, המועד האחרון המבוקש אינו זהה) מספיק כדי שהשרת יוכל לעבד ) והבקשה לא הושלמה במסגרת המועד האחרון.

מידע נוסף זמין במאמר הבא: טיפול בשגיאות ב-SDK לצרכנים.