Primeiros passos com o SDK do driver para iOS

O SDK do Driver é uma biblioteca que você integra ao seu app do driver. É responsável por atualizar o Fleet Engine com a localização, rota, distância restante e HEC. Ele também se integra ao SDK do Navigation, que fornece instruções de navegação guiada para o motorista.

Requisitos mínimos do sistema

  • O dispositivo móvel precisa ter o iOS 14 ou mais recente.
  • Xcode (em inglês) versão 15 ou mais recente.
  • Pré-requisitos

    Este guia presume que seu app já implementa o SDK do Navigation e que o Mecanismo de frota está configurado e disponível. No entanto, o código de exemplo fornece um exemplo de como configurar SDK do Navigation:

    Também é necessário ativar o SDK do Maps para iOS. no projeto do Google Cloud e Gerar uma chave de API.

    Desenvolvimento local

    Para desenvolvimento local, basta fazer login com a SDK Cloud.

    gcloud

    gcloud auth login
    

    O e-mail usado para fazer login precisa ser membro do grupo do espaço de trabalho.

    Automação (sistemas de build ou integração contínua)

    Configure os hosts de automação de acordo com práticas recomendadas:

    • Caso seu processo seja executado em um ambiente do Google Cloud, use automático detecção de credenciais.

    • Caso contrário, armazene o arquivo de chave da conta de serviço em um local seguro no sistema de arquivos do host e defina GOOGLE_APPLICATION_CREDENTIALS a variável de ambiente apropriada.

    O e-mail da conta de serviço associado às credenciais precisa ser um membro de do Workspace.

    Configuração do projeto

    Gerenciador de pacotes do Swift

    O SDK do Driver pode ser instalado via Gerenciador de pacotes do Swift (em inglês). Para adicionar o SDK, verifique se você tem removeu todas as dependências atuais do SDK do Driver.

    Para adicionar o SDK a um projeto novo ou existente, siga estas etapas:

    1. Abra seu Xcode project ou workspace e acesse File > Adicionar dependências de pacote.
    2. Digite https://github.com/googlemaps/ios-driver-sdk como o URL e pressione Enter. para extrair o pacote e clicar em "Adicionar pacote".
    3. Para instalar um version específico, defina o campo Regra de dependência como um dos as opções baseadas em versão. Para novos projetos, recomendamos especificar a versão mais recente e usando a "versão exata" é a melhor opção. Quando terminar, clique em "Adicionar pacote".
    4. Na janela Choose Package Products, verifique se GoogleRidesharingDriver será adicionado a sua meta de main designada. Quando terminar, clique em "Adicionar pacote".
    5. Para verificar sua instalação, navegue até o painel General do destino. Em Frameworks, bibliotecas e conteúdo incorporado, você verá os pacotes instalados. Também é possível consultar a página "Package Dependencies" do "Navegador do projeto" para verificar o pacote e sua versão.

    Para atualizar o package de um projeto existente, siga estas etapas:

    1. Se você estiver fazendo upgrade de uma versão anterior à 9.0.0, será necessário remover das seguintes dependências: GoogleMapsBase, GoogleMapsCore e GoogleMapsM4B após o upgrade. Não remova a dependência de GoogleMaps: Para mais informações, consulte a Notas de lançamento da versão 9.0.0.

      Nas configurações do seu projeto do Xcode, localize Frameworks, bibliotecas, e conteúdo incorporado. Use o sinal de menos(-) para remover o seguinte framework:

      • GoogleMapsBase (apenas para upgrades de versões anteriores à 9.0.0)
      • GoogleMapsCore (apenas para upgrades de versões anteriores à 9.0.0)
      • GoogleMapsM4B (apenas para upgrades de versões anteriores à 9.0.0)
    2. No Xcode, vá para "File > Pacotes > Atualize para as versões mais recentes do pacote".
    3. Para verificar a instalação, vá para a seção Package Dependencies do Project Navigator para verificar o pacote e sua versão.
    .

    Para remover as dependências atuais do SDK do Driver adicionadas usando CocoaPods, siga estas etapas:

    1. Feche seu espaço de trabalho do Xcode. Abra o terminal e execute o seguinte comando:
      sudo gem install cocoapods-deintegrate cocoapods-clean 
      pod deintegrate 
      pod cache clean --all
    2. Remova Podfile, Podfile.resolved e Xcode workspace, se você não estiver usando para algo diferente do CocoaPods.

    Para remover o SDK do Driver atual instalado manualmente, siga estas etapas:

    1. Nas configurações do projeto do Xcode, localize Frameworks, bibliotecas e conteúdo incorporado. Use o sinal de menos(-) para remover a seguinte estrutura:

      • GoogleRidesharingDriver.xcframework
    2. No diretório de nível superior do seu projeto Xcode, remova o Pacote GoogleRidesharingDriver.

    CocoaPods

    Para configurar o SDK do driver usando o CocoaPods, são necessários os seguintes itens:

    • Ferramenta CocoaPods: para instalar esta ferramenta, abra o terminal e execute a comando a seguir.
       sudo gem install cocoapods
    
    1. Crie um Podfile para o SDK do Driver e use-o para instalar a API e as dependências: crie um arquivo chamado Podfile no diretório do projeto. Esse arquivo define as dependências do seu projeto. Edite o Podfile e adicione suas dependências. Confira um exemplo que inclui as dependências:

      source "https://github.com/CocoaPods/Specs.git"
      
      target 'YOUR_APPLICATION_TARGET_NAME_HERE' do
        pod 'GoogleRidesharingDriver'
      end
      

      Este é um exemplo que inclui os pods Alfa e Beta do SDK do Driver como dependências:

      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. Salve o Podfile. Abra um terminal e acesse o diretório que contém o Podfile:

      cd <path-to-project>
      
    3. Execute o comando "pod install". Isso instalará as APIs especificadas no o Podfile e as respectivas dependências.

      pod install
      
    4. Feche o Xcode e clique duas vezes no arquivo .xcworkspace do seu projeto. para iniciar o Xcode. A partir desse momento, você vai precisar usar o arquivo .xcworkspace para abrir o projeto.

    .

    Consulte os Primeiros passos do CocoaPods guia para saber mais detalhes.

    Instalação manual

    Um XCFramework é um pacote binário usado para instalar a SDK do Driver. Você pode usar esse pacote em várias plataformas, incluindo máquinas que usam Apple Silicon. Este guia mostra como adicione manualmente o XCFramework que contém SDK do Driver ao projeto e configure o build de configuração no Xcode.

    Faça o download do binário e dos recursos do SDK:

    1. Extraia os arquivos para acessar o XCFramework e os recursos.

    2. Inicie o Xcode e abra um projeto existente ou crie um novo projeto. Se você não tem experiência com o iOS, crie um novo projeto e selecione a Modelo de app.

    3. Criar um grupo do Frameworks no grupo do projeto, se não houver um já.

    4. Para instalar o SDK do Driver, arraste o GoogleRidesharingDriver.xcframework ao seu projeto em Frameworks, bibliotecas e conteúdo incorporado. Quando solicitado, selecione Copie os itens, se necessário.

    5. Arraste o arquivo GoogleRidesharingDriver.bundle baixado para o nível superior do projeto do Xcode. Quando solicitado, selecione Copy items if needed.

    6. Selecione seu projeto no Project Navigator e escolha seu de destino do aplicativo.

    7. Abra a guia "Fases de build" e, em "Vincular binário com bibliotecas", adicione a seguintes frameworks e bibliotecas, se ainda não estiverem presentes:

      • 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
    8. Escolha seu projeto, em vez de um destino específico, e abra o Build Configurações. Na seção Outras sinalizações do vinculador, adicione -ObjC para depurar e lançar. Se essas configurações não estiverem visíveis, altere filtro na barra "Build Settings" de Básico para Todos.

    Inspecionar o arquivo do Manifesto de privacidade da Apple

    A Apple exige detalhes de privacidade de apps na App Store. Acesse a página de detalhes de privacidade da App Store da Apple para atualizações e mais informações.

    O arquivo do Manifesto de privacidade da Apple está incluído no pacote de recursos do SDK. Para verificar se o arquivo do manifesto de privacidade foi incluído e inspecionar o conteúdo dele, crie um arquivo do seu app e gere um relatório de privacidade.

    Implementar autorização e autenticação

    Quando o app Driver gera e envia atualizações para o back-end do Fleet Engine, as solicitações devem incluir tokens de acesso válidos. Para autorizar e autenticar essas solicitações, o SDK do Driver chama seu objeto em conformidade com GMTDAuthorization protocolo. O objeto é responsável por fornecer o token de acesso necessário.

    Como desenvolvedor de apps, você escolhe como os tokens são gerados. Sua implementação precisa permitir as seguintes ações:

    • Busque um token de acesso, possivelmente no formato JSON, em um servidor HTTPS.
    • Analisar e armazenar em cache o token.
    • Atualizar o token quando ele expirar.

    Para detalhes sobre os tokens esperados pelo servidor do Fleet Engine, consulte Crie um JSON Web Token (JWT) para autorização.

    O ID do provedor é igual ao ID do projeto do Google Cloud. Consulte o Guia do usuário da API Fleet Engine Deliveries. para mais informações.

    O exemplo a seguir implementa um provedor de token de acesso:

    #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
    

    Criar uma instância DeliveryDriverAPI

    Para acessar uma instância do GMTDDeliveryVehicleReporter, primeiro você precisa criar um GMTDDeliveryDriverAPI usando o providerID, veículoID, driverContext e accessTokenProvider. O providerID é igual ao ID do projeto do Google Cloud. E você pode acessar o GMTDDeliveryVehicleReporter diretamente da API do driver.

    O exemplo a seguir cria uma instância 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];
    }
    

    Como opção, detectar eventos de VehicleReporter

    O GMTDDeliveryVehicleReporter atualiza o veículo periodicamente quando locationTrackingEnabled é SIM. Para responder a essas atualizações periódicas, quaisquer pode se inscrever em eventos GMTDDeliveryVehicleReporter em conformidade com usando o protocolo GMTDVehicleReporterListener.

    É possível processar os seguintes eventos:

    • vehicleReporter:didSucceedVehicleUpdate

      Informa ao app Driver que os serviços de back-end receberam os atualização de estado e localização do veículo.

    • vehicleReporter:didFailVehicleUpdate:withError

      Informa o listener que houve uma falha na atualização do veículo. Desde que o local o acompanhamento estiver ativado, o app GMTDDeliveryVehicleReporter vai continuar enviando os dados mais recentes para o back-end do Fleet Engine.

    O exemplo a seguir lida com esses eventos:

    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
    

    Ativar rastreamento de localização

    Para ativar o rastreamento de localização, seu app pode definir locationTrackingEnabled como YES em GMTDDeliveryVehicleReporter. Então GMTDDeliveryVehicleReporter será = enviar automaticamente atualizações de localização. Quando o GMSNavigator está na navegação (quando um destino é definido por setDestinations) e locationTrackingEnabled é definido como YES, GMTDDeliveryVehicleReporter vai também enviam automaticamente atualizações de trajeto e HEC.

    O trajeto definido durante essas atualizações será o mesmo do motorista. durante a sessão de navegação. Assim, para que o rastreamento de remessas funcione, corretamente, o waypoint definido por -setDestinations:callback: deve corresponder ao definido no back-end do Fleet Engine.

    O exemplo a seguir ativa o rastreamento de localização:

    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
    

    Por padrão, o intervalo é de 10 segundos, mas pode será alterado com locationUpdateInterval. O intervalo mínimo de atualização com suporte é de 5 segundos. O intervalo máximo de atualização permitido é de 60 segundos. Mais frequente e atualizações podem resultar em solicitações e erros mais lentos.

    Desativar atualizações de localização

    Seu app pode desativar as atualizações de localização de um veículo. Por exemplo, quando um fim do turno do motorista, seu app poderá definir locationTrackingEnabled como NO.

      _vehicleReporter.locationTrackingEnabled = NO
    

    Processar erros update_mask

    Quando o GMTDDeliveryVehicleReporter envia uma atualização do veículo, um update_mask pode ocorrer quando a máscara está vazia e geralmente ocorre nos primeiros serão atualizados após a inicialização. O exemplo abaixo mostra como lidar com esse erro:

    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