بدء استخدام حزمة تطوير البرامج (SDK) للمستهلكين لنظام التشغيل Android

يمكنك استخدام حزمة SDK للمستهلك لإنشاء وتشغيل تطبيق أساسي للمستهلك متكامل مع الخدمات الخلفية لحلول عمليات التسليم والتسليم عند الطلب. يمكنك إنشاء تطبيق "رحلة وتقديم الطلب" يمكنه عرض رحلة نشطة والاستجابة لتحديثات الرحلة ومعالجة أخطاء الرحلة.

نظرًا لاحتواء حزمة SDK للمستهلك على بنية نمطية، يمكنك استخدام أجزاء واجهة برمجة التطبيقات التي تريد استخدامها لتطبيقك المعيّن ودمجها مع واجهات برمجة التطبيقات الخاصة بك، والخدمات الخلفية التي يوفرها Fleet Engine، وإضافة واجهات برمجة التطبيقات من "منصة خرائط Google".

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

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

ضبط التبعيات والإنشاء

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

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

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

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

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

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

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

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

تتوفّر حزمة تطوير البرامج (SDK) للمستهلكين من خلال مستودع Maven الخاص. يتضمن المستودع ملفات نموذج كائن المشروع (pom) لحزمة SDK وJavadocs. لإضافة حزمة 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، مع استبدال العنصر النائب 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 للخرائط بشكلٍ صريح في ملف إعداد الإصدار كما يلي، وعندما يتم طرح إصدار جديد من حزمة تطوير البرامج (SDK) لـ "خرائط Google"، ستستمر حزمة SDK الخاصة بالمستهلك في استخدام الحدّ الأدنى المطلوب من إصدار حزمة SDK المتوفرة لـ "خرائط Google".

    Gradle

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

    dependencies {
      ...
      implementation 'com.google.android.gms:play-services-maps:18.1.0'
    }
    

    Maven

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

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.gms</groupId>
        <artifactId>play-services-maps</artifactId>
        <version>18.1.0</version>
      </dependency>
    </dependencies>
    

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

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

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

ولتبسيط هذه المهمة، يمكنك استخدام المكوّن الإضافي Secret Gradle الإضافي لنظام Android.

لتثبيت المكوّن الإضافي وتخزين مفتاح واجهة برمجة التطبيقات:

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

يمكن العثور على معلومات التراخيص في ملف "rd_party_الترخيصs.txt" في ملف AAR غير المؤرشف.

يُرجى الرجوع إلى https://developers.google.com/android/guides/opensource حول كيفية تضمين إشعارات البرامج المفتوحة المصدر.

مصادقة حزمة تطوير البرامج (SDK) للمستهلك

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

تستخدم حزمة SDK الخاصة بالمستهلك رمز JSON المميز للويب الذي يوفره التطبيق للاتصال بمحرك Fleet Engine. راجع مصادقة وتفويض محرك مجموعة المركبات للحصول على مزيد من المعلومات.

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

طلبات معاودة الاتصال بالرمز المميّز JSON للويب

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

ننصحك بشدة باستخدام الرموز المميّزة لتفويض التخزين المؤقت لتنفيذ معاودة الاتصال وإعادة تحميلها عند انقضاء فترة expiry فقط. يجب إصدار الرموز المميّزة بانتهاء صلاحية ساعة واحدة

إنّ رمز معاودة الاتصال بالرمز المميّز للمصادقة يحدد رمز الخدمة المطلوب لخدمة TripService. وتعرض أيضًا السمة tripId المطلوبة للسياق.

يوضح مثال الرمز البرمجي التالي كيفية تنفيذ معاودة الاتصال بالرمز المميز للتفويض.

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

تهيئة واجهة برمجة التطبيقات

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

الحصول على مثيل "ConsumerApi"

لاستخدام حزمة SDK للمستهلك، يجب إعداد تطبيقك ConsumerApi بشكل غير متزامن. واجهة برمجة التطبيقات هي نمط فردي. وتستغرق طريقة الإعداد AuthTokenFactory. يقوم المصنع بإنشاء رموز JWT جديدة للمستخدم عند الضرورة.

providerId هو رقم تعريف المشروع لمشروعك على Google Cloud. راجِع دليل مستخدم Fleet Engine للحصول على مزيد من المعلومات حول إنشاء المشروع.

يجب أن ينفِّذ تطبيقك AuthTokenFactory كما هو موضَّح في مصادقة حزمة تطوير البرامج (SDK) للمستهلكين.

Java

Task<ConsumerApi> consumerApiTask = ConsumerApi.initialize(
    this, "myProviderId", authTokenFactory);

consumerApiTask.addOnSuccessListener(
  consumerApi -> this.consumerApi = consumerApi);

Kotlin

val consumerApiTask =
  ConsumerApi.initialize(this, "myProviderId", authTokenFactory)

consumerApiTask?.addOnSuccessListener { consumerApi: ConsumerApi ->
  this@YourActivity.consumerApi = consumerApi
}

يجب إعداد حزمة تطوير البرامج بالاستناد إلى بيانات "خرائط Google" لطلب العارض المفضّل.

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

إضافة حزمة تطوير البرامج (SDK) في "خرائط Google" كتبعية

Gradle

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

dependencies {
  //...
  implementation "com.google.android.gms:play-services-maps:18.1.0"
}

Maven

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

 <dependencies>
   ...
   <dependency>
     <groupId>com.google.android.gms</groupId>
     <artifactId>play-services-maps</artifactId>
     <version>18.1.0</version>
   </dependency>
 </dependencies>

يجب إعداد حزمة تطوير البرامج بالاستناد إلى بيانات "خرائط Google" قبل إعداد حزمة تطوير البرامج (SDK) للمستهلك.

في فئة Application أو بدء التشغيل Activity، يمكنك الاتصال بـ MapsInitializer.initialize() وانتظار نتيجة طلب العارض قبل إعداد Consumer SDK.

java

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  initViews();

  MapsInitializer.initialize(getApplicationContext(), Renderer.LATEST,
      new OnMapsSdkInitializedCallback() {
        @Override
        public void onMapsSdkInitialized(Renderer renderer) {
          switch (renderer) {
            case LATEST:
              Log.i("maps_renderer", "LATEST renderer");
              break;
            case LEGACY:
              Log.i("maps_renderer", "LEGACY renderer");
              break;
          }

          initializeConsumerSdk();
        }
      });
}

Kotlin

fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  setContentView(R.layout.main)
  initViews()

  MapsInitializer.initialize(
    getApplicationContext(), Renderer.LATEST,
    object : OnMapsSdkInitializedCallback() {
      fun onMapsSdkInitialized(renderer: Renderer?) {
        when (renderer) {
          LATEST -> Log.i("maps_renderer", "LATEST renderer")
          LEGACY -> Log.i("maps_renderer", "LEGACY renderer")
        }
        initializeConsumerSdk()
      }
    })
  }

إنشاء واجهة المستخدم

يمكنك استخدام ConsumerMapFragment أو ConsumerMapView لإنشاء واجهة المستخدم لتطبيقك. تتيح لك علامة ConsumerMapFragment تحديد خريطتك باستخدام Fragment، بينما يتيح لك ConsumerMapView استخدام View. إنّ وظائف مشاركة الرحلات هي نفسها في كلّ من ConsumerMapView وConsumerMapFragment، لذا يمكنك اختيار وظيفة تستند إلى ما إذا كان تطبيقك أفضل من View أو Fragment.

توفير واجهة برمجة التطبيقات 19 (KitKat) وواجهة برمجة التطبيقات Vector القابلة للرسم

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

Java

// ...
import android.support.v7.app.AppCompatActivity;

// ...

public class ConsumerTestActivity extends AppCompatActivity {
  // ...
}

Kotlin

// ...
import android.support.v7.app.AppCompatActivity

// ...

class ConsumerTestActivity : AppCompatActivity() {
  // ...
}

إضافة جزء أو عرض الخريطة

أنت تنشئ الخريطة لعرض مشاركة الرحلة سواء في جزء من Android أو في عرض تحدّده في ملف XML لتنسيق التطبيق (المتوفّر في /res/layout). بعد ذلك، يوفّر الجزء (أو العرض) إمكانية الوصول إلى خريطة مشاركة الرحلة التي يمكن لتطبيقك الوصول إليها وتعديلها. توفر الخريطة أيضًا اسمًا معرِّفًا لـ ConsumerController، مما يسمح لتطبيقك بالتحكم في تجربة مشاركة الرحلة وتخصيصها.

مشاركة الرحلة ووحدة التحكّم

يمكنك تحديد خريطة مشاركة الرحلة إما كجزء (باستخدام ConsumerMapFragment) أو كعرض (باستخدام ConsumerMapView)، كما هو موضّح في مثال الرمز التالي. يجب أن تطلب طريقة onCreate() عند ذلك استدعاء getConsumerGoogleMapAsync(callback)، الذي يعرض ConsumerGoogleMap بشكل غير متزامن في معاودة الاتصال. بعد ذلك، يمكنك استخدام ConsumerGoogleMap لعرض مشاركة الرحلة ويمكن أن يعدّلها التطبيق حسب الحاجة.

ConsumerMapFragment

يمكنك تحديد الجزء في ملف XML لتخطيط التطبيق، كما هو موضّح في مثال الرمز التالي.

<fragment
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:name="com.google.android.libraries.mapsplatform.transportation.consumer.view.ConsumerMapFragment"
    android:id="@+id/consumer_map_fragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

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

Java

public class SampleAppActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    ConsumerMapView mapView = findViewById(R.id.consumer_map_view);

    if (mapView != null) {
      mapView.getConsumerGoogleMapAsync(
          new ConsumerMapReadyCallback() {
            // The map returned in the callback is used to access the ConsumerController.
            @Override
            public void onConsumerMapReady(@NonNull ConsumerGoogleMap consumerGoogleMap) {
              ConsumerController consumerController = consumerGoogleMap.getConsumerController();
            }
          }, this, null);
    }
  }

}

Kotlin

class SampleAppActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    val mapView = findViewById(R.id.consumer_map_view) as ConsumerMapView

    mapView.getConsumerGoogleMapAsync(
      object : ConsumerMapReadyCallback() {
        // The map returned in the callback is used to access the ConsumerController.
        override fun onConsumerMapReady(consumerGoogleMap: ConsumerGoogleMap) {
          val consumerController = consumerGoogleMap.getConsumerController()!!
        }
      },
      /* fragmentActivity= */ this,
      /* googleMapOptions= */ null,
    )
  }
}

تكون علامة MapView في الجزء هي نفسها ماهية المثال أعلاه عن MapView في نشاط معيّن، باستثناء أنّ الجزء يضخم التنسيق الذي يتضمّن MapView في طريقة للجزء onCreateView().

Java

public class MapViewInFragment extends Fragment {

  @Override
  public View onCreateView(
      @NonNull LayoutInflater layoutInflater,
      @Nullable ViewGroup viewGroup,
      @Nullable Bundle bundle) {
    return layoutInflater.inflate(R.layout.consumer_map_view, viewGroup, false);
  }

}

Kotlin

class MapViewInFragment : Fragment() {
  override fun onCreateView(
    layoutInflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?,
  ): View {
    return layoutInflater.inflate(R.layout.consumer_map_view, viewGroup, false)
  }
}

ضبط تكبير/تصغير الكاميرا للتركيز على رحلة

يعمل زر "موقعي الجغرافي" التلقائي المُضمَّن في حزمة تطوير البرامج (SDK) للخرائط على توسيط الكاميرا على الموقع الجغرافي للجهاز.

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

حزمة تطوير البرامج (SDK) للمستهلكين لنظام Android المضمَّن: Autocam

ولتتمكّن من التركيز على الرحلة بدلاً من الموقع الجغرافي للجهاز، توفّر حزمة "SDK للمستهلكين" ميزة Auto Camera تكون مفعَّلة بشكل تلقائي. يتم تكبير الكاميرا للتركيز على مسار مشاركة الرحلة ونقطة الطريق التالية.

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

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 هو معرّف مشروع Cloud الذي يملكه مقدّم الخدمة.
401 غير مصادق لم تتم مصادقة الطلب بسبب رمز JWT المميز غير صالح. سيحدث هذا الخطأ إذا تم توقيع رمز JWT المميز بدون معرّف الرحلة أو إذا انتهت صلاحية رمز JWT المميز.
403 PERMISSION_DENIED لا يملك العميل إذنًا كافيًا. يحدث هذا الخطأ إذا كان الرمز المميّز JWT غير صالح أو لم يكن لدى العميل إذن أو إذا لم يتم تفعيل واجهة برمجة التطبيقات لمشروع العميل. قد يكون رمز JWT مفقودًا أو قد يكون الرمز المميّز موقَّعًا باستخدام معرّف رحلة لا يتطابق مع معرّف الرحلة المطلوب.
429 RESOURCE_EXHAUSTED تبلغ حصة الموارد صفر أو أن معدل الزيارات يتجاوز الحد المسموح به.
503 UNAVAILABLE الخدمة غير متاحة. عادةً ما يكون الخادم معطلاً.
504 DEADLINE_EXCEEDED تم تجاوز الموعد النهائي لتقديم الطلب. ولن يحدث هذا إلا إذا حدد المتصل موعدًا نهائيًا أقصر من الموعد النهائي الافتراضي للطريقة (أي أن الموعد النهائي المطلوب لا يكفي للخادم لمعالجة الطلب) ولم ينته الطلب خلال الموعد النهائي.

لمزيد من المعلومات، يُرجى الاطّلاع على مقالة معالجة خطأ حِزم تطوير البرامج (SDK) الخاصة بالمستهلك.