يمكنك استخدام Driver SDK لتوفير تنقّل وتتبُّع محسّنَين في تطبيق "رحلتك" و"مستوى تقدّم الطلب". توفر Driver SDK تحديثات لموقع المركبة ومهامها لحلول Fleet Solutions (الرحلات والتسليمات) عند الطلب.
تُبقي حزمة Driver SDK خدمات Fleet Engine والخدمات المخصّصة لديك على دراية بموقع المركبة وحالتها. على سبيل المثال، يمكن أن تكون المركبة ONLINE
أو OFFLINE
، ويتغيّر الموقع الجغرافي للمركبة مع تقدّم الرحلة.
الحد الأدنى من متطلبات النظام
يجب أن يعمل الجهاز الجوّال بالإصدار 6.0 من نظام التشغيل Android (المستوى 23 من واجهة برمجة التطبيقات) أو إصدار أحدث.
ضبط التبعيات والإنشاء
يتوفّر الإصدار 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، يجب أن يستهدف تطبيقك الإصدار 23 من minSdkVersion
أو الإصدارات الأحدث.
لتشغيل تطبيق تم إنشاؤه باستخدام Driver SDK، يجب تثبيت خدمات Google Play على جهاز Android.
إعداد مشروع التطوير
لإعداد مشروع التطوير والحصول على مفتاح واجهة برمجة تطبيقات للمشروع على Google Cloud Console:
أنشِئ مشروعًا جديدًا على Google Cloud Console أو اختَر مشروعًا حاليًا لاستخدامه مع حزمة تطوير البرامج (SDK) لخدمة Drive. انتظر بضع دقائق حتى يصبح المشروع الجديد مرئيًا على Google Cloud Console.
من أجل تشغيل التطبيق التجريبي، يجب أن يتمكن مشروعك من الوصول إلى حزمة تطوير البرامج بالاستناد إلى بيانات "خرائط Google" لنظام التشغيل Android. في Google Cloud Console، اختَر واجهات برمجة التطبيقات والخدمات > المكتبة، ثم ابحث عن حزمة تطوير البرامج بالاستناد إلى بيانات "خرائط Google" وفعِّلها لنظام التشغيل Android.
احصل على مفتاح واجهة برمجة تطبيقات للمشروع عن طريق اختيار واجهات برمجة التطبيقات والخدمات > بيانات الاعتماد > إنشاء بيانات اعتماد > مفتاح واجهة برمجة التطبيقات. لمزيد من المعلومات حول الحصول على مفتاح واجهة برمجة التطبيقات، يمكنك الاطّلاع على الحصول على مفتاح واجهة برمجة التطبيقات.
إضافة حزمة تطوير البرامج (SDK) للسائق إلى تطبيقك
تتوفّر حزمة Driver SDK في مستودع Google Maven. يتضمن المستودع ملفات نموذج كائن المشروع (pom) لحزمة SDK وJavadocs. لإضافة Driver SDK إلى تطبيقك:
أضِف التبعية التالية إلى إعدادات 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>
تعتمد حزمة تطوير البرامج (SDK) للسائق على حزمة تطوير البرامج (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 إلى تطبيقك، أضِف مفتاح واجهة برمجة التطبيقات إلى تطبيقك. وعليك استخدام مفتاح واجهة برمجة التطبيقات للمشروع الذي حصلت عليه عند إعداد مشروع التطوير.
يوضِّح هذا القسم طريقة تخزين مفتاح واجهة برمجة التطبيقات كي يتمكّن تطبيقك من الرجوع إليه بأمان. ويجب عدم التحقّق من مفتاح واجهة برمجة التطبيقات في نظام التحكّم في الإصدارات. يجب تخزينها في ملف local.properties
الموجود
في الدليل الجذري لمشروعك. لمزيد من المعلومات حول ملف local.properties
، راجِع ملفات خصائص Gradle.
ولتبسيط هذه المهمة، يمكنك استخدام المكوّن الإضافي Secret Gradle الإضافي لنظام Android.
لتثبيت المكوّن الإضافي وتخزين مفتاح واجهة برمجة التطبيقات:
افتح ملف
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") } }
افتح ملف
build.gradle
على مستوى التطبيق وأضِف الرمز التالي إلى العنصرplugins
.رائع
id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
Kotlin
id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
إذا كنت تستخدم "استوديو Android"، عليك مزامنة مشروعك مع Gradle.
افتح
local.properties
في الدليل على مستوى المشروع، ثم أضِف الرمز التالي. استبدِلYOUR_API_KEY
بمفتاح واجهة برمجة التطبيقات.MAPS_API_KEY=YOUR_API_KEY
في ملف
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 حول كيفية تضمين إشعارات البرامج المفتوحة المصدر.
التبعيات
إذا كنت تستخدم ProGuard لتحسين إصداراتك، قد تحتاج إلى إضافة الأسطر التالية إلى ملف إعداد ProGuard:
-dontwarn com.google.**
-dontwarn okio.**
الحد الأدنى لمستوى واجهة برمجة التطبيقات المسموح به هو 23.
جارٍ إعداد حزمة تطوير البرامج (SDK)
يجب إدخال رقم تعريف موفّر الخدمة (عادةً رقم تعريف مشروع Google Cloud) من أجل إعداد الكائن DriverContext
. لمزيد من التفاصيل حول إعداد
مشروع Google Cloud، يُرجى الاطّلاع على
المصادقة والتفويض.
قبل استخدام Driver SDK، يجب عليك أولاً تهيئة حزمة SDK للتنقل. لإعداد حزمة SDK:
يمكنك الحصول على عنصر
Navigator
منNavigationApi
.Java
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; } } );
Kotlin
NavigationApi.getNavigator( this, // Activity object : NavigatorListener() { override fun onNavigatorReady(navigator: Navigator) { // Keep a reference to the Navigator (used to configure and start nav) this@myActivity.navigator = navigator } }, )
أنشِئ عنصر
DriverContext
لتعبئة الحقول المطلوبة.Java
DriverContext driverContext = DriverContext.builder(application) .setProviderId(providerId) .setVehicleId(vehicleId) .setAuthTokenFactory(authTokenFactory) .setNavigator(navigator) .setRoadSnappedLocationProvider( NavigationApi.getRoadSnappedLocationProvider(application)) .build();
Kotlin
val driverContext = DriverContext.builder(application) .setProviderId(providerId) .setVehicleId(vehicleId) .setAuthTokenFactory(authTokenFactory) .setNavigator(navigator) .setRoadSnappedLocationProvider(NavigationApi.getRoadSnappedLocationProvider(application)) .build()
استخدِم الكائن
DriverContext
لإعداد*DriverApi
.Java
RidesharingDriverApi ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext);
Kotlin
val ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext)
يمكنك الحصول على
RidesharingVehicleReporter
من عنصر واجهة برمجة التطبيقات. (يمتد نطاق*VehicleReporter
إلىNavigationVehicleReporter
.)Java
RidesharingVehicleReporter vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter();
Kotlin
val vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter()
جارٍ المصادقة مع "AuthTokenFactory
"
عندما تُنشئ Driver SDK تحديثات للموقع الجغرافي،
يجب أن ترسل هذه التحديثات إلى
خادم Fleet Engine. لمصادقة هذه الطلبات، ستطلب حزمة تطوير البرامج (SDK) الخاصة بالسائقين من Drive الحصول على النسخة الافتراضية AuthTokenFactory
التي يوفّرها المتصل.
فإن المصنع مسؤول عن إنشاء رموز المصادقة في وقت تحديث الموقع.
إنّ الطريقة التي يتم بها إنشاء الرموز المميّزة بالضبط ستكون خاصة بحالة كل مطوّر. ومع ذلك، من المحتمل أن يحتاج التنفيذ إلى:
- جلب رمز مميز للمصادقة، ربما بتنسيق JSON، من خادم HTTPS
- تحليل الرمز المميّز وتخزينه مؤقتًا
- إعادة تحميل الرمز المميّز عند انتهاء صلاحيته
لمعرفة تفاصيل الرموز المميّزة التي يتوقعها خادم Fleet Engine، يُرجى الاطّلاع على المقالة إنشاء رمز JSON المميّز للويب (JWT) للتفويض.
في ما يلي تنفيذ لهيكل AuthTokenFactory
:
Java
class JsonAuthTokenFactory implements AuthTokenFactory {
private String token; // 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(authTokenContext.getVehicleId());
}
return token;
}
private void fetchNewToken(String vehicleId) {
String url =
new Uri.Builder()
.scheme("https")
.authority("yourauthserver.example")
.appendPath("token")
.appendQueryParameter("vehicleId", vehicleId)
.build()
.toString();
try (Reader r = new InputStreamReader(new URL(url).openStream())) {
com.google.gson.JsonObject obj
= com.google.gson.JsonParser.parseReader(r).getAsJsonObject();
token = obj.get("Token").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);
}
}
}
Kotlin
class JsonAuthTokenFactory : AuthTokenFactory() {
private var token: String = ""
private var expiryTimeMs: Long = 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 fun getToken(context: AuthTokenContext): String {
if (System.currentTimeMillis() > expiryTimeMs) {
// The token has expired, go get a new one.
fetchNewToken(authTokenContext.getVehicleId())
}
return token
}
fun fetchNewToken(vehicleId: String) {
val url =
Uri.Builder()
.scheme("https")
.authority("yourauthserver.example")
.appendPath("token")
.appendQueryParameter("vehicleId", vehicleId)
.build()
.toString()
try {
val reader = InputStreamReader(URL(url).openStream())
reader.use {
val obj = com.google.gson.JsonParser.parseReader(r).getAsJsonObject()
token = obj.get("ServiceToken").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 (e: IOException) {
// 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 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
اختيارية على النحو التالي:
Java
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.
}
}
Kotlin
class MyStatusListener : StatusListener() {
/** Called when background status is updated, during actions such as location reporting. */
override fun updateStatus(statusLevel: StatusLevel, statusCode: StatusCode, statusMsg: String) {
// 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 (الإصدار 19 من واجهة برمجة التطبيقات أو الإصدارات الأقدم) رمز تصحيح SecurityProvider
ليتمكّن من الاتصال بالخادم. يمكنك الاطّلاع على هذه المقالة للحصول على مزيد من المعلومات حول العمل باستخدام طبقة المقابس الآمنة (SSL) في Android. تحتوي المقالة أيضًا على عيّنات تعليمات برمجية لتصحيح مقدم خدمة الأمان.
تفعيل تحديثات الموقع الجغرافي
بعد توفّر مثيل *VehicleReporter
، يصبح تفعيل تعديلات الموقع الجغرافي
مباشرةً:
Java
RidesharingVehicleReporter reporter = ...;
reporter.enableLocationTracking();
Kotlin
val reporter = ...
reporter.enableLocationTracking()
يتم إرسال إشعارات الموقع الجغرافي على فترات منتظمة عندما تكون حالة المركبة
ONLINE
. يُرجى العِلم أنّ طلب الرقم reporter.enableLocationTracking()
لا
يضبط حالة المركبة تلقائيًا على ONLINE
. عليك ضبط حالة المركبة بشكل صريح.
يبلغ الفاصل الزمني لإعداد التقارير 10 ثوانٍ تلقائيًا. يمكن تغيير الفاصل الزمني لإعداد التقارير باستخدام reporter.setLocationReportingInterval(long, TimeUnit)
الحد الأدنى للفاصل الزمني للتحديث المتوافق هو 5 ثوانٍ. وقد تؤدي التحديثات الأكثر تكرارًا
إلى بطء الطلبات والأخطاء.
إيقاف تحديثات الموقع الجغرافي
عند انتهاء عملية تبديل السائق، يمكن إيقاف تعديلات الموقع الجغرافي
ووضع علامة بلا اتصال بالإنترنت على المركبة من خلال الاتصال على
DeliveryVehicleReporter.disableLocationTracking
أو
RidesharingVehicleReporter.disableLocationTracking
.
ستؤدي هذه المكالمة إلى تحديد موعد تحديث أخير للتسليم الفوري، مما يشير إلى أن المركبة غير متصلة بالإنترنت. لن يحتوي هذا التحديث على الموقع الجغرافي للمستخدم.
ضبط حالة المركبة
عند تفعيل ميزة تعديل الموقع الجغرافي، سيؤدي ضبط حالة المركبة على ONLINE
إلى إتاحة المركبة لطلبات البحث SearchVehicles
. وبالمثل، سيؤدي وضع علامة OFFLINE
على مركبة إلى أنّها غير متوفّرة.
يمكنك ضبط حالة المركبة على جهة الخادم (راجِع تحديث المركبة)، أو مباشرةً في حزمة تطوير البرامج (SDK) للسائق:
Java
RidesharingVehicleReporter reporter = ...;
reporter.enableLocationTracking();
reporter.setVehicleState(VehicleState.ONLINE);
Kotlin
val reporter = ...
reporter.enableLocationTracking()
reporter.setVehicleState(VehicleState.ONLINE)
عند تفعيل تحديثات الموقع الجغرافي، سيتم نشر مكالمة إلى setVehicleState
عند تحديث الموقع الجغرافي التالي.
سيؤدي وضع علامة ONLINE
على مركبة في حال عدم تفعيل ميزة "تتبُّع الموقع الجغرافي" إلى
ظهور IllegalStateException
. يمكن وضع علامة OFFLINE
على المركبة في حال
عدم تفعيل ميزة تتبُّع الموقع الجغرافي أو إيقافها صراحةً. وسيؤدي ذلك إلى
تحديث فوري. سيؤدي الاتصال على
RidesharingVehicleReporter.disableLocationTracking()
إلى ضبط
حالة المركبة على OFFLINE
.
يُرجى العِلم أنّ setVehicleState
سيعود فورًا ويتم تطبيق التعديلات على سلسلة محادثات تحديث الموقع الجغرافي. كما هو الحال عند معالجة الأخطاء المتعلقة بتحديثات المواقع الجغرافية، يتم نشر الأخطاء التي تحدث عند تعديل حالة المركبة باستخدام السمة StatusListener
المتوفرة اختياريًا والتي تم ضبطها في DriverContext
.