Você pode usar o SDK do Driver para oferecer navegação e rastreamento aprimorados ao seu aplicativo Trip and Order Progress. O SDK do Driver oferece atualizações de localização de veículos e tarefas no Fleet Engine da solução de viagens e entregas sob demanda.
O SDK do Driver mantém os serviços do Fleet Engine e seus serviços personalizados cientes
da localização e do estado do veículo. Por exemplo, o veículo pode ser ONLINE
.
ou OFFLINE
, e a localização do veículo muda conforme a viagem progride.
Requisitos mínimos do sistema
O dispositivo móvel precisa ter o Android 6.0 (nível 23 da API) ou mais recente.
Configuração do build e das dependências
As versões 4.99 e mais recentes do SDK do driver estão disponíveis no repositório Maven do Google.
Gradle
Adicione a instrução a seguir ao seu arquivo build.gradle
:
repositories {
...
google()
}
Maven
Adicione a instrução a seguir ao seu arquivo pom.xml
:
<project>
...
<repositories>
<repository>
<id>google-maven-repository</id>
<url>https://maven.google.com</url>
</repository>
</repositories>
...
</project>
Configuração do projeto
Para usar o SDK do Driver, seu app precisa ser direcionado
minSdkVersion
23 ou mais recente.
Para executar um app criado com o SDK do Driver, o Android dispositivo deve ter Google Play Services instalado.
Configurar seu projeto de desenvolvimento
Como configurar seu projeto de desenvolvimento e gerar uma chave de API para o projeto no console do Google Cloud:
Crie um novo projeto do console do Google Cloud ou selecione um projeto atual para usar com o SDK do Driver. Aguarde alguns minutos até o novo projeto fica visível no console do Google Cloud.
Para executar o app de demonstração, seu projeto precisa ter acesso ao SDK do Maps. para Android. No console do Google Cloud, selecione APIs e Serviços > Library, pesquise e ative o SDK do Maps para Android
Receba uma chave de API para o projeto selecionando APIs e Serviços > Credenciais > Criar credenciais > Chave de API. Para mais informações sobre como acessar uma chave de API, consulte Gere uma chave de API.
Adicionar o SDK do Driver ao app
O SDK do Driver está disponível no repositório Maven do Google. O inclui os arquivos .pom (Project Object Model) do SDK e Javadocs. Para adicionar o SDK do Driver ao app:
Adicione a seguinte dependência à sua configuração do Gradle ou Maven, substituindo " O marcador
VERSION_NUMBER
para a versão desejada do SDK do driver.Gradle
Adicione o seguinte ao seu
build.gradle
:dependencies { ... implementation 'com.google.android.libraries.mapsplatform.transportation:transportation-driver:VERSION_NUMBER' }
Maven
Adicione o seguinte ao seu
pom.xml
:<dependencies> ... <dependency> <groupId>com.google.android.libraries.mapsplatform.transportation</groupId> <artifactId>transportation-driver</artifactId> <version>VERSION_NUMBER</version> </dependency> </dependencies>
O SDK do Driver depende do SDK do Navigation. Essa dependência é configurada de uma de modo que, se uma versão específica do SDK do Navigation for necessária, ela será explicitamente definido no arquivo de configuração do build, da seguinte maneira: a omissão do bloco de código mencionado permitirá que o projeto sempre faça o download a versão mais recente do SDK do Navigation na versão de lançamento principal; Observe que os comportamentos combinados das versões mais recentes do SDK do Driver e O SDK do Navigation foi submetido a testes rigorosos antes do lançamento.
Organizar a configuração de dependências dos aplicativos de desenvolvimento e versão de acordo com os ambientes.
Gradle
Adicione o seguinte ao seu
build.gradle
:dependencies { ... implementation 'com.google.android.libraries.navigation:navigation:5.0.0' }
Maven
Adicione o seguinte ao seu
pom.xml
:<dependencies> ... <dependency> <groupId>com.google.android.libraries.navigation</groupId> <artifactId>navigation</artifactId> <version>5.0.0</version> </dependency> </dependencies>
Adicionar a chave de API ao seu app
Depois de adicionar o SDK do Driver ao app, inclua a chave de API. Você precisa usar a chave de API do projeto que você recebeu quando configure seu projeto de desenvolvimento.
Esta seção descreve como armazenar sua chave de API para que ela seja mais segura
referenciadas pelo seu app. Não inclua a chave de API na sua versão
de controle de acesso. Ele será armazenado no arquivo local.properties
, que é
localizado no diretório raiz do seu projeto. Para mais informações sobre o
local.properties
, consulte
Arquivos de propriedades do Gradle.
Para otimizar essa tarefa, use o Plug-in Secrets Gradle para Android (em inglês).
Para instalar o plug-in e armazenar sua chave de API, siga estas instruções:
Abra seu arquivo
build.gradle
no nível raiz e adicione o seguinte código ao Elementodependencies
embuildscript
.Groovy
buildscript { dependencies { // ... classpath "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.0" } }
Kotlin
buildscript { dependencies { // ... classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.0") } }
Abra o arquivo
build.gradle
no nível do app e adicione o seguinte código aoplugins
.Groovy
id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
Kotlin
id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
Se você usa o Android Studio, sincronizar seu projeto com o Gradle.
Abra o
local.properties
no diretório do nível do projeto e adicione o código a seguir. SubstituaYOUR_API_KEY
pela sua chave de API.MAPS_API_KEY=YOUR_API_KEY
No seu arquivo
AndroidManifest.xml
, acessecom.google.android.geo.API_KEY
e atualize o atributoandroid:value
desta forma:<meta-data android:name="com.google.android.geo.API_KEY" android:value="${MAPS_API_KEY}" />
O exemplo a seguir mostra um manifesto completo para um app de exemplo:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.driverapidemo">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/_AppTheme">
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="${MAPS_API_KEY}" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Incluir as atribuições necessárias no seu app
Se você usa o SDK do Driver no app, é necessário incluir texto de atribuição e licenças de código aberto como parte dos avisos legais do seu app nesta seção. É melhor incluir as atribuições como um item de menu independente ou como no item de menu Sobre.
As informações sobre as licenças podem ser encontradas em "third_party_licenses.txt" arquivo no o arquivo AAR desarquivado.
Consulte https://developers.google.com/android/guides/opensource sobre como incluir avisos de código aberto.
Dependências
Se você usa o ProGuard para otimizar suas compilações, pode ser necessário adicionar as seguintes linhas ao seu ProGuard de configuração do Terraform:
-dontwarn com.google.**
-dontwarn okio.**
O nível mínimo de API com suporte é 23.
Initializing the SDK
Um ID de provedor (geralmente o ID do projeto do Google Cloud) é necessário para
inicializar o objeto DriverContext
. Para mais detalhes sobre como configurar
projeto do Google Cloud, consulte
Autenticação e autorização.
Antes de usar o SDK do Driver, primeiro é necessário inicializar SDK do Navigation. Para iniciar o SDK:
Consiga um objeto
Navigator
doNavigationApi
.Java
NavigationApi.getNavigator( this, // Activity new NavigationApi.NavigatorListener() { @Override public void onNavigatorReady(Navigator navigator) { // Keep a reference to the Navigator (used to configure and start nav) this.navigator = navigator; } } );
Kotlin
NavigationApi.getNavigator( this, // Activity object : NavigatorListener() { override fun onNavigatorReady(navigator: Navigator) { // Keep a reference to the Navigator (used to configure and start nav) this@myActivity.navigator = navigator } }, )
Crie um objeto
DriverContext
, preenchendo os campos obrigatórios.Java
DriverContext driverContext = DriverContext.builder(application) .setProviderId(providerId) .setVehicleId(vehicleId) .setAuthTokenFactory(authTokenFactory) .setNavigator(navigator) .setRoadSnappedLocationProvider( NavigationApi.getRoadSnappedLocationProvider(application)) .build();
Kotlin
val driverContext = DriverContext.builder(application) .setProviderId(providerId) .setVehicleId(vehicleId) .setAuthTokenFactory(authTokenFactory) .setNavigator(navigator) .setRoadSnappedLocationProvider(NavigationApi.getRoadSnappedLocationProvider(application)) .build()
Use o objeto
DriverContext
para inicializar o*DriverApi
.Java
RidesharingDriverApi ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext);
Kotlin
val ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext)
Consiga o
RidesharingVehicleReporter
do objeto da API. (*VehicleReporter
estendeNavigationVehicleReporter
.)Java
RidesharingVehicleReporter vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter();
Kotlin
val vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter()
Como autenticar com AuthTokenFactory
Quando o SDK do Driver gera atualizações de localização,
ele precisa enviar essas atualizações para
no servidor do Fleet Engine. Para autenticar essas solicitações, o
O SDK do Driver vai chamar o autor da chamada
instância de AuthTokenFactory
.
A fábrica é responsável por gerar tokens de autenticação no local
e a hora da atualização.
A maneira exata como os tokens são gerados será específico para a situação de cada desenvolvedor. No entanto, a implementação provavelmente precisará:
- buscar um token de autenticação, 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.
Confira o esqueleto de implementação de um AuthTokenFactory
:
Java
class JsonAuthTokenFactory implements AuthTokenFactory {
private String token; // initially null
private long expiryTimeMs = 0;
// This method is called on a thread whose only responsibility is to send
// location updates. Blocking is OK, but just know that no location updates
// can occur until this method returns.
@Override
public String getToken(AuthTokenContext authTokenContext) {
if (System.currentTimeMillis() > expiryTimeMs) {
// The token has expired, go get a new one.
fetchNewToken(authTokenContext.getVehicleId());
}
return token;
}
private void fetchNewToken(String vehicleId) {
String url =
new Uri.Builder()
.scheme("https")
.authority("yourauthserver.example")
.appendPath("token")
.appendQueryParameter("vehicleId", vehicleId)
.build()
.toString();
try (Reader r = new InputStreamReader(new URL(url).openStream())) {
com.google.gson.JsonObject obj
= com.google.gson.JsonParser.parseReader(r).getAsJsonObject();
token = obj.get("Token").getAsString();
expiryTimeMs = obj.get("TokenExpiryMs").getAsLong();
// The expiry time could be an hour from now, but just to try and avoid
// passing expired tokens, we subtract 10 minutes from that time.
expiryTimeMs -= 10 * 60 * 1000;
} catch (IOException e) {
// It's OK to throw exceptions here. The StatusListener you passed to
// create the DriverContext class will be notified and passed along the failed
// update warning.
throw new RuntimeException("Could not get auth token", e);
}
}
}
Kotlin
class JsonAuthTokenFactory : AuthTokenFactory() {
private var token: String = ""
private var expiryTimeMs: Long = 0
// This method is called on a thread whose only responsibility is to send
// location updates. Blocking is OK, but just know that no location updates
// can occur until this method returns.
override fun getToken(context: AuthTokenContext): String {
if (System.currentTimeMillis() > expiryTimeMs) {
// The token has expired, go get a new one.
fetchNewToken(authTokenContext.getVehicleId())
}
return token
}
fun fetchNewToken(vehicleId: String) {
val url =
Uri.Builder()
.scheme("https")
.authority("yourauthserver.example")
.appendPath("token")
.appendQueryParameter("vehicleId", vehicleId)
.build()
.toString()
try {
val reader = InputStreamReader(URL(url).openStream())
reader.use {
val obj = com.google.gson.JsonParser.parseReader(r).getAsJsonObject()
token = obj.get("ServiceToken").getAsString()
expiryTimeMs = obj.get("TokenExpiryMs").getAsLong()
// The expiry time could be an hour from now, but just to try and avoid
// passing expired tokens, we subtract 10 minutes from that time.
expiryTimeMs -= 10 * 60 * 1000
}
} catch (e: IOException) {
// It's OK to throw exceptions here. The StatusListener you passed to
// create the DriverContext class will be notified and passed along the failed
// update warning.
throw RuntimeException("Could not get auth token", e)
}
}
}
Essa implementação específica usa o cliente HTTP Java integrado para buscar uma token em formato JSON do servidor de autenticação do desenvolvedor. O token é salvas para reutilização. O token será buscado novamente se o token antigo estiver dentro de 10 minutos. do tempo de validade.
Sua implementação pode fazer coisas de forma diferente, como usar uma linha de execução em segundo plano para atualizar tokens.
As exceções em AuthTokenFactory
serão tratadas como temporárias, a menos que aconteçam
repetidamente. Depois de algumas tentativas, o SDK do Driver
vai assumir que o
é permanente e interromperá a tentativa de enviar atualizações.
Status e relatórios de erros com StatusListener
Como o SDK do Driver realiza ações
segundo plano, use StatusListener
para acionar notificações quando determinados
como erros, avisos ou mensagens de depuração. Os erros podem ser
temporária por natureza (como BACKEND_CONNECTIVITY_ERROR
), ou podem
fazer com que as atualizações de localização sejam interrompidas permanentemente (como VEHICLE_NOT_FOUND
,
indicando um erro de configuração).
Você fornece uma implementação de StatusListener
opcional, como esta:
Java
class MyStatusListener implements StatusListener {
/** Called when background status is updated, during actions such as location reporting. */
@Override
public void updateStatus(
StatusLevel statusLevel, StatusCode statusCode, String statusMsg) {
// Status handling stuff goes here.
// StatusLevel may be DEBUG, INFO, WARNING, or ERROR.
// StatusCode may be DEFAULT, UNKNOWN_ERROR, VEHICLE_NOT_FOUND,
// BACKEND_CONNECTIVITY_ERROR, or PERMISSION_DENIED.
}
}
Kotlin
class MyStatusListener : StatusListener() {
/** Called when background status is updated, during actions such as location reporting. */
override fun updateStatus(statusLevel: StatusLevel, statusCode: StatusCode, statusMsg: String) {
// Status handling stuff goes here.
// StatusLevel may be DEBUG, INFO, WARNING, or ERROR.
// StatusCode may be DEFAULT, UNKNOWN_ERROR, VEHICLE_NOT_FOUND,
// BACKEND_CONNECTIVITY_ERROR, or PERMISSION_DENIED.
}
}
Observações sobre SSL/TLS
Internamente, a implementação do SDK do Driver usa
SSL/TLS para comunicação segura
com o servidor do Fleet Engine. Versões mais antigas do Android (versões 19 ou
anterior) pode exigir que um patch SecurityProvider
possa se comunicar com o
servidor. Vai aparecer este
artigo
para mais informações sobre como trabalhar com SSL no Android. O artigo também
contém exemplos de código para aplicar patches ao provedor de segurança.
Ativando atualizações de localização
Quando você tiver uma instância do *VehicleReporter
, será necessário ativar as atualizações de localização.
direta:
Java
RidesharingVehicleReporter reporter = ...;
reporter.enableLocationTracking();
Kotlin
val reporter = ...
reporter.enableLocationTracking()
As atualizações de localização são enviadas em intervalos regulares quando o estado do veículo é
ONLINE
: Observe que chamar reporter.enableLocationTracking()
não
define automaticamente o estado do veículo como ONLINE
. Você deve
defina o estado do veículo explicitamente.
Por padrão, o intervalo do relatório é de 10 segundos. O intervalo do relatório pode
será alterado com reporter.setLocationReportingInterval(long, TimeUnit)
. O
o intervalo mínimo de atualização permitido é de cinco segundos. Atualizações mais frequentes podem
resultam em solicitações e erros mais lentos.
Desativar atualizações de localização
Quando o turno do motorista termina, as atualizações de localização podem ser interrompidas e o
veículo marcado como off-line ligando para
DeliveryVehicleReporter.disableLocationTracking
ou
RidesharingVehicleReporter.disableLocationTracking
.
Essa ligação fará com que uma última atualização seja agendada para entrega imediata, indicando que o veículo está off-line. Essa atualização não conterá as configurações o local.
Definir o estado do veículo
Quando as atualizações de localização estão ativadas, definir o estado do veículo como ONLINE
vai
disponibilizar o veículo para consultas de SearchVehicles
; da mesma forma, marcar uma
OFFLINE
vai marcar o veículo como indisponível.
Você tem a opção de definir o estado do veículo no lado do servidor (consulte Atualizar um veículo), ou diretamente no SDK do Driver:
Java
RidesharingVehicleReporter reporter = ...;
reporter.enableLocationTracking();
reporter.setVehicleState(VehicleState.ONLINE);
Kotlin
val reporter = ...
reporter.enableLocationTracking()
reporter.setVehicleState(VehicleState.ONLINE)
Quando as atualizações de local estiverem ativadas, uma chamada para setVehicleState
será propagada
a próxima atualização de local.
Marcar um veículo como ONLINE
quando o rastreamento de localização não estiver ativado
em um IllegalStateException
. Um veículo pode ser marcado como OFFLINE
quando
o monitoramento de local ainda não está ativado ou desativado explicitamente. Isso resultará em
em uma atualização imediata. Uma chamada para
RidesharingVehicleReporter.disableLocationTracking()
vai
Defina o estado do veículo como OFFLINE
.
Observe que setVehicleState
retorna imediatamente e as atualizações são feitas no
conversa de atualização de local. Semelhante ao tratamento de erros de atualizações de locais, os erros
atualizar o estado do veículo são propagadas usando o método
StatusListener
definido no DriverContext
.