ה-SDK של Drive הוא ספרייה שאתם משלבים באפליקציה לנהג. עדכון ה-Fleet Engine כולל את המיקום, המסלול, המרחק שנותר וזמן ההגעה המשוער ב-Fleet Engine. אפשר לשלב אותו גם עם ה-SDK של הניווט, שמספק לנהג הוראות ניווט מפורטות.
דרישות מערכת מינימליות
דרישות מוקדמות
במדריך הזה ההנחה היא שהאפליקציה כבר מטמיעה את ה-SDK של הניווט ושהקצה העורפי של Fleet Engine מוגדר וזמין. עם זאת, הקוד לדוגמה מספק דוגמה לאופן ההגדרה של Navigation SDK.
בנוסף, עליכם להפעיל את Maps SDK for 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.
הגדרת הפרויקט
אתם יכולים להגדיר את ה-SDK של Drive באמצעות CocoaPods.
שימוש ב-CocoaPods
כדי להגדיר את Driver SDK באמצעות CocoaPods, אתם צריכים את הפריטים הבאים:
- הכלי CocoaPods: כדי להתקין את הכלי הזה, פותחים את Terminal ומריצים את הפקודה הבאה.
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: כדי להתקין את הכלי הזה, פותחים את Terminal ומריצים את הפקודה הבאה.
sudo gem install cocoapods
לפרטים נוספים, תוכלו לקרוא את המדריך לתחילת העבודה של CocoaPods.
חשבון הפיתוח שלך ברשימת הגישה ב-Google. מאגר הפודים של גרסאות האלפא והבטא של ה-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:
מחלצים את הקבצים הדחוסים כדי לגשת ל-XCFramework ולמשאבים.
מפעילים את Xcode ופותחים פרויקט קיים או יוצרים פרויקט חדש. אם זו הפעם הראשונה שאתם משתמשים ב-iOS, תוכלו ליצור פרויקט חדש ולבחור את התבנית של האפליקציה ל-iOS.
אם עדיין לא קיימת קבוצת פרויקטים, יוצרים קבוצת מסגרות בקבוצת הפרויקטים.
גוררים את קובץ
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 flags מוסיפים את
‑ObjC
לניפוי הבאגים ולשחרור הנתונים. אם ההגדרות האלה לא גלויות, משנים את המסנן בסרגל ההגדרות של Build מ-Basic (בסיסי) ל-All (הכול).
יישום הרשאה ואימות
כשאפליקציית Drive יוצרת ושולחת עדכונים לקצה העורפי של Fleet Engine, הבקשות חייבות לכלול אסימוני גישה תקפים. כדי לאשר ולאמת את הבקשות האלה, ה-SDK של Drive קורא לאובייקט את האובייקט שתואם לפרוטוקול GMTDAuthorization
. האובייקט אחראי לספק את אסימון הגישה הנדרש.
כמפתחי אפליקציות, אתם בוחרים את אופן היצירה של האסימונים. ההטמעה צריכה לספק את היכולת:
- מאחזרים אסימון גישה, כנראה בפורמט JSON, משרת HTTPS.
- ניתוח ושמירה של האסימון במטמון.
- מרעננים את האסימון כשהתוקף שלו פג.
לפרטים על האסימונים הצפויים על ידי שרת Fleet Engine, ראו יצירת JSON Web Token (JWT) להרשאה.
מזהה הספק זהה למזהה הפרויקט ב-Google Cloud. מידע נוסף זמין במדריך למשתמש של Flet 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. ה-providerID זהה למזהה הפרויקט ב-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
הוא YES. כדי להגיב לעדכונים התקופתיים האלה, כל אובייקט יכול להירשם לאירועי 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