بدء استخدام SDK Driver لنظام التشغيل Android

الحد الأدنى من متطلبات النظام

يجب أن يعمل الجهاز الجوّال بالإصدار 6.0 من نظام التشغيل Android (المستوى 23 من واجهة برمجة التطبيقات) أو إصدار أحدث.

إعداد Maven

تتوفّر الإصدار 4.99 والإصدارات الأحدث من حزمة تطوير البرامج (SDK) لخدمة Drive في مستودع 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، يجب تثبيت خدمات Google Play على جهاز Android.

إعداد مشروع التطوير

لإعداد مشروع التطوير والحصول على مفتاح واجهة برمجة تطبيقات للمشروع على Google Cloud Console:

  1. أنشِئ مشروعًا جديدًا على Google Cloud Console أو اختَر مشروعًا حاليًا لاستخدامه مع حزمة Driver SDK. انتظر بضع دقائق حتى يصبح المشروع الجديد مرئيًا على Google Cloud Console.

  2. لتشغيل التطبيق التجريبي، يجب أن يتمكن مشروعك من الوصول إلى حزمة تطوير البرامج بالاستناد إلى بيانات "خرائط Google" لنظام التشغيل Android. في Google Cloud Console، اختَر واجهات برمجة التطبيقات والخدمات > المكتبة، ثم ابحث عن حزمة تطوير البرامج بالاستناد إلى بيانات "خرائط Google" وفعِّلها لنظام التشغيل Android.

  3. احصل على مفتاح واجهة برمجة تطبيقات للمشروع عن طريق اختيار واجهات برمجة التطبيقات والخدمات > بيانات الاعتماد > إنشاء بيانات اعتماد > مفتاح واجهة برمجة التطبيقات. لمزيد من المعلومات حول الحصول على مفتاح واجهة برمجة التطبيقات، يمكنك الاطّلاع على الحصول على مفتاح واجهة برمجة التطبيقات.

إضافة حزمة تطوير البرامج (SDK) للسائق إلى تطبيقك

تتوفّر حزمة Driver SDK في مستودع Google Maven. يتضمن المستودع ملفات نموذج كائن المشروع (pom) لحزمة SDK وJavadocs. لإضافة Driver SDK إلى تطبيقك:

  1. أضِف التبعية التالية إلى إعداد Gradle أو Maven، واستبدِل العنصر النائب VERSION_NUMBER بالإصدار المحدَّد من حزمة تطوير البرامج (SDK) لخدمة Driver.

    Gradle

    أضِف ما يلي إلى build.gradle:

    dependencies {
      ...
      implementation 'com.google.android.libraries.mapsplatform.transportation:transportation-driver:[VERSION_NUMBER]'
    }
    

    Maven

    أضِف ما يلي إلى pom.xml:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.mapsplatform.transportation.driver</groupId>
        <artifactId>transportation-driver</artifactId>
        <version>[VERSION_NUMBER]</version>
      </dependency>
    </dependencies>
    

إضافة مفتاح واجهة برمجة التطبيقات إلى تطبيقك

بعد إضافة حزمة Driver SDK إلى تطبيقك، أضِف مفتاح واجهة برمجة التطبيقات إلى تطبيقك. وعليك استخدام مفتاح واجهة برمجة التطبيقات للمشروع الذي حصلت عليه عند إعداد مشروع التطوير.

يوضّح هذا القسم كيفية تخزين مفتاح واجهة برمجة التطبيقات كي يتمكّن تطبيقك من الرجوع إليه بأمان. ويجب عدم التحقّق من مفتاح واجهة برمجة التطبيقات في نظام التحكّم في الإصدارات. يجب تخزينها في ملف local.properties الموجود في الدليل الجذري لمشروعك. لمزيد من المعلومات حول ملف local.properties، راجِع ملفات خصائص Gradle.

ولتبسيط هذه المهمّة، يمكنك استخدام Secrets Gradle Plugin for Android. اتّبِع هذا الإجراء لتثبيت المكوّن الإضافي Secret Gradle وتخزين مفتاح واجهة برمجة التطبيقات بأمان.

  1. افتح ملف build.gradle على مستوى الجذر وأضِف الرمز التالي إلى العنصر 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 بمفتاح واجهة برمجة التطبيقات.

    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 في تطبيقك، عليك تضمين نص تحديد المصدر وتراخيص البرامج المفتوحة المصدر كجزء من قسم الإشعارات القانونية في تطبيقك. من الأفضل تضمين معلومات المساهمة كعنصر مستقل في القائمة أو كجزء من عنصر في القائمة لمحة.

يمكن العثور على معلومات التراخيص في ملف "rd_party_الترخيصs.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 لتحسين إصداراتك، قد تحتاج إلى إضافة الأسطر التالية إلى ملف إعداد ProGuard:

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

الحد الأدنى لمستوى واجهة برمجة التطبيقات المسموح به هو 23.

إعداد حزمة تطوير البرامج (SDK)

يجب إدخال رقم تعريف موفّر الخدمة (عادةً رقم تعريف مشروع Google Cloud) لإعداد الكائن DriverContext. لمزيد من التفاصيل حول إعداد مشروع Google Cloud، يُرجى الاطّلاع على المصادقة والتفويض.

قبل استخدام Driver SDK، يجب عليك أولاً تهيئة حزمة 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 من عنصر واجهة برمجة التطبيقات. (يمتد نطاق DeliveryVehicleReporter إلى NavigationVehicleReporter.)

    DeliveryVehicleReporter vehicleReporter = driverApi.getDeliveryVehicleReporter();
    

جارٍ المصادقة مع "AuthTokenFactory"

عندما تُنشئ Driver SDK تحديثات للموقع الجغرافي، يجب أن ترسل هذه التحديثات إلى خادم Fleet Engine. لمصادقة هذه الطلبات، تستدعي حزمة تطوير البرامج (SDK) للقيادة نسخة AuthTokenFactory التي يوفّرها المتصل. فإن المصنع مسؤول عن إنشاء رموز المصادقة في وقت تحديث الموقع.

تختلف الطريقة التي يتم من خلالها إنشاء الرموز المميّزة تحديدًا حالة كل مطوّر. ومع ذلك، قد يحتاج التنفيذ إلى:

  • جلب رمز مميز للمصادقة، ربما بتنسيق JSON، من خادم HTTPS
  • تحليل الرمز المميّز وتخزينه مؤقتًا
  • إعادة تحميل الرمز المميّز عند انتهاء صلاحيته

لمعرفة تفاصيل الرموز المميّزة التي يتوقعها خادم Fleet Engine، يُرجى الاطّلاع على المقالة إنشاء رمز JSON المميّز للويب (JWT) للتفويض.

في ما يلي تنفيذ لهيكل 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);
    }
  }
}

يستخدم هذا التنفيذ بالتحديد عميل Java HTTP المضمّن لاسترجاع رمز مميّز بتنسيق JSON من خادم المصادقة لدى المطوّر. يتم حفظ الرمز الخاص لإعادة استخدامه. وتتم إعادة جلب الرمز المميّز إذا كان خلال 10 دقائق من وقت انتهاء صلاحيته.

قد تنفِّذ عملية التنفيذ إجراءات مختلفة، مثل استخدام سلسلة محادثات في الخلفية لإعادة تحميل الرموز المميّزة.

يتم التعامل مع الاستثناءات في AuthTokenFactory على أنّها مؤقتة ما لم تحدث بشكل متكرر. بعد عدد من المحاولات، تفترض حزمة Driver 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.
  }
}

ملاحظات حول طبقة المقابس الآمنة/بروتوكول أمان طبقة النقل (TLS)

داخليًا، يستخدم تطبيق Driver SDK طبقة المقابس الآمنة/بروتوكول أمان طبقة النقل (TLS) للاتصال بشكل آمن بخادم Fleet Engine. قد تتطلّب الإصدارات السابقة من Android (الإصدار 23 من واجهة برمجة التطبيقات أو الإصدارات الأقدم) رمز تصحيح SecurityProvider للاتصال بالخادم. لمزيد من المعلومات حول استخدام طبقة المقابس الآمنة (SSL) في Android، راجِع مقدّم خدمة GMS للأمان. تحتوي المقالة أيضًا على عيّنات تعليمات برمجية لتصحيح مزوّد الأمان.

تفعيل تحديثات الموقع الجغرافي

بعد توفّر مثيل *VehicleReporter، يصبح تفعيل تعديلات الموقع الجغرافي مباشرةً:

DeliveryVehicleReporter reporter = ...;

reporter.enableLocationTracking();

يتم إرسال تحديثات الموقع الجغرافي على فترات منتظمة، إن أمكن. يشير كل تحديث للموقع أيضًا إلى أن المركبة متصلة بالإنترنت.

يبلغ الفاصل الزمني لإعداد التقارير 10 ثوانٍ تلقائيًا. يمكنك تغيير الفاصل الزمني لإعداد التقارير باستخدام reporter.setLocationReportingInterval(long, TimeUnit) الحد الأدنى للفاصل الزمني للتحديث المتوافق هو 5 ثوانٍ. وقد تؤدي التحديثات الأكثر تكرارًا إلى بطء الطلبات والأخطاء.

إيقاف تحديثات الموقع الجغرافي

عند انتهاء عملية تبديل موقع السائق، يمكنك إيقاف تعديلات الموقع الجغرافي من خلال الاتصال على الرقم DeliveryVehicleReporter.disableLocationTracking.

حالات استخدام النموذج الموثوق به

يوضِّح هذا القسم كيفية استخدام حزمة Driver SDK لتنفيذ حالات الاستخدام الشائعة عند استخدام النموذج الموثوق به.

إنشاء مركبة

يمكنك إنشاء مركبة من خلال حزمة تطوير البرامج (SDK) للسائق.

قبل إنشاء مركبة، احرص على إعداد Delivery Driver API. يجب إنشاء رقم تعريف المركبة باستخدام رقم تعريف المركبة ورقم تعريف مقدّم الخدمة اللذان تم استخدامهما أثناء إعداد "حزمة تطوير البرامج (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.
}

المحطات المجدوَلة

يمكنك إنشاء مهمة مُجدوَلة للإيقاف سواء من خلال حزمة تطوير البرامج (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 مرة أخرى إلى أن تتم المكالمة بنجاح.

وتشمل المشاكل المحتملة ما يلي:

  • لا تتبع "مجموعات توقُّف المركبات" المحدّدة نمطًا صالحًا. يمكن إدخال حالة VehicleStop الأولى فقط في أي من حالات AutomotiveStopStates: "جديد" أو "ENROUTE" أو "تم الوصول". يجب أن تكون "محطات توقف المركبة" بعد المحطة الحالية ضمن فئة "CarStopState" الجديدة.

  • المهام إما غير موجودة أو تنتمي إلى مركبة مختلفة.

  • المركبة غير موجودة.

المركبة في طريقها إلى المحطة التالية

يجب إرسال إشعار إلى 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 متبقّية في حزمة تطوير البرامج (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 متبقّية في حزمة تطوير البرامج (SDK) للسائق.

مركبة تكمل محطة توقّف

يجب عليك إعلام Fleet Engine عندما تكمل إحدى المركبات توقّفها. يؤدي هذا الإشعار إلى تعيين جميع المهام المرتبطة بالتوقف على حالة إغلاق. يمكنك إرسال إشعار إلى Fleet Engine من حزمة Driver SDK.

أبلِغ محرّك Fleet Engine بأنّ المركبة قد استكملت نظام AutomotiveStop كما هو موضَّح في المثال التالي.

    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 متبقّية في حزمة تطوير البرامج (SDK) للسائق.

إغلاق مهمة

لإغلاق مهمة تم تعيينها لمركبة، يمكنك إما إعلام Fleet Engine بأن المركبة قد اكتملت في المكان الذي تحدث فيه المهمة، أو إزالته من قائمة محطات التوقف للمركبة. لإجراء ذلك، يمكنك ضبط قائمة بمحطات التوقّف المتبقية في المركبة كما هو الحال عند تعديل ترتيب المهام الخاص بالمركبة.

إذا لم يتم تعيين مركبة لمهمة بعد، وتحتاج إلى إغلاقها، فقم بتحديث المهمة إلى حالة "مغلقة". ومع ذلك، لا يمكنك إعادة فتح مهمة مغلقة.

لا يشير إغلاق المهمة إلى النجاح أو الفشل. ويشير إلى أن المهمة لم تعد تُعد قيد التنفيذ. بالنسبة لتتبع الشحن، من المهم الإشارة إلى النتيجة الفعلية للمهمة حتى يمكن عرض نتيجة التسليم.

يجب تعيين مهمة للمركبة لتتمكن من استخدام Driver SDK لإغلاق المهمة. لإغلاق مهمة تم تعيينها إلى مركبة، أبلغ Fleet Engine بأن المركبة قد أكملت التوقف في المكان الذي تحدث فيه المهمة.

بدلاً من ذلك، يمكنك تحديث ترتيب المهام للمركبة التي تم إسناد المهمة إليها، ثم إزالة المهمة من قائمة محطات التوقف.

حدد نتيجة المهمة وموقع النتيجة

لا يشير إغلاق المهمة إلى النجاح أو الفشل. ويشير إلى أن المهمة لم تعد تُعد قيد التنفيذ. بالنسبة لتتبع الشحن، من المهم الإشارة إلى النتيجة الفعلية للمهمة حتى يمكن عرض نتيجة التسليم، ومن ثم يكون هناك فوترة مناسبة للخدمات. بمجرد التعيين، لا يمكنك تغيير نتيجة المهمة. ولكن يمكنك تعديل وقت نتيجة المهمة وموقع نتيجة المهمة بعد تعيينهما.

يمكن ضبط نتيجتها للمهام التي تكون في الحالة "مغلقة" على SUCCEEDED أو "تعذّر". لا تفرض Fleet Engine رسومًا إلا على مهام التسليم التي تكون بالحالة SUCCEEDED.

عند وضع علامة على نتيجة مهمة، يملأ Fleet Engine تلقائيًا موقع ناتج المهمة بآخر موقع معروف للمركبة. يمكنك إلغاء هذا السلوك.

يوضِّح لك المثال التالي كيفية استخدام Driver SDK لتحديد نتيجة المهمة والطابع الزمني. لا يمكنك تحديد موقع نتيجة المهمة باستخدام حزمة تطوير البرامج (SDK) لخدمة Drive.

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

البحث عن مركبة

يمكنك البحث عن مركبة من خلال حزمة تطوير البرامج (SDK) الخاصة بالسائق. قبل البحث عن مركبة، احرص على إعداد Delivery Driver API. ويمكنك بعد ذلك البحث عن المركبة كما هو موضح في المثال التالي.

    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 عن رقم تعريف المركبة الذي تم توفيره أثناء إعداد Delivery Driver API.