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

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

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

تكوين الإصدار والتبعيات

يتوفّر الإصدار 4.99 والإصدارات الأحدث من حزمة تطوير البرامج (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، يجب أن يستهدف تطبيقك الإصدار 23 من minSdkVersion أو الإصدارات الأحدث. لمزيد من المعلومات، يُرجى الاطّلاع على ملاحظات الإصدار.

لتشغيل تطبيق تم إنشاؤه باستخدام Driver SDK، يجب تثبيت خدمات Google Play على جهاز Android.

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

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

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

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

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

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

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

  1. أضِف التبعية التالية إلى إعدادات Gradle أو Maven، واستبدِل العنصر النائب 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</groupId>
        <artifactId>transportation-driver</artifactId>
        <version>VERSION_NUMBER</version>
      </dependency>
    </dependencies>
    
  2. تعتمد حزمة تطوير البرامج (SDK) لبرنامج التشغيل على حزمة تطوير البرامج (SDK) للتنقّل، ويتم ضبط هذه التبعية بطريقة تتيح للمشروع إمكانية تنزيل أحدث إصدار دائمًا من حزمة التنقّل في الإصدار الرئيسي، في حال الحاجة إلى إصدار معيّن من حزمة SDK للتنقّل، وذلك بشكل صريح في ملف إعداد الإصدار كالتالي. تجدر الإشارة إلى أنّ السلوكيات المُجمّعة لأحدث إصدارات Driver SDK وحزمة تطوير البرامج (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>
    

تعديل بيان التطبيق

بعد إضافة حزمة Driver SDK إلى تطبيقك، يمكنك تعديل ملف البيان لتطبيقك من خلال تعديل ملف AndroidManifest.xml.

أضِف مفتاح واجهة برمجة التطبيقات داخل العنصر <application>. يجب استخدام مفتاح واجهة برمجة تطبيقات المشروع الذي حصلت عليه عند إعداد مشروع التطوير.

على سبيل المثال، استبدِل PASTE_YOUR_API_KEY_HERE بمفتاح واجهة برمجة التطبيقات في البيانات الوصفية للتطبيقات التالية:

<meta-data
    android:name="com.google.android.geo.API_KEY"
    android:value="PASTE_YOUR_API_KEY_HERE"/>

يعرض المثال التالي بيانًا كاملاً لنموذج تطبيق:

<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="PASTE_YOUR_API_KEY_HERE"/>

        <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 حول كيفية تضمين إشعارات البرامج المفتوحة المصدر.

التبعيات

تستخدم حزمة 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) لإعداد عنصر FleetEngine. لمزيد من التفاصيل حول إعداد مشروع Google Cloud، يُرجى الاطّلاع على المصادقة والتفويض.

قبل استخدام حزمة تطوير البرامج (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

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

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

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

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

في ما يلي تنفيذ هيكلي لـ AuthToken جدًا:

class JsonAuthTokenFactory implements AuthTokenFactory {
  String vehicleServiceToken;  // initially null
  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 URL(url).openStream()) {
      com.google.gson.JsonObject obj
          = new com.google.gson.JsonParser().parse(r);
      vehicleServiceToken = obj.get("VehicleServiceToken").getAsString();
      expiryTimeMs = obj.getAsLong("TokenExpiryMs");

      // 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 FleetEngine class will be notified and pass along the failed
      // update warning.
      throw new RuntimeException("Could not get auth token", e);
    }
  }
}

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

قد تختلف طريقة التنفيذ بالنسبة إليك، مثل استخدام سلسلة محادثات في الخلفية لإعادة تحميل الرموز المميّزة.

يتم التعامل مع الاستثناءات في AuthTokenFactory كاستثناءات مؤقتة ما لم تحدث بشكل متكرر. بعد إجراء عدد من المحاولات، تفترض حزمة Driver SDK أن الخطأ دائم وتتوقف عن محاولة إرسال التحديثات.

الإبلاغ عن الحالة والأخطاء في "StatusListener"

بما أنّ "حزمة تطوير البرامج (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 داخليًا طبقة المقابس الآمنة (SSL)/بروتوكول أمان طبقة النقل (TLS) للاتصال الآمن بخادم Fleet Engine. قد تتطلّب الإصدارات السابقة من Android (الإصدار 23 من واجهة برمجة التطبيقات أو الإصدارات الأقدم) رمز تصحيح SecurityProvider للاتصال بالخادم. لمزيد من المعلومات حول العمل باستخدام طبقة المقابس الآمنة (SSL) في Android، يُرجى الاطّلاع على تحديث موفِّر الأمان للحماية من استغلال طبقة المقابس الآمنة (SSL). تحتوي المقالة أيضًا على عيّنات تعليمات برمجية لتصحيح إعدادات موفِّر الأمان.

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

بعد الحصول على مثيل *VehicleReporter، ستكون عملية تفعيل تعديلات الموقع الجغرافي واضحة:

DeliveryVehicleReporter reporter = ...;

reporter.enableLocationTracking();

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

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

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

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

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

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

إنشاء مركبة

يمكنك إنشاء مركبة من حزمة Driver 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.
}

إنشاء مهمة استلام الشحنة

يمكنك إنشاء مهمة استلام الشحنة من "حزمة تطوير البرامج (SDK) لبرنامج التشغيل".

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

إنشاء مهمة تسليم شحنة

يمكنك إنشاء مهمة تسليم شحنة من "حزمة تطوير البرامج (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.
}

عدم التوفّر المجدوَل

يمكنك إنشاء مهمة من حزمة تطوير البرامج (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.
}

تعديل ترتيب المهام

يمكنك تعديل ترتيب تنفيذ المهام المخصّصة للمركبة من "حزمة تطوير البرامج (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.
}

قد يحدث استثناء قد يمنع إجراء تحديث للحالة الداخلية لحزمة تطوير البرامج (SDK) لبرنامج التشغيل. إذا حدث هذا، قم بحل المشكلة ثم الاتصال بـ setVehicleStops مرة أخرى حتى تتم المكالمة بنجاح.

يمكن أن تشمل المشاكل المحتملة ما يلي:

  • إنّ نقاط إيقاف السيارة المحدّدة لا تتّبع نمطًا صالحًا. يمكن أن تكون أول VehicleStop فقط في أي من حالة نقطة OnHub: NEW أو ENROUTE أو ARRIVED. يجب أن تكون "محطات إيقاف المركبات" بعد المحطة الحالية في "حالة إيقاف السيارة" الجديدة.

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

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

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

يجب إبلاغ فريق 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.
}

قد يحدث استثناء قد يمنع إجراء تحديث للحالة الداخلية لحزمة تطوير البرامج (SDK) لبرنامج التشغيل. وفي حال حدوث ذلك، يجب حل المشكلة ثم الاتصال بـ enrouteToNextStop مرة أخرى إلى أن تتم معالجة المشكلة.

يمكن أن تشمل المشاكل المحتملة ما يلي:

  • لم يتم ضبط VehicleStops متبقية في حزمة تطوير البرامج (SDK) لبرنامج التشغيل.

وصول مركبة إلى محطة

يجب إرسال إشعار إلى مجموعة المركبات عند وصول مركبة إلى محطة. يمكنك إبلاغ 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.
}

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

قد تشمل المشاكل المحتملة ما يلي:

  • لم يتم ضبط VehicleStops متبقية في حزمة تطوير البرامج (SDK) لبرنامج التشغيل.

تكمل مركبة محطة

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

أبلغ Fleet Engine بأنّ المركبة قد أكملت عملية إيقاف السيارة وفقًا لما هو موضّح في المثال التالي.

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

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

يمكن أن تشمل المشاكل المحتملة ما يلي:

  • لم يتم ضبط VehicleStops متبقية في حزمة تطوير البرامج (SDK) لبرنامج التشغيل.

إغلاق مهمة

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

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

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

يجب تعيين مهمة لمركبة حتى تتمكن من استخدام حزمة تطوير البرامج (SDK) الخاصة ببرنامج التشغيل لإغلاق المهمة. لإغلاق مهمة تم تعيينها لمركبة، قم بإعلام Fleet Engine بأن المركبة قد أكملت المحطة التي تتم فيها المهمة.

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

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

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

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

عند وضع علامة على نتيجة مهمة، يملأ Fleet Engine تلقائيًا موقع نتيجة المهمة بآخر موقع معروف للمركبة. يمكنك تجاوز هذا السلوك عن طريق استدعاء Fleet Engine. لاحظ أنه لا يمكنك تعيين موقع نتيجة المهمة باستخدام حزمة تطوير البرامج (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.
}

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

يمكنك البحث عن مركبة من خلال حزمة تطوير البرامج (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.