حزمة Driver SDK هي مكتبة تدمجها في تطبيق السائق. وتكون مسؤولة تحديث Fleet Engine عن الموقع الجغرافي للسائق والمسار والمسافة المتبقية والوقت المقدر للوصول. كما أنها تتكامل مع حزمة SDK للتنقل، والتي توفر إرشادات التنقل منعطفًا بمنعطف للسائق.
الحد الأدنى لمتطلبات النظام
المتطلّبات الأساسية
يفترض هذا الدليل أن تطبيقك يستخدم حزمة SDK للتنقل وأنه تم إعداد الواجهة الخلفية Fleet Engine وهي متاحة. ومع ذلك، يوفّر مثال الرمز البرمجي نموذجًا لكيفية إعداد حزمة SDK للتنقّل.
يجب أيضًا تفعيل حزمة تطوير البرامج بالاستناد إلى بيانات "خرائط Google" لنظام التشغيل iOS في مشروعك على Google Cloud والحصول على مفتاح واجهة برمجة تطبيقات.
الحصول على إذن بالوصول
إذا كنت أحد عملاء Google Workspace، يمكنك إنشاء
مجموعة Workspace مثل
google-maps-platform-sdk-users@workspacedomain.com
أثناء عملية الإعداد
وتقديم الاسم إلى Google. هذه هي الطريقة الموصى بها.
ستتم بعد ذلك إضافة مجموعة Workspace إلى القائمة المسموح بها التي
تمنح إمكانية الوصول إلى مستودعات CocoaPods الصحيحة. تأكد من أن رسائل البريد الإلكتروني للمستخدم وعناوين البريد الإلكتروني
لحساب الخدمة التي تحتاج إلى الوصول مدرجة في هذه القائمة.
إذا لم تتمكّن مؤسستك من إنشاء مجموعات Workspace، يمكنك إرسال قائمة بعناوين البريد الإلكتروني لحسابات المستخدمين والخدمة إلى Google والتي تحتاج إلى الوصول إلى هذه العناصر.
تنمية محلية
بالنسبة إلى التطوير المحلي، يكفي تسجيل الدخول باستخدام حزمة تطوير البرامج (SDK) للسحابة الإلكترونية.
gcloud
gcloud auth login
يجب أن يكون عنوان البريد الإلكتروني المستخدَم لتسجيل الدخول عضوًا في مجموعة Workspace.
الأتمتة (إنشاء الأنظمة أو الدمج المستمر)
إعداد مضيفي التشغيل الآلي وفقًا لأفضل الممارسات:
إذا تم إجراء العملية داخل بيئة Google Cloud، يمكنك استخدام الرصد التلقائي لبيانات الاعتماد.
يمكنك أيضًا تخزين ملف مفتاح حساب الخدمة في موقع آمن على نظام ملفات المضيف وضبط متغيّر بيئة GOOGLE_APPLICATION_CREDENTIALS بشكل مناسب.
يجب أن يكون البريد الإلكتروني لحساب الخدمة المرتبط ببيانات الاعتماد عضوًا في Workspace Goup.
تكوين المشروع
يمكنك ضبط حزمة تطوير البرامج (SDK) لبرنامج التشغيل باستخدام CocoaPods.
استخدام CocoaPods
لضبط حزمة تطوير البرامج (SDK) لبرنامج التشغيل باستخدام CocoaPods، ستحتاج إلى العناصر التالية:
- أداة CocoaPods: لتثبيت هذه الأداة، افتح المحطة الطرفية وشغِّل
الأمر التالي.
shell sudo gem install cocoapods
يمكنك الاطّلاع على دليل بدء استخدام CocoaPods للحصول على مزيد من التفاصيل.
يمكنك إنشاء ملف Podfile لـ Driver SDK واستخدامه لتثبيت واجهة برمجة التطبيقات وتبعياتها: أنشئ ملفًا باسم Podfile في دليل مشروعك. يحدد هذا الملف تبعيات مشروعك. قم بتحرير Podfile وإضافة تبعياتك. فيما يلي مثال يتضمن التبعيات:
source "https://github.com/CocoaPods/Specs.git" target 'YOUR_APPLICATION_TARGET_NAME_HERE' do pod 'GoogleRidesharingDriver' end
احفظ ملف Podfile. افتح نافذة طرفية وانتقل إلى الدليل الذي يحتوي على Podfile:
cd <path-to-project>
شغِّل الأمر pod install. سيؤدي ذلك إلى تثبيت واجهات برمجة التطبيقات المحددة في Podfile، إلى جانب أي ملحقات قد تكون لديهم.
pod install
أغلق Xcode، ثم افتح ملف xcworkspace لمشروعك (بالنقر المزدوج) لبدء Xcode. من الآن فصاعدًا، يجب عليك استخدام ملف .xcworkspace لفتح المشروع.
إصدارات ألفا أو الإصدارات التجريبية من حزمة تطوير البرامج (SDK)
لإعداد الإصدارات الأولية أو التجريبية من Driver SDK لنظام التشغيل iOS، ستحتاج إلى العناصر التالية:
أداة CocoaPods: لتثبيت هذه الأداة، افتح المحطة الطرفية وشغِّل الأمر التالي.
sudo gem install cocoapods
لمزيد من التفاصيل، يُرجى الاطّلاع على دليل بدء استخدام CocoaPods.
حساب التطوير الخاص بك ضمن قائمة أذونات الوصول إلى Google لا يُعدّ مستودع اللوحات الخاصة بإصدارَي ألفا والإصدار التجريبي من حزمة تطوير البرامج (SDK) مصدرًا عامًا. للوصول إلى هذه الإصدارات، اتصل بمهندس عملاء Google. يضيف المهندس حساب التطوير الخاص بك إلى قائمة أذونات الوصول، ثم يضبط ملف تعريف ارتباط للمصادقة.
بعد إدراج مشروعك في قائمة أذونات الوصول، يمكنك الوصول إلى المجموعة.
أنشئ ملف Podfile لحزمة Driver SDK لنظام التشغيل iOS واستخدمه لتثبيت واجهة برمجة التطبيقات وتبعياتها: أنشئ ملفًا باسم Podfile في دليل مشروعك. يحدد هذا الملف تبعيات مشروعك. قم بتحرير Podfile وإضافة تبعياتك. فيما يلي مثال يتضمن التبعيات:
source "https://cpdc-eap.googlesource.com/ridesharing-driver-sdk.git" source "https://github.com/CocoaPods/Specs.git" target 'YOUR_APPLICATION_TARGET_NAME_HERE' do pod 'GoogleRidesharingDriver' end
احفظ ملف Podfile. افتح نافذة طرفية وانتقل إلى الدليل الذي يحتوي على Podfile:
cd <path-to-project>
شغِّل الأمر pod install. سيؤدي ذلك إلى تثبيت واجهات برمجة التطبيقات المحددة في Podfile، إلى جانب أي ملحقات قد تكون لديهم.
pod install
أغلق Xcode، ثم افتح ملف xcworkspace لمشروعك (بالنقر المزدوج) لبدء Xcode. من الآن فصاعدًا، يجب عليك استخدام ملف .xcworkspace لفتح المشروع.
تثبيت XCFramework
XCFramework عبارة عن حزمة ثنائية تستخدمها لتثبيت SDK لبرنامج التشغيل. يمكنك استخدام هذه الحزمة على عدة أنظمة أساسية، بما في ذلك الأجهزة التي تستخدم شريحة M1. يوضِّح هذا الدليل كيفية إضافة XCFramework الذي يحتوي على حزمة Driver SDK إلى مشروعك يدويًا وضبط إعدادات الإصدار في Xcode.
تنزيل البرنامج الثنائي لحزمة SDK والموارد:
فك ضغط الملفات المضغوطة للوصول إلى XCFramework والموارد.
ابدأ Xcode وافتح مشروعًا حاليًا أو أنشئ مشروعًا جديدًا. إذا كنت مستخدمًا جديدًا لنظام التشغيل iOS، أنشِئ مشروعًا جديدًا واختَر نموذج تطبيق iOS.
قم بإنشاء مجموعة أطر عمل ضمن مجموعة المشروعات إذا لم تكن هناك مجموعة بالفعل.
اسحب ملف
gRPCCertificates.bundle
الذي تم تنزيله إلى دليل المستوى الأعلى في مشروع Xcode. اختَر نسخ العناصر إذا لزم الأمر عندما يُطلب منك ذلك.لتثبيت "حزمة تطوير البرامج (SDK) لبرنامج التشغيل"، اسحب ملف
GoogleRidesharingDriver.xcframework
إلى مشروعك ضمن أطر العمل والمكتبات والمحتوى المضمَّن. اختَر نسخ العناصر إذا لزم الأمر عندما يُطلب منك ذلك.اسحب ملف
GoogleRidesharingDriver.bundle
الذي تم تنزيله إلى دليل المستوى الأعلى في مشروع Xcode. اختَر "Copy items if needed
" عندما يُطلب منك ذلك.اختَر مشروعك من Project Navigator، ثم اختَر الهدف الذي يستهدفه تطبيقك.
افتح علامة التبويب "Build Stages" (مراحل الإنشاء)، وفي Link Binary with Libraries (رابط Binary مع المكتبات)، أضف أطر العمل والمكتبات التالية إذا لم تكن موجودة بالفعل:
Accelerate.framework
AudioToolbox.framework
AVFoundation.framework
CoreData.framework
CoreGraphics.framework
CoreLocation.framework
CoreTelephony.framework
CoreText.framework
GLKit.framework
ImageIO.framework
libc++.tbd
libxml2.tbd
libz.tbd
LocalAuthentication.framework
OpenGLES.framework
QuartzCore.framework
SystemConfiguration.framework
UIKit.framework
WebKit.framework
اختر مشروعك بدلاً من هدف محدد، وافتح علامة التبويب إعدادات التصميم. في القسم علامات الرابط الأخرى، أضِف
‑ObjC
لكل من تصحيح الأخطاء والإصدار. إذا لم تكن هذه الإعدادات مرئية، غيِّر الفلتر في شريط "إعدادات الإصدار" من أساسي إلى الكل.
فحص ملف بيان الخصوصية في Apple
تشترط Apple تفاصيل خصوصية التطبيقات للتطبيقات المتوفّرة على App Store. يُرجى الانتقال إلى صفحة تفاصيل خصوصية Apple App Store لمعرفة آخر الأخبار ومزيد من المعلومات.
يتم تضمين ملف بيان الخصوصية من Apple في حزمة الموارد لحزمة تطوير البرامج (SDK). للتأكّد من تضمين "ملف بيان الخصوصية" وفحص محتواه، عليك إنشاء أرشيف لتطبيقك وإنشاء تقرير خصوصية من الأرشيف.
تنفيذ التفويض والمصادقة
عندما ينشئ تطبيق Driver تحديثات في الخلفية Fleet Engine ويرسلها،
يجب أن تتضمّن الطلبات رموز دخول صالحة. للموافقة على هذه الطلبات
والمصادقة عليها، تستدعي "حزمة تطوير البرامج (SDK) لبرنامج التشغيل" العنصر الذي يتوافق مع
بروتوكول GMTDAuthorization
. الكائن مسؤول عن توفير رمز الدخول المطلوب.
بصفتك مطوّر التطبيق، أنت تختار كيفية إنشاء الرموز المميّزة. وينبغي أن يوفر التنفيذ الخاص بك القدرة على القيام بما يلي:
- استرجاع رمز دخول، ربما بتنسيق JSON، من خادم HTTPS.
- تحليل الرمز المميّز وتخزينه مؤقتًا
- أعِد تحميل الرمز المميّز عند انتهاء صلاحيته.
لمعرفة تفاصيل الرموز المميّزة التي يتوقعها خادم Fleet Engine، يُرجى الاطّلاع على إنشاء رمز JSON المميّز للويب (JWT) للتفويض.
رقم تعريف مقدّم الخدمة هو نفسه رقم تعريف مشروع Google Cloud. يمكنك الاطّلاع على دليل المستخدم لواجهة برمجة التطبيقات Fleet Engine Deliveries API للحصول على مزيد من المعلومات.
يقدم المثال التالي موفّرًا لرمز الدخول:
#import "SampleAccessTokenProvider.h"
#import <GoogleRidesharingDriver/GoogleRidesharingDriver.h>
// SampleAccessTokenProvider.h
@interface SampleAccessTokenProvider : NSObject<GMTDAuthorization>
@end
static NSString *const PROVIDER_URL = @"INSERT_YOUR_TOKEN_PROVIDER_URL";
// SampleAccessTokenProvider.m
@implementation SampleAccessTokenProvider{
// The cached vehicle token.
NSString *_cachedVehicleToken;
// Keep track of the vehicle ID the cached token is for.
NSString *_lastKnownVehicleID;
// Keep track of when tokens expire for caching.
NSTimeInterval _tokenExpiration;
}
- (void)fetchTokenWithContext:(nullable GMTDAuthorizationContext *)authorizationContext
completion:(nonnull GMTDAuthTokenFetchCompletionHandler)completion {
if (!completion) {
NSAssert(NO, @"%s encountered an unexpected nil completion.", __PRETTY_FUNCTION__);
return;
}
// Get the vehicle ID from the authorizationContext. This is set by the Driver SDK.
NSString *vehicleID = authorizationContext.vehicleID;
if (!vehicleID) {
NSAssert(NO, @"Vehicle ID is missing from authorizationContext.");
return;
}
// Clear cached vehicle token if vehicle ID has changed.
if (![_lastKnownVehicleID isEqual:vehicleID]) {
_tokenExpiration = 0.0;
_cachedVehicleToken = nil;
}
_lastKnownVehicleID = vehicleID;
// Clear cached vehicle token if it has expired.
if ([[NSDate date] timeIntervalSince1970] > _tokenExpiration) {
_cachedVehicleToken = nil;
}
// If appropriate, use the cached token.
if (_cachedVehicleToken) {
completion(_cachedVehicleToken, nil);
return;
}
// Otherwise, try to fetch a new token from your server.
NSURL *requestURL = [NSURL URLWithString:PROVIDER_URL];
NSMutableURLRequest *request =
[[NSMutableURLRequest alloc] initWithURL:requestURL];
request.HTTPMethod = @"GET";
// Replace the following key values with the appropriate keys based on your
// server's expected response.
NSString *vehicleTokenKey = @"VEHICLE_TOKEN_KEY";
NSString *tokenExpirationKey = @"TOKEN_EXPIRATION";
__weak typeof(self) weakSelf = self;
void (^handler)(NSData *_Nullable data, NSURLResponse *_Nullable response,
NSError *_Nullable error) =
^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) {
typeof(self) strongSelf = weakSelf;
if (error) {
completion(nil, error);
return;
}
NSError *JSONError;
NSMutableDictionary *JSONResponse =
[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&JSONError];
if (JSONError) {
completion(nil, JSONError);
return;
} else {
// Sample code only. No validation logic.
id expirationData = JSONResponse[tokenExpirationKey];
if ([expirationData isKindOfClass:[NSNumber class]]) {
NSTimeInterval expirationTime = ((NSNumber *)expirationData).doubleValue;
strongSelf->_tokenExpiration = [[NSDate date] timeIntervalSince1970] + expirationTime;
}
strongSelf->_cachedVehicleToken = JSONResponse[vehicleTokenKey];
completion(JSONResponse[vehicleTokenKey], nil);
}
};
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *mainQueueURLSession =
[NSURLSession sessionWithConfiguration:config delegate:nil
delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDataTask *task = [mainQueueURLSession dataTaskWithRequest:request completionHandler:handler];
[task resume];
}
@end
إنشاء مثيل DeliveryDriverAPI
للحصول على مثيل GMTDDeliveryVehicleReporter
، عليك أولاً إنشاء مثيل GMTDDeliveryDriverAPI
باستخدام providerID وvehicleID وdriverContext وaccessTokenProvider. إنّ رقم تعريف مقدّم الخدمة هو نفسه
معرّف مشروع Google Cloud. ويمكنك الوصول إلى مثيل GMTDDeliveryVehicleReporter
من واجهة برمجة تطبيقات برنامج التشغيل مباشرةً.
ينشئ المثال التالي مثيل GMTDDeliveryDriverAPI
:
#import “SampleViewController.h”
#import “SampleAccessTokenProvider.h”
#import <GoogleRidesharingDriver/GoogleRidesharingDriver.h>
static NSString *const PROVIDER_ID = @"INSERT_YOUR_PROVIDER_ID";
@implementation SampleViewController {
GMSMapView *_mapView;
}
- (void)viewDidLoad {
NSString *vehicleID = @"INSERT_CREATED_VEHICLE_ID";
SampleAccessTokenProvider *accessTokenProvider =
[[SampleAccessTokenProvider alloc] init];
GMTDDriverContext *driverContext =
[[GMTDDriverContext alloc] initWithAccessTokenProvider:accessTokenProvider
providerID:PROVIDER_ID
vehicleID:vehicleID
navigator:_mapView.navigator];
GMTDDeliveryDriverAPI *deliveryDriverAPI = [[GMTDDeliveryDriverAPI alloc] initWithDriverContext:driverContext];
}
الاستماع بشكل اختياري إلى أحداث AutomotiveReporter
يتم تحديث المركبة من قِبل "GMTDDeliveryVehicleReporter
" بشكل دوري عندما
تكون قيمة "locationTrackingEnabled
" هي "نعم". للاستجابة لهذه التعديلات الدورية، يمكن لأي كائن الاشتراك في أحداث GMTDDeliveryVehicleReporter
من خلال الالتزام ببروتوكول GMTDVehicleReporterListener
.
يمكنك التعامل مع الأحداث التالية:
vehicleReporter:didSucceedVehicleUpdate
تُعلم تطبيق Drive بأن خدمات الخلفية قد تلقّت بنجاح تحديث الموقع الجغرافي والولاية للمركبة.
vehicleReporter:didFailVehicleUpdate:withError
تُبلِغ المستمِع بتعذُّر تحديث المركبة. طالما تم تفعيل ميزة تتبُّع الموقع الجغرافي، يواصل "
GMTDDeliveryVehicleReporter
" إرسال أحدث البيانات إلى خلفية Fleet Engine.
يتعامل المثال التالي مع هذه الأحداث:
SampleViewController.h
@interface SampleViewController : UIViewController<GMTDVehicleReporterListener>
@end
SampleViewController.m
#import “SampleViewController.h”
#import “SampleAccessTokenProvider.h”
#import <GoogleRidesharingDriver/GoogleRidesharingDriver.h>
static NSString *const PROVIDER_ID = @"INSERT_YOUR_PROVIDER_ID";
@implementation SampleViewController {
GMSMapView *_mapView;
}
- (void)viewDidLoad {
// ASSUMES YOU IMPLEMENTED HAVE THE SAMPLE CODE UP TO THIS STEP.
[ridesharingDriverAPI.vehicleReporter addListener:self];
}
- (void)vehicleReporter:(GMTDDeliveryVehicleReporter *)vehicleReporter didSucceedVehicleUpdate:(GMTDVehicleUpdate *)vehicleUpdate {
// Handle update succeeded.
}
- (void)vehicleReporter:(GMTDDeliveryVehicleReporter *)vehicleReporter didFailVehicleUpdate:(GMTDVehicleUpdate *)vehicleUpdate withError:(NSError *)error {
// Handle update failed.
}
@end
تفعيل تتبع الموقع الجغرافي
لتفعيل ميزة تتبُّع الموقع الجغرافي، يمكن لتطبيقك ضبط locationTrackingEnabled
على YES
في GMTDDeliveryVehicleReporter
. بعد ذلك، سيرسل GMTDDeliveryVehicleReporter
تلقائيًا آخر المعلومات حول الموقع الجغرافي. عند ضبط GMSNavigator
في وضع التنقّل (عندما يتم ضبط وجهة من خلال setDestinations
) وضبط locationTrackingEnabled
على YES
، سيرسل GMTDDeliveryVehicleReporter
تلقائيًا آخر المعلومات المتعلقة بالمسار والوقت المقدر للوصول.
وسيكون المسار الذي تم ضبطه أثناء هذه التعديلات هو المسار نفسه الذي ينتقل إليه
السائق أثناء جلسة التنقّل. وبالتالي، لكي يعمل تتبُّع الشحن بشكل صحيح، يجب أن تتطابق نقطة الطريق المحدّدة من خلال -setDestinations:callback:
مع الوجهة المحدّدة في الواجهة الخلفية لـ Fleet Engine.
يوضّح المثال التالي ميزة تتبُّع الموقع الجغرافي:
SampleViewController.m
#import “SampleViewController.h”
#import “SampleAccessTokenProvider.h”
#import <GoogleRidesharingDriver/GoogleRidesharingDriver.h>
static NSString *const PROVIDER_ID = @"INSERT_YOUR_PROVIDER_ID";
@implementation SampleViewController {
GMSMapView *_mapView;
}
- (void)viewDidLoad {
// ASSUMES YOU IMPLEMENTED HAVE THE SAMPLE CODE UP TO THIS STEP.
deliveryDriverAPI.vehicleReporter.locationTrackingEnabled = YES;
}
@end
يكون الفاصل الزمني لإعداد التقارير 10 ثوانٍ تلقائيًا، ولكن يمكن تغيير الفاصل الزمني لإعداد التقارير باستخدام locationUpdateInterval
. يبلغ الحدّ الأدنى للفاصل الزمني المسموح به
للتحديث 5 ثوانٍ. يبلغ الحدّ الأقصى للفاصل الزمني المسموح به للتحديث 60 ثانية. قد تؤدي التحديثات الأكثر تكرارًا إلى بطء الطلبات وحدوث أخطاء.
إيقاف تحديثات الموقع الجغرافي
يمكن لتطبيقك إيقاف تحديثات الموقع الجغرافي لمركبة. على سبيل المثال، عند انتهاء وردية السائق، يمكن لتطبيقك ضبط locationTrackingEnabled
على NO
.
_vehicleReporter.locationTrackingEnabled = NO
التعامل مع أخطاء update_mask
عندما يرسل GMTDDeliveryVehicleReporter
تحديثًا عن مركبة، يمكن أن يحدث خطأ update_mask
عندما يكون القناع فارغًا، وعادةً ما يحدث ذلك مع أول تحديث بعد بدء التشغيل. يوضح المثال التالي كيفية التعامل مع هذا الخطأ:
Swift
import GoogleRidesharingDriver
class VehicleReporterListener: NSObject, GMTDVehicleReporterListener {
func vehicleReporter(
_ vehicleReporter: GMTDVehicleReporter,
didFail vehicleUpdate: GMTDVehicleUpdate,
withError error: Error
) {
let fullError = error as NSError
if let innerError = fullError.userInfo[NSUnderlyingErrorKey] as? NSError {
let innerFullError = innerError as NSError
if innerFullError.localizedDescription.contains("update_mask cannot be empty") {
emptyMaskUpdates += 1
return
}
}
failedUpdates += 1
}
override init() {
emptyMaskUpdates = 0
failedUpdates = 0
}
}
Objective-C
#import "VehicleReporterListener.h"
#import <GoogleRidesharingDriver/GoogleRidesharingDriver.h>
@implementation VehicleReporterListener {
NSInteger emptyMaskUpdates = 0;
NSInteger failedUpdates = 0;
}
- (void)vehicleReporter:(GMTDVehicleReporter *)vehicleReporter
didFailVehicleUpdate:(GMTDVehicleUpdate *)vehicleUpdate
withError:(NSError *)error {
for (NSError *underlyingError in error.underlyingErrors) {
if ([underlyingError.localizedDescription containsString:@"update_mask cannot be empty"]) {
emptyMaskUpdates += 1;
return;
}
}
failedUpdates += 1
}
@end