Driver SDK הוא ספרייה שאפשר לשלב באפליקציית הנהג. באחריות ה-Fleet Engine לעדכן את מיקום הנהג, מסלול הנסיעה, המרחק שנותר וזמן ההגעה המשוער. הוא גם משתלב עם Navigation SDK, שמספק לנהג הוראות ניווט מפורטות.
דרישות מערכת מינימליות
דרישות מוקדמות
במדריך הזה יוצאים מנקודת הנחה שבאפליקציה כבר מוטמע Navigation SDK ושהקצה העורפי Fleet Engine מוגדר וזמין. אבל הקוד לדוגמה מדגים איך מגדירים את Navigation SDK.
צריך גם להפעיל את Maps SDK ל-iOS בפרויקט ב-Google Cloud ולקבל מפתח API.
קבלת גישה
אם אתם לקוחות של Google Workspace, אתם צריכים ליצור קבוצה של Workspace כמו google-maps-platform-sdk-users@workspacedomain.com
בתהליך ההצטרפות ולספק את השם ל-Google. זו הגישה המומלצת.
קבוצת Workspace תתווסף לרשימת היתרים שמעניקה גישה למאגרים הנכונים של CocoaPods. מוודאים שכתובות האימייל וכתובות האימייל של חשבונות השירות של המשתמשים שזקוקים לגישה כלולות ברשימה הזו.
אם בארגון שלכם אין אפשרות ליצור קבוצות Workspace, אפשר לשלוח ל-Google רשימה של כתובות אימייל של משתמשים וחשבונות שירות שזקוקים לגישה לפריטי המידע האלה.
פיתוח מקומי
לפיתוח מקומי, מספיק להתחבר באמצעות Cloud SDK.
gcloud
gcloud auth login
כתובת האימייל שמשמשת להתחברות חייבת להיות חברה בקבוצה ב-Workspace.
אוטומציה (פיתוח מערכות או אינטגרציה רציפה (CI)
מגדירים את המארחים לפעולות אוטומטיות לפי השיטות המומלצות:
אם התהליך פועל בסביבת Google Cloud, צריך להשתמש בזיהוי אוטומטי של פרטי כניסה.
אחרת, יש לאחסן את קובץ המפתח של חשבון השירות במיקום מאובטח במערכת הקבצים של המארח, ולהגדיר את משתנה הסביבה GOOGLE_APPLICATION_CREDENTIALS בהתאם.
כתובת האימייל של חשבון השירות שמשויכת לפרטי הכניסה צריכה להיות חברה ב-Workspace Goup.
הגדרות הפרויקט
אפשר להגדיר את Driver SDK באמצעות CocoaPods.
שימוש ב-CocoaPods
כדי להגדיר את Driver SDK באמצעות CocoaPods, צריך את הפריטים הבאים:
- הכלי CocoaPods: כדי להתקין את הכלי, פותחים את הטרמינל ומריצים את הפקודה הבאה.
shell sudo gem install cocoapods
למידע נוסף, עיינו במדריך לתחילת העבודה של CocoaPods.
יצירת Podfile ל-Driver SDK ושימוש בו כדי להתקין את ה-API ואת יחסי התלות שלו: יוצרים קובץ בשם 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. הפעולה הזו תתקין את ממשקי ה-API שצוינו ב-Podfile, יחד עם כל יחסי התלות שיש להם.
pod install
סוגרים את Xcode ואז פותחים (לחיצה כפולה) את קובץ ה- .xcworkspace של הפרויקט כדי להפעיל את Xcode. לאחר מכן צריך להשתמש בקובץ .xcworkspace כדי לפתוח את הפרויקט.
גרסאות אלפא/בטא SDK
כדי להגדיר את גרסאות אלפא או בטא של Driver SDK ל-iOS, אתם צריכים את הפריטים הבאים:
הכלי CocoaPods: כדי להתקין את הכלי, פותחים את הטרמינל ומריצים את הפקודה הבאה.
sudo gem install cocoapods
לפרטים נוספים, עיינו במדריך לתחילת העבודה של CocoaPods.
חשבון הפיתוח שלך ברשימת הגישה ל-Google. מאגר ה-Pod של גרסאות האלפא והבטא של ה-SDK הוא לא מקור ציבורי. כדי לקבל גישה לגרסאות האלה, צריך לפנות למהנדסי הלקוחות של Google. המהנדס מוסיף את חשבון הפיתוח שלכם לרשימת הגישה ואז מגדיר קובץ Cookie לאימות.
אחרי שהפרויקט יופיע ברשימת הגישה, תוכלו לגשת ל-Pod.
יוצרים קובץ Podfile ל-Driver SDK ל-iOS ולהשתמש בו כדי להתקין את ה-API ואת יחסי התלות שלו: יוצרים קובץ בשם 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. הפעולה הזו תתקין את ממשקי ה-API שצוינו ב-Podfile, יחד עם כל יחסי התלות שיש להם.
pod install
סוגרים את Xcode ואז פותחים (לחיצה כפולה) את קובץ ה- .xcworkspace של הפרויקט כדי להפעיל את Xcode. לאחר מכן צריך להשתמש בקובץ .xcworkspace כדי לפתוח את הפרויקט.
התקנת ה-XCFramework
XCFramework היא חבילה בינארית שבה משתמשים כדי להתקין את Driver SDK. אפשר להשתמש בחבילה הזו בכמה פלטפורמות, כולל מכונות שמשתמשות בערכת השבבים M1. במדריך הזה מוסבר איך להוסיף לפרויקט באופן ידני את ה-XCFramework שמכיל את Driver SDK, ולקבוע את הגדרות ה-build ב-Xcode.
מורידים את הקובץ הבינארי ומשאבים של ה-SDK:
פורקים את קובצי ה-ZIP כדי לגשת ל-XCFramework ולמשאבים.
מפעילים את Xcode ופותחים פרויקט קיים, או יוצרים פרויקט חדש. אם זו הפעם הראשונה שאתם משתמשים ב-iOS, יוצרים פרויקט חדש ובוחרים את תבנית האפליקציה ל-iOS.
יוצרים קבוצת Frameworks תחת קבוצת הפרויקט אם היא עדיין לא קיימת.
גוררים את קובץ
gRPCCertificates.bundle
שהורדתם לספרייה ברמה העליונה של פרויקט Xcode. כשתתבקשו, בחרו באפשרות 'העתקת פריטים', אם יש צורך.כדי להתקין את Driver SDK, גוררים את הקובץ
GoogleRidesharingDriver.xcframework
אל הפרויקט בקטע Frameworks, ספריות ותוכן מוטמע. כשתתבקשו, בחרו באפשרות 'העתקת פריטים', אם יש צורך.גוררים את הקובץ
GoogleRidesharingDriver.bundle
שהורדתם לספרייה ברמה העליונה של פרויקט Xcode. כשמופיעה בקשה, בוחרים באפשרותCopy items if needed
.בוחרים את הפרויקט מ-Project Navigator ובוחרים את יעד האפליקציה.
פותחים את הכרטיסייה Build Phases (שלבי פיתוח), ובקטע Link Binary with Libraries (קישור בינארי עם ספריות), מוסיפים את ה-frameworks והספריות הבאות אם הן עדיין לא קיימות:
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
בוחרים את הפרויקט ולא יעד ספציפי ופותחים את הכרטיסייה Build Settings (הגדרות Build). בקטע Other Linker Banners (סימונים של מקשר אחר), מוסיפים את
‑ObjC
גם לניפוי באגים וגם לתוכנית ההפצה. אם ההגדרות האלה לא מוצגות, משנים את המסנן בסרגל הגדרות Build מ-בסיסי להכול.
בדיקת קובץ מניפסט הפרטיות של Apple
Apple דורשת פרטים לגבי הפרטיות של אפליקציות ב-App Store. עדכונים ומידע נוסף זמינים בדף פרטי הפרטיות של Apple App Store.
קובץ מניפסט הפרטיות של Apple כלול בחבילת המשאבים של ה-SDK. כדי לוודא שקובץ מניפסט הפרטיות נכלל וכדי לבדוק את התוכן שלו, יש ליצור ארכיון של האפליקציה ולהפיק דוח פרטיות מהארכיון.
הטמעת הרשאה ואימות
כשאפליקציית Drive יוצרת ושולחת עדכונים לקצה העורפי של Fleet Engine, הבקשות צריכות לכלול אסימוני גישה תקפים. כדי לאשר ולאמת את הבקשות האלה, Driver SDK קורא לאובייקט בהתאם לפרוטוקול GMTDAuthorization
. האובייקט אחראי לספק את אסימון הגישה הנדרש.
כמפתחי האפליקציה, אתם בוחרים איך האסימונים נוצרים. ההטמעה צריכה לאפשר לכם לבצע את הפעולות הבאות:
- מאחזרים אסימון גישה משרת HTTPS, כנראה בפורמט JSON.
- ניתוח האסימון ושמירה שלו במטמון.
- צריך לרענן את האסימון כשהתוקף שלו יפוג.
במאמר יצירת אסימון אינטרנט מסוג JSON (JWT) לצורך הרשאה תוכלו לקרוא פרטים נוספים על האסימונים הנדרשים לשרת Fleet Engine.
מזהה הספק זהה למזהה הפרויקט ב-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, driveContext ו-accessTokenProvider. מזהה הספק זהה למזהה הפרויקט ב-Google Cloud. בנוסף, אפשר לגשת למכונה GMTDDeliveryVehicleReporter
ישירות מה-API של מנהל ההתקן.
הדוגמה הבאה יוצרת מכונה של 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];
}
אפשר להאזין לאירועים של VehicleReporter
מערכת GMTDDeliveryVehicleReporter
מעדכנת את הרכב מדי פעם כשהערך של locationTrackingEnabled
מופעל. כדי להגיב לעדכונים התקופתיים האלה, כל אובייקט יכול להירשם לאירועי GMTDDeliveryVehicleReporter
באמצעות תאימות לפרוטוקולGMTDVehicleReporterListener
.
אתם יכולים לטפל באירועים הבאים:
vehicleReporter:didSucceedVehicleUpdate
מודיעה לאפליקציית הנהג על כך ששירותי הקצה העורפי קיבלו בהצלחה את מיקום הרכב ואת עדכון המצב.
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