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

דרישות מערכת מינימליות

במכשיר הנייד צריכה להיות מותקנת מערכת 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>

הגדרות אישיות של פרויקט

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

כדי להריץ אפליקציה שנוצרה באמצעות Driver SDK, צריך להתקין במכשיר ה-Android את Google Play Services.

הגדרת פרויקט פיתוח

כדי להגדיר את פרויקט הפיתוח ולקבל מפתח API לפרויקט במסוף Google Cloud:

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

  2. כדי להריץ את אפליקציית ההדגמה, לפרויקט שלכם צריכה להיות גישה ל-SDK של מפות Google ל-Android. במסוף Google Cloud, בוחרים באפשרות APIs & Services > Library ואז מחפשים את ה-SDK של מפות Google ל-Android ומפעילים אותו.

  3. כדי לקבל מפתח API לפרויקט, בוחרים באפשרות APIs & Services > Credentials > Create credentials > API key. במאמר קבלת מפתח API תוכלו לקרוא מידע נוסף על קבלת מפתח API.

הוספת ה-Driver SDK לאפליקציה

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

  1. מוסיפים את התלות הבאה להגדרות של Gradle או Maven, ומחליפים את ה-placeholder של VERSION_NUMBER בגרסה שנבחרה של Driver SDK.

    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.driver</groupId>
        <artifactId>transportation-driver</artifactId>
        <version>[VERSION_NUMBER]</version>
      </dependency>
    </dependencies>
    
  2. ה-SDK של Drive תלוי ב-Navigation SDK. התלות הזו מוגדרת כך שאם נדרשת גרסה ספציפית של Navigation SDK, יש להגדיר אותה באופן מפורש בקובץ תצורת ה-build כמו בדוגמה הבאה. אם תשמיטו את בלוק הקוד שצוין, הפרויקט יוכל להוריד תמיד את הגרסה האחרונה של ה-Navigation SDK בגרסת הגרסה הראשית. שימו לב שההתנהגויות המשולבות של הגרסאות האחרונות של 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 ראו קובצי מאפייני Gradle.

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

לכלול את הייחוסים הנדרשים באפליקציה

אם אתם משתמשים ב-Driver SDK באפליקציה, אתם צריכים לכלול את טקסט השיוך ורישיונות קוד פתוח כחלק מהקטע 'הודעות משפטיות' של האפליקציה. מומלץ לכלול את הקרדיטים האלה כאפשרות עצמאית בתפריט או כחלק מפריט בתפריט מידע כללי.

ניתן למצוא את פרטי הרישיונות בקובץ 'third_party_Licenses.txt' בקובץ ה-AAR מהארכיון.

במאמר https://developers.google.com/android/guides/opensource מוסבר איך מוסיפים הודעות בנושא קוד פתוח.

יחסי תלות

ה-Driver SDK משתמש ב-gRPC כדי לתקשר עם השרת של Fleet Engine. אם אתם עדיין לא מכניסים את gRPC, יכול להיות שתצטרכו להצהיר על יחסי התלות הבאים:

dependencies {
    implementation 'io.grpc:grpc-android:1.12.0'
    implementation 'io.grpc:grpc-okhttp:1.12.0'
}

בלי יחסי התלות האלה, Driver SDK עלול להיתקל בשגיאות בזמן הריצה במהלך הניסיון לתקשר עם השרת של Fleet Engine.

אם אתם משתמשים ב-ProGuard כדי לבצע אופטימיזציה של גרסאות ה-build שלכם, יכול להיות שתצטרכו להוסיף את השורות הבאות לקובץ התצורה של ProGuard:

-dontwarn com.google.**
-dontwarn io.grpc.**
-dontwarn okio.**

רמת ה-API המינימלית הנתמכת היא 23.

הפעלת ה-SDK

כדי לאתחל את האובייקט DriverContext, צריך מזהה ספק (בדרך כלל מזהה הפרויקט ב-Google Cloud). למידע נוסף על הגדרת הפרויקט ב-Google Cloud, קראו את המאמר אימות והרשאה.

לפני השימוש ב-Driver SDK, צריך קודם לאתחל את ה-Navigation SDK. כדי לאתחל את ה-SDK:

  1. מקבלים אובייקט Navigator מה-NavigationApi.

    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;
          }
        }
    );
    
  2. יוצרים אובייקט DriverContext כדי לאכלס את שדות החובה.

    DriverContext driverContext = DriverContext.builder(application)
        .setProviderId(providerId)
        .setVehicleId(vehicleId)
        .setAuthTokenFactory(authTokenFactory)
        .setNavigator(navigator)
        .setRoadSnappedLocationProvider(
            NavigationApi.getRoadSnappedLocationProvider(application))
        .build();
    
  3. צריך להשתמש באובייקט DriverContext כדי לאתחל את *DriverApi.

    DeliveryDriverApi driverApi = DeliveryDriverApi.createInstance(driverContext);
    
  4. מקבלים את ה-DeliveryVehicleReporter מהאובייקט של ה-API. (DeliveryVehicleReporter נמשך NavigationVehicleReporter.)

    DeliveryVehicleReporter vehicleReporter = driverApi.getDeliveryVehicleReporter();
    

מתבצע אימות עם AuthTokenFactory

כש-Driver SDK יוצר עדכוני מיקום, הוא צריך לשלוח את העדכונים האלה לשרת Fleet Engine. כדי לאמת את הבקשות האלה, Driver SDK שולח קריאה למופע של AuthTokenFactory שסופק על ידי המתקשר. המפעל אחראי ליצור אסימוני אימות בזמן עדכון המיקום.

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

  • אחזור אסימון אימות משרת HTTPS, כנראה בפורמט JSON
  • לנתח את האסימון ולשמור אותו במטמון
  • לרענן את האסימון כשהתוקף שלו יפוג

במאמר יצירת אסימון אינטרנט מסוג JSON (JWT) לצורך הרשאה תוכלו לקרוא פרטים נוספים על האסימונים הנדרשים לשרת Fleet Engine.

זהו הטמעת בסיס של AuthTokenFactory:

class JsonAuthTokenFactory implements AuthTokenFactory {
  private String vehicleServiceToken;  // 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(vehicleId);
    }
    if (ServiceType.VEHICLE.equals(authTokenContext.getServiceType)) {
      return vehicleServiceToken;
    } else {
      throw new RuntimeException("Unsupported ServiceType: " + authTokenContext.getServiceType());
    }
  }

  private void fetchNewToken(String vehicleId) {
    String url = "https://yourauthserver.example/token/" + vehicleId;

    try (Reader r = new InputStreamReader(new URL(url).openStream())) {
      com.google.gson.JsonObject obj
          = com.google.gson.JsonParser.parseReader(r).getAsJsonObject();
      vehicleServiceToken = obj.get("VehicleServiceToken").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);
    }
  }
}

ההטמעה הספציפית הזו משתמשת בלקוח ה-HTTP המובנה ב-Java כדי לאחזר אסימון בפורמט JSON משרת האימות של המפתח. האסימון נשמר לשימוש חוזר. האסימון מאוחזר מחדש אם האסימון הישן נמצא תוך 10 דקות ממועד התפוגה שלו.

יכול להיות שההטמעה תתבצע באופן שונה, למשל שימוש ב-thread ברקע כדי לרענן אסימונים.

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

דיווח סטטוס ושגיאות באמצעות StatusListener

מכיוון ש-Driver SDK מבצע פעולות ברקע, אפשר להשתמש ב-StatusListener כדי להפעיל התראות כשמתרחשים אירועים מסוימים, כמו שגיאות, אזהרות או הודעות ניפוי באגים. שגיאות עשויות להיות זמניות (כמו BACKEND_CONNECTIVITY_ERROR), או שעדכוני המיקום יופסקו באופן סופי (למשל VEHICLE_NOT_FOUND, מה שמעיד על שגיאה בהגדרות).

מספקים הטמעה אופציונלית של StatusListener, כמו בדוגמה הבאה:

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.
  }
}

הערות לגבי SSL/TLS

באופן פנימי, הטמעת ה-Driver SDK משתמשת ב-SSL/TLS כדי לתקשר באופן מאובטח עם שרת Fleet Engine. בגרסאות קודמות של Android (גרסאות API 23 ומטה) יכול להיות שיהיה צורך בתיקון SecurityProvider כדי לתקשר עם השרת. למידע נוסף על עבודה עם SSL ב-Android, ראו ספק אבטחה של GMS. המאמר גם מכיל דוגמאות קוד לתיקון ספק האבטחה.

הפעלת עדכוני המיקום

אחרי שיש לכם מכונה *VehicleReporter, הפעלת עדכוני המיקום מתבצעת ישירות:

DeliveryVehicleReporter reporter = ...;

reporter.enableLocationTracking();

אם אפשר, עדכוני המיקום נשלחים במרווחי זמן קבועים. כל עדכון מיקום מציין גם שהרכב מחובר לאינטרנט.

כברירת מחדל, מרווח הזמן לדיווח הוא 10 שניות. אפשר לשנות את מרווח הזמן בין הדיווח באמצעות reporter.setLocationReportingInterval(long, TimeUnit). מרווח הזמן המינימלי הנתמך לעדכון הוא 5 שניות. עדכונים תכופים יותר עלולים לגרום לעיכובים ולשגיאות בבקשות ובשגיאות.

השבתה של עדכוני המיקום

בסיום המשמרת של הנהג, אפשר להפסיק את עדכוני המיקום על ידי התקשרות אל DeliveryVehicleReporter.disableLocationTracking.

תרחישים לדוגמה של מודלים מהימנים

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

יצירת רכב

אתם יכולים ליצור כלי רכב מה-Driver SDK.

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

DeliveryDriverApi api = DeliveryDriverApi.getInstance();
DeliveryVehicleManager vehicleManager = api.getDeliveryVehicleManager();
try {
  DeliveryVehicle vehicle = vehicleManager.createVehicle().get();
  // Handle CreateVehicleRequest DeliveryVehicle response.
} catch (Exception e) {
  // Handle CreateVehicleRequest error.
}

יצירת משימה לאיסוף משלוח

אפשר ליצור משימת איסוף משלוח מ-Driver SDK.

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

static final String TASK_ID = "task-8241890"; // Avoid auto-incrementing IDs.

DeliveryDriverApi api = DeliveryDriverApi.getInstance();
DeliveryTaskManager taskManager = api.getDeliveryTaskManager();
CreateDeliveryTaskRequest request = CreateDeliveryTaskRequest.builder(TASK_ID)
   .setPlannedWaypoint(Waypoint.builder().setLatLng(-6.195139, 106.820826).build())
   .setTaskDurationSeconds(2 * 60)
   .setParentId("my-tracking-id")
   .setTaskType(TaskType.DELIVERY_PICKUP)
   .build();

try {
   DeliveryTask task = taskManager.createTask(request).get();
   // Handle CreateTaskRequest DeliveryTask response.
} catch (Exception e)  {
   // Handle CreateTaskRequest error.
}

יצירת משימה של מסירת משלוח

אפשר ליצור משימת משלוח מה-Driver SDK.

לפני שיוצרים משימה, צריך לוודא שהפעלתם את Delivery Driver API. לאחר מכן יוצרים את משימת המשלוח של המשלוח כמו בדוגמה הבאה. למידע נוסף על מזהי משימות, ראו דוגמאות למזהי משימות.

static final String TASK_ID = "task-8241890"; // Avoid auto-incrementing IDs.

DeliveryDriverApi api = DeliveryDriverApi.getInstance();
DeliveryTaskManager taskManager = api.getDeliveryTaskManager();
CreateDeliveryTaskRequest request = CreateDeliveryTaskRequest.builder(TASK_ID)
   .setPlannedWaypoint(Waypoint.builder().setLatLng(-6.195139, 106.820826).build())
   .setTaskDurationSeconds(2 * 60)
   .setParentId("my-tracking-id")
   .setTaskType(TaskType.DELIVERY_DELIVERY)
   .build();
try {
   DeliveryTask task = taskManager.createTask(request).get();
   // Handle CreateTaskRequest DeliveryTask response.
} catch (Exception e)  {
   // Handle CreateTaskRequest error.
}

חוסר זמינות מתוזמן

אתם יכולים ליצור ב-Driver SDK משימה שמציינת אי זמינות (לדוגמה, כשיש תקלות לנהגים או לתדלוק). משימת אי-זמינות מתוזמנת לא יכולה לכלול מזהה לצורכי מעקב. אפשר גם לציין מיקום.

לפני שיוצרים משימה, צריך לוודא שהפעלתם את Delivery Driver API. לאחר מכן יוצרים את המשימה 'חוסר זמינות' כפי שמוצג בדוגמה הבאה. למידע נוסף על מזהי משימות, ראו דוגמאות למזהי משימות.

static final String TASK_ID = "task-8241890"; // Avoid auto-incrementing IDs.

DeliveryDriverApi api = DeliveryDriverApi.getInstance();
DeliveryTaskManager taskManager = api.getDeliveryTaskManager();
CreateDeliveryTaskRequest request = CreateDeliveryTaskRequest.builder(TASK_ID)
   .setTaskDurationSeconds(2 * 60) // Duration or location (or both) must be provided for a BREAK task.
   .setTaskType(TaskType.UNAVAILABLE)
   .build();
try {
   DeliveryTask task = taskManager.createTask(request).get();
   // Handle CreateTaskRequest DeliveryTask response.
} catch (Exception e)  {
   // Handle CreateTaskRequest error.
}

תחנות מתוכננות

אפשר ליצור משימה של עצירה מתוזמנת ב-Driver SDK. יכול להיות שמשימה מתוזמנת מתוזמנת לא כוללת מזהה לצורכי מעקב.

לפני שיוצרים משימה, צריך לוודא שהפעלתם את Delivery Driver API. לאחר מכן יוצרים את המשימה של עצירה מתוזמנת כמו בדוגמה הבאה. למידע נוסף על מזהי משימות, ראו דוגמאות למזהי משימות.

    static final String TASK_ID = "task-8241890"; //  Avoid auto-incrementing IDs.

    DeliveryDriverApi api = DeliveryDriverApi.getInstance();
    DeliveryTaskManager taskManager = api.getDeliveryTaskManager();
    CreateDeliveryTaskRequest request = CreateDeliveryTaskRequest.builder(TASK_ID)
       .setPlannedWaypoint(Waypoint.builder().setLatLng(-6.195139, 106.820826).build())
       .setTaskDurationSeconds(2 * 60)
       .setTaskType(TaskType.DELIVERY_SCHEDULED_STOP)
       .build();
    try {
       DeliveryTask task = taskManager.createTask(request).get();
       // Handle CreateTaskRequest DeliveryTask response.
    } catch (Exception e)  {
       // Handle CreateTaskRequest error.
    }

עדכון סדר המשימות

אתם יכולים לעדכן ב-Driver SDK את סדר הביצוע של המשימות שהוקצו לרכב.

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

אתם יכולים לעדכן את סדר המשימות מתי שתרצו.

לפני שמעדכנים את סדר המשימות ברכב, צריך לוודא שהרכב והמשימות כבר נוצרו ב-Fleet Engine. אחר כך מעדכנים את סדר המשימות ברכב, כמו בדוגמה הבאה.

    DeliveryDriverApi api = DeliveryDriverApi.getInstance();
    DeliveryVehicleReporter reporter = api.getDeliveryVehicleReporter();
    try {
       List<VehicleStop> stops = reporter.setVehicleStops(
         ImmutableList.of(
             VehicleStop.builder()
                 .setVehicleStopState(VehicleStopState.ARRIVED)
                 .setWaypoint(Waypoint.builder().setLatLng(37.1749, 122.412).build())
                 .setTasks(ImmutableList.of(task1)) // Previously created DeliveryTask in Fleet Engine.
                 .build(),
             VehicleStop.builder()
                 .setVehicleStopState(VehicleStopState.NEW) // The current vehicle stop.
                 .setWaypoint(Waypoint.builder().setLatLng(37.7749, 122.4194).build())
                 .setTasks(ImmutableList.of(task2)) // Previously created DeliveryTask in Fleet Engine.
                 .build(),
             VehicleStop.builder()
                 .setVehicleStopState(VehicleStopState.NEW)
                 .setWaypoint(Waypoint.builder().setLatLng(37.3382, 121.8863).build())
                 .setTasks(ImmutableList.of(task3, task4)) // Previously created DeliveryTasks in Fleet Engine.
                 .build())).get();
       // Successfully updated vehicle stops in Fleet Engine. Returns the successfully set VehicleStops.
    } catch (Exception e)  {
       // Failed to update vehicle stops in Fleet Engine. Setting VehicleStops must be attempted again after resolving
       // errors.
    }

יכול להיות שתתרחש חריגה שעלולה למנוע עדכון המצב הפנימי של ה-Driver SDK. במקרה כזה, צריך לפתור את הבעיה ולהתקשר שוב אל setVehicleStops עד שהשיחה תתבצע בהצלחה.

הבעיות האפשריות עשויות לכלול:

  • עצירות הביניים שצוינו לא תואמות לקו ביטול נעילה תקין. רק העצירה הראשונה של כלי הרכב יכולה להיות בכל אחד מהמצבים הבאים: NEW, ENROUTE או ARRIVED. עצירות ביניים אחרי העצירה הנוכחית חייבות להיות במצב NEW VehicleStopState.

  • המשימות לא קיימות או שהן שייכות לרכב אחר.

  • הרכב לא קיים.

הרכב בדרך לתחנה הבאה

חובה לקבל התראה מ-Fleet Engine כשרכב יוצא מעצירה וכשהוא מתחיל בניווט. אפשר להודיע ל-Fleet Engine מה-Driver SDK.

לפני שמעבירים הודעה ל-Fleet Engine שרכב יצא מעצירה, צריך לוודא שהרכב הוגדר ונוצר. לאחר מכן יש להודיע ל-Fleet Engine לגבי המראת הרכב, כפי שמוצג בדוגמה הבאה.

    DeliveryDriverApi api = DeliveryDriverApi.getInstance();
    DeliveryVehicleReporter reporter = api.getDeliveryVehicleReporter();
    reporter.enableLocationTracking(); // Location tracking must be enabled.

    // Create Vehicle, VehicleStops, and DeliveryTasks.
    // Set VehicleStops on Vehicle.

    navigator.setDestination(vehicleStop.getWaypoint());
    try {
       List<VehicleStop> updatedStops = reporter.enrouteToNextStop().get();
       // Successfully updated vehicle stops in Fleet Engine. Returns the set VehicleStops, with the first
       // VehicleStop updated to ENROUTE state.
    } catch (Exception e)  {
       // Failed to update vehicle stops in Fleet Engine. Updating VehicleStops must be attempted again
       // after resolving errors.
    }

יכול להיות שתתרחש חריגה שעלולה למנוע עדכון המצב הפנימי של ה-Driver SDK. במקרה כזה, צריך לפתור את הבעיה ואז להתקשר שוב אל enrouteToNextStop, עד שהבעיה תיפתר.

הבעיות האפשריות עשויות לכלול:

  • לא הוגדר עוד VehicleStops ב-Driver SDK.

רכב מגיע בעצירה

יש ליידע את ה-Fleet Engine כשרכב מגיע לעצירה. אפשר להודיע ל-Fleet Engine מ-Driver SDK.

לפני שמעדכנים את Fleet Engine שרכב מסוים הגיע לעצירה, צריך לוודא שהתחנות שלו מוגדרות. לאחר מכן יש להודיע ל-Fleet Engine לגבי הגעת הרכב בעצירה, כמו בדוגמה הבאה.

DeliveryDriverApi api = DeliveryDriverApi.getInstance();
DeliveryVehicleReporter reporter = api.getDeliveryVehicleReporter();
reporter.enableLocationTracking(); // Location tracking must be enabled.

// Create Vehicle, VehicleStops, and DeliveryTasks.
// Set VehicleStops on Vehicle.
// Mark ENROUTE to VehicleStop and start guidance using Navigator.

try {
   List<VehicleStop> updatedStopsArrived = reporter.arrivedAtStop().get();
   // Successfully updated vehicle stops in Fleet Engine. Returns the set VehicleStops, with the first
   // VehicleStop updated to ARRIVED state.
   navigator.clearDestinations();
} catch (Exception e)  {
   // Failed to update vehicle stops in Fleet Engine. Updating VehicleStops must be attempted again
   // after resolving errors.
}

ייתכן חריגה שעלולה למנוע עדכון המצב הפנימי של Driver SDK. במקרה כזה, צריך לפתור את הבעיה ואז להתקשר שוב אל arrivedAtStop עד שזה יצליח.

הבעיות האפשריות עשויות לכלול:

  • לא הוגדר עוד VehicleStops ב-Driver SDK.

הרכב עומד בעצירה

חובה להודיע ל-Fleet Engine כשרכב משלים עצירה. בעקבות ההתראה, כל המשימות שמשויכות לעצירה מוגדרות למצב 'סגור'. אפשר להודיע ל-Fleet Engine מ-Driver SDK.

מיידעים את ה-Fleet Engine שהרכב השלים את פעולתו ב-vehicleStop, כמו בדוגמה הבאה.

    DeliveryDriverApi api = DeliveryDriverApi.getInstance();
    DeliveryVehicleReporter reporter = api.getDeliveryVehicleReporter();
    reporter.enableLocationTracking(); // Location tracking must be enabled.

    // After completing the tasks at the VehicleStop, remove it from the
    // the current list of VehicleStops.

    try {
       List<VehicleStop> updatedStopsCompleted = reporter.completedStop().get();
       // Successfully updated vehicle stops in Fleet Engine. All tasks on the completed stop are set to CLOSED.
       // Returns the set VehicleStops, with the completed VehicleStop removed from the remaining list.
    } catch (Exception e)  {
       // Failed to update vehicle stops in Fleet Engine. Updating VehicleStops must be attempted again
       // after resolving errors.
    }

ייתכן חריגה שעלולה למנוע עדכון המצב הפנימי של Driver SDK. במקרה כזה, צריך לפתור את הבעיה ואז להתקשר שוב אל completedStop עד שזה יצליח.

הבעיות האפשריות עשויות לכלול:

  • לא הוגדר עוד VehicleStops ב-Driver SDK.

סגירת משימה

כדי לסגור משימה שהוקצתה לרכב, צריך להודיע ל-Fleet Engine כי הרכב השלים את העצירה שבה המשימה מתבצעת, או להסיר אותה מרשימת העצירות. לשם כך, אפשר להגדיר את רשימת התחנות הנותרות של הרכב, בדיוק כמו שמעדכנים את סדר המשימות של רכב מסוים.

אם למשימה עדיין לא הוקצה רכב וצריך לסגור אותה, צריך לעדכן את המשימה למצב 'סגור'. עם זאת, אי אפשר לפתוח מחדש משימה שסגרה.

סגירת משימה לא מצביעה על הצלחה או כישלון. היא מציינת שהמשימה כבר לא מתבצעת. לצורך מעקב אחרי המשלוח, חשוב לציין את התוצאה בפועל של המשימה, כדי שתהיה אפשרות להציג את תוצאת המסירה.

כדי שאפשר יהיה להשתמש ב-Driver SDK ולסגור את המשימה, צריך להקצות משימה לרכב מסוים. כדי לסגור משימה שהוקצתה לרכב, צריך להודיע ל-Fleet Engine כי הרכב השלים את העצירה שבה המשימה מתבצעת.

לחלופין, אפשר לעדכן את סדר המשימות של הרכב שהמשימה הוקצתה לו ולהסיר את המשימה מרשימת העצירות.

מגדירים את תוצאת המשימה ואת המיקום שלה

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

במשימות שנמצאות במצב CLOSED, אפשר להגדיר את התוצאה שלהן כ-{2} מציגה לסירוגין או כ-נכשל. Fleet Engine מחויב רק במשימות מסירה עם מצב חולפות.

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

בדוגמה הבאה תוכלו לראות איך להשתמש ב-Driver SDK כדי להגדיר תוצאת משימה וחותמת זמן. אי אפשר להגדיר את מיקום תוצאת המשימה באמצעות Driver SDK.

    static final String TASK_ID = "task-8241890";

    DeliveryDriverApi api = DeliveryDriverApi.getInstance();
    DeliveryTaskManager taskManager = api.getDeliveryTaskManager();

    // Updating an existing DeliveryTask which is already CLOSED. Manually
    // setting TaskOutcomeLocation with Driver SDK is not supported at this time.
    UpdateDeliveryTaskRequest req = UpdateDeliveryTaskRequest.builder(TASK_ID)
        .setTaskOutcome(TaskOutcome.SUCCEEDED)
        .setTaskOutcomeTimestamp(now()) // Timestamp in milliseconds.
        .build();

    try {
       DeliveryTask updatedTask = taskManager.updateTask(req);
       // Handle UpdateTaskRequest DeliveryTask response.
    } catch (Exception e)  {
       // Handle UpdateTaskRequest error.
    }

חיפוש כלי רכב

אתם יכולים לחפש רכב ב-Driver SDK. לפני שאתם מחפשים רכב, ודאו שאתם מאתחלים את ממשק ה-API של Delivery Driver. לאחר מכן אתם יכולים לחפש את הרכב כמו בדוגמה הבאה.

    DeliveryDriverApi api = DeliveryDriverApi.getInstance();
    DeliveryVehicleManager vehicleManager = api.getDeliveryVehicleManager();
    try {
       DeliveryVehicle vehicle = vehicleManager.getVehicle().get();
       // Handle GetVehicleRequest DeliveryVehicle response.
    } catch (Exception e)  {
       // Handle GetVehicleRequest error.
    }

DeliveryVehicleManager יכול לחפש ב-DeliveryVehicle רק את מזהה הרכב שסופק במהלך אתחול ה-API של מנהל העברות.