Pakiet Driver SDK to biblioteka zintegrowana z aplikacją sterownika. Odpowiada za aktualizowanie Fleet Engine o lokalizację kierowcy, trasę, pozostały dystans i szacowany czas dotarcia. Integruje się też z pakietem Navigation SDK, który zawiera szczegółowe instrukcje nawigacji dla kierowcy.
Minimalne wymagania systemowe
Wymagania wstępne
W tym przewodniku zakładamy, że Twoja aplikacja korzysta już z nawigacji SDK oraz że backend Fleet Engine jest skonfigurowany i dostępny. Ten przykładowy kod pokazuje jednak, jak skonfigurować pakiet SDK nawigacji.
Musisz też włączyć w projekcie Google Cloud pakiet SDK Map Google na iOS i uzyskać klucz interfejsu API.
Uzyskaj dostęp
Jeśli jesteś klientem Google Workspace, podczas rejestracji utwórz grupę dyskusyjną Workspace, na przykład google-maps-platform-sdk-users@workspacedomain.com
, i podaj jej nazwę. To zalecana metoda.
Twoja grupa Workspace zostanie dodana do listy dozwolonych, która zapewnia dostęp do odpowiednich repozytoriów CocoaPods. Upewnij się, że adresy e-mail użytkowników i konta usługi, które wymagają dostępu, znajdują się na tej liście.
Jeśli Twoja organizacja nie może tworzyć grup Workspace, wyślij do Google listę adresów e-mail użytkowników i kont usługi, którzy potrzebują dostępu do tych artefaktów.
Programowanie lokalne
W przypadku programowania lokalnego wystarczy zalogować się za pomocą pakietu SDK Cloud.
gcloud
gcloud auth login
Adres e-mail używany do logowania musi należeć do grupy Workspace.
Automatyzacja (systemy tworzenia systemów lub ciągłej integracji)
Skonfiguruj hosty automatyzacji zgodnie ze sprawdzonymi metodami:
Jeśli proces działa w środowisku Google Cloud, użyj automatycznego wykrywania danych logowania.
W przeciwnym razie zapisz plik klucza konta usługi w bezpiecznej lokalizacji w systemie plików hosta i odpowiednio ustaw zmienną środowiskową GOOGLE_APPLICATION_CREDENTIALS.
Adres e-mail konta usługi powiązany z danymi logowania musi należeć do grupy Workspace.
Konfiguracja projektu
Możesz skonfigurować pakiet SDK sterownika za pomocą CocoaPods.
Korzystanie z CocoaPods
Aby skonfigurować pakiet SDK sterownika za pomocą CocoaPods, potrzebujesz tych elementów:
- Narzędzie CocoaPods: aby zainstalować to narzędzie, otwórz terminal i uruchom to polecenie.
shell sudo gem install cocoapods
Więcej informacji znajdziesz w przewodniku dla początkujących na temat CocoaPods.
Utwórz plik Podfile dla pakietu Driver SDK i użyj go do zainstalowania interfejsu API i jego zależności: utwórz w katalogu projektu plik o nazwie Podfile. Ten plik określa zależności w projekcie. Edytuj plik Podfile i dodaj zależności. Oto przykład uwzględniający zależności:
source "https://github.com/CocoaPods/Specs.git" target 'YOUR_APPLICATION_TARGET_NAME_HERE' do pod 'GoogleRidesharingDriver' end
Zapisz plik Podfile. Otwórz terminal i przejdź do katalogu z plikiem Podfile:
cd <path-to-project>
Uruchom polecenie instalacji podów. Spowoduje to zainstalowanie interfejsów API określonych w pliku Podfile oraz wszystkich ich zależności.
pod install
Zamknij Xcode, a następnie otwórz (dwukrotnie) plik .xcworkspace swojego projektu, by uruchomić Xcode. Od tej pory projekt będzie można otwierać tylko za pomocą pliku .xcworkspace.
Wersje pakietu SDK alfa i beta
Aby skonfigurować wersję alfa lub beta pakietu Driver SDK na iOS, potrzebujesz tych elementów:
Narzędzie CocoaPods: aby zainstalować to narzędzie, otwórz terminal i uruchom to polecenie.
sudo gem install cocoapods
Więcej informacji znajdziesz w przewodniku dla początkujących.
Twoje konto programisty jest na liście dostępu Google. Repozytorium poda wersji alfa i beta pakietu SDK nie jest publicznym źródłem. Aby uzyskać dostęp do tych wersji, skontaktuj się z inżynierem Google ds. obsługi klienta. Inżynier dodaje Twoje konto dewelopera do listy dostępu, a następnie ustawia plik cookie do uwierzytelniania.
Gdy projekt znajdzie się na liście dostępu, uzyskasz dostęp do poda.
Utwórz plik Podfile dla pakietu Driver SDK na iOS i użyj go do zainstalowania interfejsu API i jego zależności: utwórz w katalogu projektu plik o nazwie Podfile. Ten plik określa zależności w projekcie. Edytuj plik Podfile i dodaj zależności. Oto przykład uwzględniający zależności:
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
Zapisz plik Podfile. Otwórz terminal i przejdź do katalogu z plikiem Podfile:
cd <path-to-project>
Uruchom polecenie instalacji podów. Spowoduje to zainstalowanie interfejsów API określonych w pliku Podfile oraz wszystkich ich zależności.
pod install
Zamknij Xcode, a następnie otwórz (dwukrotnie) plik .xcworkspace swojego projektu, by uruchomić Xcode. Od tej pory projekt będzie można otwierać tylko za pomocą pliku .xcworkspace.
Wdrażanie autoryzacji i uwierzytelniania
Gdy aplikacja sterownika generuje i wysyła aktualizacje do backendu Fleet Engine, żądania muszą zawierać prawidłowe tokeny dostępu. Aby autoryzować i uwierzytelnić te żądania, pakiet SDK sterownika wywołuje obiekt zgodnie z protokołem GMTDAuthorization
. Obiekt odpowiada za udostępnienie wymaganego tokena dostępu.
Jako deweloper aplikacji możesz wybrać sposób generowania tokenów. Implementacja powinna umożliwiać:
- Wygeneruj token dostępu w formacie JSON z serwera HTTPS.
- Przeanalizuj i zapisz token w pamięci podręcznej.
- Odśwież token, gdy straci ważność.
Informacje o tokenach, których oczekuje serwer Fleet Engine, znajdziesz w sekcji Tworzenie tokena internetowego JSON (JWT) do autoryzacji.
Identyfikator dostawcy jest taki sam jak identyfikator projektu Google Cloud. Więcej informacji znajdziesz w przewodniku użytkownika interfejsu API Fleet Engine Deliveries.
Oto przykład implementowania dostawcy tokena dostępu:
#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
Tworzenie instancji DeliveryDriverAPI
Aby pobrać instancję GMTDDeliveryVehicleReporter
, musisz najpierw utworzyć instancję GMTDDeliveryDriverAPI
przy użyciu identyfikatorów providerID, vehicleID, sterownikContext i accessTokenProvider. Identyfikator dostawcy jest taki sam jak identyfikator projektu Google Cloud. Instancja GMTDDeliveryVehicleReporter
jest też dostępna bezpośrednio z poziomu interfejsu API sterownika.
Ten przykład tworzy instancję 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];
}
Opcjonalnie nasłuchiwanie zdarzeń VehicleReporter
GMTDDeliveryVehicleReporter
okresowo aktualizuje pojazd, gdy
locationTrackingEnabled
ma wartość YES (TAK). Aby móc reagować na te okresowe aktualizacje, każdy obiekt może subskrybować zdarzenia GMTDDeliveryVehicleReporter
zgodnie z protokołem GMTDVehicleReporterListener
.
Możesz obsługiwać te zdarzenia:
vehicleReporter:didSucceedVehicleUpdate
Informuje aplikację sterownika, że usługi backendu pomyślnie otrzymały aktualizację lokalizacji i stanu pojazdu.
vehicleReporter:didFailVehicleUpdate:withError
Informuje detektor, że aktualizacja pojazdu nie powiodła się. Dopóki śledzenie lokalizacji jest włączone,
GMTDDeliveryVehicleReporter
nadal wysyła najnowsze dane do backendu Fleet Engine.
Ten przykład obsługuje te zdarzenia:
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
Włącz śledzenie lokalizacji
Aby włączyć śledzenie lokalizacji, ustaw locationTrackingEnabled
na YES
w aplikacji GMTDDeliveryVehicleReporter
. Następnie GMTDDeliveryVehicleReporter
=
automatycznie wysyła aktualizacje lokalizacji. Gdy GMSNavigator
jest w trybie nawigacji (gdy miejsce docelowe jest ustawione na setDestinations
), a locationTrackingEnabled
ma wartość YES
, GMTDDeliveryVehicleReporter
automatycznie wysyła też informacje o trasie i szacowanym czasie dotarcia na miejsce.
Trasa ustawiona podczas tych aktualizacji będzie tą samą trasą, którą kierowca porusza się podczas sesji nawigacji. Aby śledzenie przesyłki działało prawidłowo, punkt pośredni ustawiony w -setDestinations:callback:
powinien być zgodny z miejscem docelowym ustawionym w backendzie Fleet Engine.
Ten przykład umożliwia włączenie śledzenia lokalizacji:
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
Domyślnie interwał raportowania wynosi 10 sekund, ale można go zmienić za pomocą locationUpdateInterval
. Minimalny obsługiwany interwał aktualizacji
to 5 sekund. Maksymalny obsługiwany interwał aktualizacji to 60 sekund. Częstsze aktualizacje mogą powodować wolniejsze żądania i błędy.
Wyłącz aktualizacje lokalizacji
Twoja aplikacja może wyłączyć aktualizacje lokalizacji pojazdu. Na przykład, gdy kończy się zmiana kierowcy, aplikacja może ustawić locationTrackingEnabled
na NO
.
_vehicleReporter.locationTrackingEnabled = NO
Obsługa błędów update_mask
Gdy GMTDDeliveryVehicleReporter
wysyła aktualizację pojazdu, gdy maska jest pusta, może wystąpić błąd update_mask
. Zwykle występuje on przy pierwszej aktualizacji po uruchomieniu. Z przykładu poniżej dowiesz się, jak obsłużyć ten błąd:
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