Você pode usar o SDK do motorista para oferecer navegação e rastreamento aprimorados ao seu aplicativo do andamento da viagem e do pedido. O SDK do motorista fornece atualizações de localização e tarefas do veículo para o mecanismo de frota de viagens e entregas sob demanda.
O SDK do Driver mantém os serviços do Fleet Engine e os serviços personalizados cientes
do local e do estado do veículo. Por exemplo, o veículo pode ser ONLINE
ou OFFLINE
, e a localização dele muda conforme a viagem.
Requisitos mínimos do sistema
O dispositivo móvel precisa ter o Android 5.0 (nível 21 da API) ou mais recente.
Configuração do Maven
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 ao
minSdkVersion
21 ou mais recente.
Para executar um app criado com o SDK do motorista, o dispositivo Android precisa ter o Google Play Services instalado.
Configurar seu projeto de desenvolvimento
Para configurar o projeto de desenvolvimento e conseguir 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 existente para usar com o SDK do driver. Aguarde alguns minutos até que o novo projeto esteja 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 > Biblioteca, depois pesquise e ative o SDK do Maps para Android.
Para gerar uma chave de API para o projeto, selecione APIs e serviços > Credenciais > Criar credenciais > Chave de API. Para saber mais, consulte Acessar uma chave de API.
Adicionar o SDK do driver ao seu app
O SDK do driver está disponível em um repositório Maven particular. O repositório inclui os arquivos Javadocs e os arquivos do Modelo de objeto do projeto (.pom) do SDK. Para adicionar o SDK do driver ao seu app:
Adicione a dependência abaixo à configuração do Gradle ou Maven, substituindo o marcador
VERSION_NUMBER
pela 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>
Adicionar a chave de API ao seu app
Depois de adicionar o SDK do driver ao app, inclua a chave de API nele. Use a chave de API do projeto que você recebeu ao configurar seu projeto de desenvolvimento.
Nesta seção, descrevemos como armazenar sua chave de API para que possa ser referenciada com mais segurança pelo app. Não verifique sua chave de API no sistema de controle de versões. Ele precisa ser armazenado no arquivo local.properties
, que fica
no diretório raiz do projeto. Para saber mais sobre o arquivo
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 ao elementoplugins
.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, sincronize 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
da seguinte maneira:<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 motorista no seu app, é necessário incluir o texto de atribuição e as licenças de código aberto como parte da seção de avisos legais do app. É melhor incluir as atribuições como um item de menu independente ou como parte de um item de menu Sobre.
Você pode encontrar o texto de atribuição necessário e as licenças de código aberto no arquivo ZIP do SDK do driver:
NOTICE.txt
LICENSES.txt
Dependências
Se você usa o ProGuard para otimizar seus builds, pode ser necessário adicionar as seguintes linhas ao arquivo de configuração do ProGuard:
-dontwarn com.google.**
-dontwarn okio.**
O nível mínimo da API com suporte é 21.
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 o
projeto do Google Cloud, consulte
Autenticação e autorização (em inglês).
Antes de usar o SDK do motorista, inicialize o 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 de 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 enviá-las ao
servidor do Fleet Engine. Para autenticar essas solicitações, o
SDK do motorista chama uma instância de AuthTokenFactory
fornecida pelo autor da chamada.
A fábrica é responsável por gerar tokens de autenticação no momento da atualização
do local.
A forma exata como os tokens são gerados vai depender da situação de cada desenvolvedor. No entanto, a implementação provavelmente vai precisar:
- buscar um token de autenticação, possivelmente no formato JSON, de um servidor HTTPS
- analisar e armazenar em cache o token
- atualizar o token quando ele expirar.
Para ver detalhes sobre os tokens esperados pelo servidor do Fleet Engine, consulte Como criar um JSON Web Token (JWT) para autorização.
Confira o modelo 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 um token no formato JSON no servidor de autenticação do desenvolvedor. O token é salvo para reutilização. O token será buscado novamente se o token antigo estiver dentro de 10 minutos após a data de validade.
Sua implementação pode fazer as coisas de forma diferente, como usar uma linha de execução em segundo plano para atualizar os tokens.
As exceções em AuthTokenFactory
serão tratadas como temporárias, a menos que ocorram
repetidamente. Após uma série de tentativas, o SDK do driver
vai presumir que o
erro é permanente e vai parar de tentar enviar atualizações.
Status e Error Reporting com StatusListener
Como o SDK do driver realiza ações em
segundo plano, use o StatusListener
para acionar notificações quando determinados
eventos ocorrerem, como erros, avisos ou mensagens de depuração. Os erros podem ser
temporários por natureza (como BACKEND_CONNECTIVITY_ERROR
) ou podem
fazer com que as atualizações de local sejam interrompidas permanentemente (como VEHICLE_NOT_FOUND
,
indicando um erro de configuração).
Você fornece uma implementação 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 se comunicar com segurança
com o servidor do Fleet Engine. As versões mais antigas do Android (versão 19 ou
da API anteriores) podem exigir um patch SecurityProvider
para se comunicar com o
servidor. Consulte este
artigo
para mais informações sobre como trabalhar com SSL no Android. O artigo também
contém exemplos de código para corrigir o provedor de segurança.
Ativando atualizações de localização
Quando você tiver uma instância de *VehicleReporter
, ativar as atualizações de localização será simples:
Java
RidesharingVehicleReporter reporter = ...;
reporter.enableLocationTracking();
Kotlin
val reporter = ...
reporter.enableLocationTracking()
As atualizações de localização são enviadas em um intervalo regular quando o estado do veículo é
ONLINE
. Observe que chamar reporter.enableLocationTracking()
não
define automaticamente o estado do veículo como ONLINE
. É necessário
definir 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
intervalo mínimo de atualização com suporte é de cinco segundos. Atualizações mais frequentes podem resultar em solicitações mais lentas e erros.
Desativando atualizações de local
Quando o turno do motorista terminar, as atualizações de localização poderão ser interrompidas e o
veículo será marcado como off-line chamando
DeliveryVehicleReporter.disableLocationTracking
ou
RidesharingVehicleReporter.disableLocationTracking
.
Essa chamada fará com que uma atualização final seja agendada para entrega imediata, indicando que o veículo está off-line. Essa atualização não vai conter a localização do usuário.
Como definir o estado do veículo
Quando as atualizações de localização estão ativadas, definir o estado do veículo como ONLINE
o torna disponível para consultas SearchVehicles
. Da mesma forma, marcar um
veículo como OFFLINE
marca o veículo como indisponível.
Você pode definir o estado do veículo no lado do servidor (consulte Atualizar um veículo) ou diretamente no SDK do motorista:
Java
RidesharingVehicleReporter reporter = ...;
reporter.enableLocationTracking();
reporter.setVehicleState(VehicleState.ONLINE);
Kotlin
val reporter = ...
reporter.enableLocationTracking()
reporter.setVehicleState(VehicleState.ONLINE)
Quando as atualizações de localização estão ativadas, uma chamada para setVehicleState
será propagada na próxima atualização de local.
Marcar um veículo como ONLINE
quando o monitoramento de localização não estiver ativado resultará em uma IllegalStateException
. Um veículo pode ser marcado como OFFLINE
quando o rastreamento de localização ainda não está ativado ou explicitamente desativado. Isso resulta
em uma atualização imediata. Uma chamada para
RidesharingVehicleReporter.disableLocationTracking()
define
o estado do veículo como OFFLINE
.
Observe que setVehicleState
retorna imediatamente, e as atualizações são feitas na linha de execução de atualização de local. Assim como no tratamento de erros das atualizações de local, os erros ao atualizar o estado do veículo são propagados usando o StatusListener
fornecido opcionalmente, definido no DriverContext
.