תחילת העבודה עם ה-SDK של Drive ל-iOS

Driver SDK הוא ספרייה שאפשר לשלב באפליקציה לנהגים. זה כן באחריות לעדכן את Fleet Engine במיקום של הנהג, במסלול שלו המרחק שנותר וזמן ההגעה המשוער. הוא גם משתלב עם Navigation SDK, שמספק לנהג הוראות ניווט מפורטות.

דרישות מערכת מינימליות

  • במכשיר הנייד צריכה לפעול מערכת iOS בגרסה 14 ואילך.
  • Xcode גרסה 15 ואילך.
  • דרישות מוקדמות

    המדריך הזה מניח שהאפליקציה כבר מטמיעה Navigation SDK, Fleet Engine הקצה העורפי מוגדר וזמין. אבל הקוד לדוגמה מספק דוגמה לאופן שבו מגדירים Navigation SDK.

    יש להפעיל גם את ה-SDK של מפות ל-iOS בפרויקט ב-Google Cloud וקבלת מפתח API.

    קבלת גישה

    ללקוחות של Google Workspace: קבוצת Workspace כמו google-maps-platform-sdk-users@workspacedomain.com במהלך ההצטרפות לספק את השם ל-Google. זו הגישה המומלצת. לאחר מכן, הקבוצה שלך ב-Workspace תתווסף לרשימת היתרים מעניק גישה למאגרים הנכונים של CocoaPods. אישור שהמשתמש כתובות אימייל של חשבונות שירות ואימיילים של חשבונות שירות שנדרשת להם גישה נכללות ברשימה הזו.

    אם בארגון שלך אין אפשרות ליצור קבוצות ב-Workspace, אפשר לשלוח ל-Google רשימה של אימיילים של משתמשים וחשבונות שירות שזקוקים לגישה לפריטי המידע האלה שנוצרו בתהליך הפיתוח (Artifact).

    פיתוח מקומי

    לפיתוח מקומי, מספיק להתחבר באמצעות Cloud SDK.

    gcloud

    gcloud auth login
    

    כתובת האימייל שמשמשת להתחברות חייבת להיות חברה בקבוצה ב-Workspace.

    אוטומציה (פיתוח מערכות או אינטגרציה רציפה (CI)

    מגדירים את מארחי האוטומציה בהתאם שיטות מומלצות:

    • אם התהליך פועל בסביבת Google Cloud, צריך להשתמש אוטומטית זיהוי של פרטי כניסה.

    • לחלופין, יש לאחסן את קובץ המפתח של חשבון השירות במיקום מאובטח את מערכת הקבצים של המארח ולהגדיר GOOGLE_APPLICATION_CREDENTIALS בהתאם למשתנה הסביבה.

    כתובת האימייל של חשבון השירות המשויכת לפרטי הכניסה חייבת להיות חברה ב- קבוצת Workspace.

    הגדרות הפרויקט

    אפשר להגדיר את Driver SDK באמצעות CocoaPods.

    שימוש ב-CocoaPods

    כדי להגדיר את Driver SDK באמצעות CocoaPods, צריך את הפריטים הבאים:

    • הכלי CocoaPods: כדי להתקין את הכלי הזה, פותחים את Terminal ומפעילים את הפקודה הבאה. shell sudo gem install cocoapods עיינו ב מדריך לתחילת העבודה של CocoaPods אפשר לקבל פרטים נוספים.
    1. יוצרים Podfile ל-Driver SDK ומשתמשים בו כדי להתקין את API ויחסי התלות שלו: יוצרים קובץ בשם Podfile בפרויקט הקובץ הזה מגדיר את יחסי התלות של הפרויקט. עריכת ה-Podfile ולהוסיף את יחסי התלות. כאן יש דוגמה שכוללת את של יחסי התלות:

      source "https://github.com/CocoaPods/Specs.git"
      
      target 'YOUR_APPLICATION_TARGET_NAME_HERE' do
        pod 'GoogleRidesharingDriver'
      end
      
    2. שומרים את ה-Podfile. פותחים טרמינל ועוברים לספרייה שמכילה את Podfile:

      cd <path-to-project>
      
    3. מריצים את פקודת ההתקנה של pod. הפעולה הזו תתקין את ממשקי ה-API שצוינו Podfile, יחד עם כל יחסי התלות שיש להם.

      pod install
      
    4. סוגרים את Xcode ואז פותחים (לחיצה כפולה) את קובץ ה- .xcworkspace של הפרויקט כדי להפעיל את Xcode. מהשלב הזה ואילך צריך להשתמש בקובץ .xcworkspace כדי לפתוח את הפרויקט.

    גרסאות אלפא/בטא SDK

    כדי להגדיר את גרסאות אלפא או בטא של Driver SDK ל-iOS, צריך הפריטים הבאים:

    • הכלי CocoaPods: כדי להתקין את הכלי הזה, פותחים את Terminal ומפעילים את הפקודה הבאה.

      sudo gem install cocoapods
      

      עיינו ב מדריך לתחילת העבודה של CocoaPods אפשר לקבל פרטים נוספים.

    • חשבון הפיתוח שלך ברשימת הגישה ל-Google. מאגר ה-Pod מגרסאות האלפא והבטא של ה-SDK הן לא מקור ציבורי. שפת תרגום כדי לגשת לגרסאות האלה, צריך ליצור קשר עם מהנדס בתחום הלקוחות של Google. המהנדס מוסיף את חשבון הפיתוח שלך לרשימת הגישה ואז מגדיר קובץ Cookie בשביל אימות.

    אחרי שהפרויקט יופיע ברשימת הגישה, תוכלו לגשת ל-Pod.

    1. יצירת 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
      
    2. שומרים את ה-Podfile. פותחים טרמינל ועוברים לספרייה שמכילה את הפקודה Podfile:

      cd <path-to-project>
      
    3. מריצים את פקודת ההתקנה של pod. הפעולה הזו תתקין את ממשקי ה-API שצוינו Podfile, יחד עם כל יחסי התלות שיש להם.

      pod install
      
    4. סוגרים את Xcode ואז פותחים (לחיצה כפולה) את קובץ ה- .xcworkspace של הפרויקט כדי להפעיל את Xcode. מהשלב הזה ואילך צריך להשתמש בקובץ .xcworkspace כדי לפתוח את הפרויקט.

    התקנת ה-XCFramework

    XCFramework היא חבילה בינארית שבה משתמשים כדי להתקין את Driver SDK. אפשר להשתמש בחבילה הזו בכמה פלטפורמות, כולל מכונות שמשתמשות בערכת השבבים M1. במדריך הזה מוסבר איך להוסיף לפרויקט באופן ידני את ה-XCFramework שמכיל את Driver SDK, ולקבוע את הגדרות ה-build ב-Xcode.

    מורידים את הקובץ הבינארי ומשאבים של ה-SDK:

    1. פורקים את קובצי ה-ZIP כדי לגשת ל-XCFramework ולמשאבים.

    2. מפעילים את Xcode ופותחים פרויקט קיים, או יוצרים פרויקט חדש. אם זו הפעם הראשונה שאתם משתמשים ב-iOS, יוצרים פרויקט חדש ובוחרים את תבנית האפליקציה ל-iOS.

    3. יוצרים קבוצת Frameworks תחת קבוצת הפרויקט אם היא עדיין לא קיימת.

    4. גוררים את קובץ gRPCCertificates.bundle שהורדתם לספרייה ברמה העליונה של פרויקט Xcode. כשתתבקשו, בחרו באפשרות 'העתקת פריטים', אם יש צורך.

    5. כדי להתקין את Driver SDK, גוררים את הקובץ GoogleRidesharingDriver.xcframework אל הפרויקט בקטע Frameworks, ספריות ותוכן מוטמע. כשתתבקשו, בחרו באפשרות 'העתקת פריטים', אם יש צורך.

    6. גוררים את הקובץ GoogleRidesharingDriver.bundle שהורדתם לספרייה ברמה העליונה של פרויקט Xcode. כשמופיעה בקשה, בוחרים באפשרות Copy items if needed.

    7. בוחרים את הפרויקט מ-Project Navigator ובוחרים את יעד האפליקציה.

    8. פותחים את הכרטיסייה 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
    9. בוחרים את הפרויקט ולא יעד ספציפי ופותחים את הכרטיסייה Build Settings (הגדרות Build). בקטע Other Linker Banners (סימונים של מקשר אחר), מוסיפים את ‑ObjC גם לניפוי באגים וגם לתוכנית ההפצה. אם ההגדרות האלה לא מוצגות, משנים את המסנן בסרגל הגדרות Build מ-בסיסי להכול.

    בדיקת קובץ מניפסט הפרטיות של Apple

    Apple דורשת פרטים לגבי הפרטיות של אפליקציות ב-App Store. עדכונים ומידע נוסף זמינים בדף פרטי הפרטיות של Apple App Store.

    קובץ מניפסט הפרטיות של Apple כלול בחבילת המשאבים של ה-SDK. כדי לוודא שקובץ מניפסט הפרטיות נכלל וכדי לבדוק את התוכן שלו, יש ליצור ארכיון של האפליקציה ולהפיק דוח פרטיות מהארכיון.

    הטמעת הרשאה ואימות

    כשאפליקציית Drive יוצרת ושולחת עדכונים לקצה העורפי של Fleet Engine, הבקשות חייבות לכלול אסימוני גישה תקפים. כדי לאשר לאמת את הבקשות האלה, ה-SDK של מנהל התקן קורא לאובייקט שעומד בדרישות של GMTDAuthorization של Google. האובייקט אחראי לספק את אסימון הגישה הנדרש.

    כמפתחי האפליקציה, אתם בוחרים איך האסימונים נוצרים. ההטמעה שלך צריכה להיות יכולת לבצע את הפעולות הבאות:

    • מאחזרים אסימון גישה משרת HTTPS, כנראה בפורמט JSON.
    • ניתוח האסימון ושמירה שלו במטמון.
    • צריך לרענן את האסימון כשהתוקף שלו יפוג.

    ניתן למצוא פרטים על האסימונים שנדרשים על ידי שרת 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, carID, 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 היא כן. כדי להגיב לעדכונים התקופתיים האלה, האובייקט יכול להירשם לאירועי 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