شروع کار با Driver SDK برای iOS، شروع به کار با Driver SDK برای iOS

Driver SDK کتابخانه ای است که در برنامه درایور خود ادغام می کنید. مسئول به روز رسانی Fleet Engine با موقعیت راننده، مسیر، مسافت باقیمانده و ETA است. همچنین با Navigation SDK که دستورالعمل‌های ناوبری گام به گام را برای راننده ارائه می‌کند، ادغام می‌شود.

کمترین سیستم مورد نیاز

  • دستگاه تلفن همراه باید دارای iOS 14 یا جدیدتر باشد.
  • Xcode نسخه 15 یا بالاتر.
  • پیش نیازها

    این راهنما فرض می‌کند که برنامه شما قبلاً Navigation SDK را پیاده‌سازی کرده است و پشتیبان Fleet Engine راه‌اندازی و در دسترس است. با این حال، کد مثال نمونه ای از نحوه راه اندازی Navigation SDK را ارائه می دهد.

    همچنین باید Maps SDK برای iOS را در پروژه Google Cloud خود فعال کنید و یک کلید API دریافت کنید .

    دسترسی داشته باشید

    اگر مشتری Google Workspace هستید، در حین ورود، یک Workspace Group مانند google-maps-platform-sdk-users@workspacedomain.com ایجاد کنید و نام آن را در اختیار Google قرار دهید. این رویکرد توصیه شده است. سپس گروه فضای کاری شما به لیست مجاز اضافه می شود که به مخازن صحیح CocoaPods دسترسی می دهد. تأیید کنید که ایمیل‌های کاربر و ایمیل‌های حساب خدماتی که نیاز به دسترسی دارند، در این لیست گنجانده شده‌اند.

    اگر سازمان شما نمی‌تواند گروه‌های فضای کاری ایجاد کند، فهرستی از ایمیل‌های حساب کاربری و خدماتی را که نیاز به دسترسی به این مصنوعات دارند، به Google ارسال کنید.

    توسعه محلی

    برای توسعه محلی، کافی است با Cloud SDK وارد شوید.

    gcloud

    gcloud auth login
    

    ایمیلی که برای ورود به سیستم استفاده می شود باید عضوی از Workspace Group باشد.

    اتوماسیون (ساخت سیستم ها یا ادغام مداوم)

    هاست های اتوماسیون خود را بر اساس بهترین روش ها تنظیم کنید:

    • اگر فرآیند شما در محیط Google Cloud اجرا می‌شود، از شناسایی خودکار اعتبار استفاده کنید.

    • در غیر این صورت، فایل کلید حساب سرویس را در مکانی امن در سیستم فایل میزبان ذخیره کنید و متغیر محیطی GOOGLE_APPLICATION_CREDENTIALS را به طور مناسب تنظیم کنید.

    ایمیل حساب سرویس مرتبط با اطلاعات کاربری باید عضو Workspace Goup باشد.

    پیکربندی پروژه

    می‌توانید 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 بروید:

      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. مخزن غلاف نسخه آلفا و بتا SDK منبع عمومی نیست. برای دسترسی به آن نسخه‌ها، با مهندس مشتری Google تماس بگیرید. مهندس حساب توسعه شما را به لیست دسترسی اضافه می کند و سپس یک کوکی برای احراز هویت تنظیم می کند .

    پس از اینکه پروژه شما در لیست دسترسی قرار گرفت، می توانید به پاد دسترسی داشته باشید.

    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 بروید:

      cd <path-to-project>
      
    3. دستور نصب pod را اجرا کنید. این API های مشخص شده در Podfile را به همراه وابستگی هایی که ممکن است داشته باشند نصب می کند.

      pod install
      
    4. Xcode را ببندید و سپس فایل xcworkspace. پروژه خود را باز کنید (دوبار کلیک کنید) تا Xcode راه اندازی شود. از این زمان به بعد باید از فایل .xcworkspace برای باز کردن پروژه استفاده کنید.

    XCFramework را نصب کنید

    XCFramework یک بسته باینری است که برای نصب Driver SDK از آن استفاده می کنید. شما می توانید از این بسته در چندین پلتفرم از جمله ماشین هایی که از چیپست M1 استفاده می کنند استفاده کنید. این راهنما نشان می دهد که چگونه XCFramework حاوی Driver SDK را به صورت دستی به پروژه خود اضافه کنید و تنظیمات ساخت خود را در Xcode پیکربندی کنید.

    باینری و منابع SDK را دانلود کنید:

    1. برای دسترسی به XCFramework و منابع، فایل های فشرده شده را باز کنید.

    2. Xcode را راه اندازی کنید و یک پروژه موجود را باز کنید یا یک پروژه جدید ایجاد کنید. اگر در iOS تازه کار هستید، یک پروژه جدید ایجاد کنید و قالب iOS App را انتخاب کنید.

    3. در صورتی که قبلاً وجود نداشته باشد، یک گروه Frameworks در زیر گروه پروژه خود ایجاد کنید.

    4. فایل gRPCCertificates.bundle دانلود شده را به دایرکتوری سطح بالای پروژه Xcode خود بکشید. هنگامی که از شما خواسته شد، در صورت نیاز، کپی موارد را انتخاب کنید.

    5. برای نصب Driver SDK، فایل GoogleRidesharingDriver.xcframework را به داخل پروژه خود در بخش Frameworks, Libraries, and Embedded Content بکشید. هنگامی که از شما خواسته شد، در صورت نیاز، کپی موارد را انتخاب کنید.

    6. GoogleRidesharingDriver.bundle دانلود شده را به دایرکتوری سطح بالای پروژه Xcode خود بکشید. هنگامی که از شما خواسته شد، Copy items if needed را انتخاب کنید.

    7. پروژه خود را از Project Navigator انتخاب کنید و هدف برنامه خود را انتخاب کنید.

    8. تب Build Phases را باز کنید و در پیوند باینری با کتابخانه‌ها، چارچوب‌ها و کتابخانه‌های زیر را در صورتی که قبلاً موجود نیستند اضافه کنید:

      • 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 را باز کنید. در بخش Other Linker Flags ، ‑ObjC هم برای رفع اشکال و هم برای انتشار اضافه کنید. اگر این تنظیمات قابل مشاهده نیستند، فیلتر موجود در نوار تنظیمات ساخت را از Basic به All تغییر دهید.

    اجرای مجوز و احراز هویت

    هنگامی که برنامه Driver شما به‌روزرسانی‌هایی را به باطن Fleet Engine ارسال می‌کند، درخواست‌ها باید شامل نشانه‌های دسترسی معتبر باشند. برای تأیید و تأیید اعتبار این درخواست‌ها، Driver 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 را با استفاده از شناسه ارائه دهنده، شناسه خودرو، driverContext و accessTokenProvider ایجاد کنید. شناسه ارائه دهنده همان شناسه پروژه Google Cloud است. و می توانید مستقیماً از API درایور به نمونه 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];
    }
    

    به صورت اختیاری به رویدادهای VehicleReporter گوش دهید

    GMTDDeliveryVehicleReporter به‌صورت دوره‌ای وسیله نقلیه را به‌روزرسانی می‌کند که locationTrackingEnabled بله است. برای پاسخ به این به روز رسانی های دوره ای، هر شی می تواند با انطباق با پروتکل GMTDVehicleReporterListener GMTDDeliveryVehicleReporter شود.

    شما می توانید رویدادهای زیر را مدیریت کنید:

    • vehicleReporter:didSucceedVehicleUpdate

      به برنامه Driver اطلاع می دهد که سرویس های پشتیبان با موفقیت موقعیت خودرو و به روز رسانی وضعیت را دریافت کردند.

    • 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 به طور خودکار به روز رسانی مسیر و ETA را نیز ارسال می کند.

    مسیری که در طول آن به‌روزرسانی‌ها تعیین می‌شود، همان مسیری است که راننده در طول جلسه ناوبری به آن پیمایش می‌کند. بنابراین، برای اینکه ردیابی محموله به درستی کار کند، نقطه بین تعیین شده از طریق -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
    

    به طور پیش فرض، فاصله گزارش دهی ثانیه است، اما فاصله گزارش را می توان با locationUpdateInterval تغییر داد. حداقل فاصله به روز رسانی پشتیبانی شده 5 ثانیه است. حداکثر فاصله به روز رسانی پشتیبانی شده 60 ثانیه است. به‌روزرسانی‌های مکرر ممکن است منجر به درخواست‌ها و خطاهای کندتر شود.

    به روز رسانی موقعیت مکانی را غیرفعال کنید

    برنامه شما می‌تواند به‌روزرسانی‌های مکان را برای یک وسیله نقلیه غیرفعال کند. به عنوان مثال، وقتی شیفت راننده به پایان می رسد، برنامه شما می تواند locationTrackingEnabled را روی NO تنظیم کند.

      _vehicleReporter.locationTrackingEnabled = NO
    

    خطاهای update_mask را مدیریت کنید

    هنگامی که GMTDDeliveryVehicleReporter یک به‌روزرسانی وسیله نقلیه ارسال می‌کند، خطای update_mask زمانی رخ می‌دهد که ماسک خالی است و معمولاً برای اولین به‌روزرسانی پس از راه‌اندازی رخ می‌دهد. مثال زیر نحوه رسیدگی به این خطا را نشان می دهد:

    سریع

    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
      }
    }
    
    

    هدف-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