Primeiros passos com o SDK do consumidor para Android

Use o SDK do consumidor para criar e executar um app básico de consumidor integrado aos serviços de back-end da solução de viagens e entregas sob demanda. É possível criar um app de progresso de viagem e pedido que possa exibir uma viagem ativa, responder a atualizações e processar erros.

Como o SDK do consumidor tem uma arquitetura modular, você pode usar as partes da API que quer usar no seu app específico e integrá-las às suas próprias APIs, aos serviços de back-end fornecidos pelo Fleet Engine e a APIs adicionais da Plataforma Google Maps.

Requisitos mínimos do sistema

O dispositivo móvel precisa ter o Android 6.0 (API de nível 23) ou mais recente.

Configuração do build e das dependências

As versões 1.99.0 e mais recentes do SDK para consumidor estão disponíveis no repositório Maven do Google. O canal de repositório particular usado anteriormente foi descontinuado.

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 consumidor para Android, seu app precisa ser direcionado ao minSdkVersion 23 ou mais recente.

Para executar um app criado com o SDK do consumidor, o dispositivo Android precisa ter o Google Play Services instalado.

Configurar seu projeto de desenvolvimento

Para configurar o projeto de desenvolvimento e receber uma chave de API para o projeto no Console do Google Cloud:

  1. Crie um novo projeto do Console do Google Cloud ou selecione um projeto atual para usar com o SDK do consumidor. Aguarde alguns minutos até que o novo projeto esteja visível no Console do Google Cloud.

  2. 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, pesquise e ative o SDK do Maps para Android.

  3. Para gerar uma chave de API para o projeto, selecione APIs e serviços > Credenciais > Criar credenciais > Chave de API. Para mais informações sobre como conseguir uma chave de API, consulte Acessar uma chave de API.

Adicionar o SDK do consumidor ao seu app

O SDK do Consumer está disponível em um repositório Maven particular. O repositório inclui os arquivos do Modelo de objeto de projeto (.pom) do SDK e Javadocs. Para adicionar o SDK do consumidor ao seu app:

  1. Configure seu ambiente para acessar o repositório Maven do host, conforme descrito na seção anterior.

    Se você tiver uma configuração de gerenciamento de dependências centralizada declarada em settings.gradle, desative-a da seguinte maneira.

    • Remova o seguinte bloco de código em settings.gradle:

      import org.gradle.api.initialization.resolve.RepositoriesMode
      dependencyResolutionManagement {
          repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
          repositories {
              google()
              mavenCentral()
          }
      }
      
  2. Adicione a seguinte dependência à configuração do Gradle ou do Maven, substituindo o marcador VERSION_NUMBER pela versão desejada do SDK do consumidor.

    Gradle

    Adicione o seguinte ao seu build.gradle:

    dependencies {
      ...
      implementation 'com.google.android.libraries.mapsplatform.transportation:transportation-consumer:VERSION_NUMBER'
    }
    

    Maven

    Adicione o seguinte ao seu pom.xml:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.mapsplatform.transportation</groupId>
        <artifactId>transportation-consumer</artifactId>
        <version>VERSION_NUMBER</version>
      </dependency>
    </dependencies>
    
  3. O SDK do consumidor depende do SDK do Maps. Essa dependência é configurada de forma que, se a versão do SDK do Maps não for definida explicitamente no arquivo de configuração do build, como no exemplo a seguir, quando uma nova versão do SDK do Maps for lançada, o SDK de consumidor continuará usando a versão mínima compatível exigida por ele.

    Gradle

    Adicione o seguinte ao seu build.gradle:

    dependencies {
      ...
      implementation 'com.google.android.gms:play-services-maps:18.1.0'
    }
    

    Maven

    Adicione o seguinte ao seu pom.xml:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.gms</groupId>
        <artifactId>play-services-maps</artifactId>
        <version>18.1.0</version>
      </dependency>
    </dependencies>
    

Adicionar a chave de API ao seu app

Depois de adicionar o SDK do consumidor ao app, inclua a chave de API nele. É necessário usar 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 ela possa ser referenciada pelo seu app com mais segurança. Não faça a verificação da sua chave de API no sistema de controle de versões. Ele precisa ser armazenado no arquivo local.properties, localizado 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:

  1. Abra o arquivo build.gradle no nível raiz e adicione o seguinte código ao elemento dependencies em buildscript.

    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")
        }
    }
    
  2. Abra o arquivo build.gradle no nível do app e adicione o seguinte código ao elemento plugins.

    Groovy

    id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
    

    Kotlin

    id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
    
  3. Se você usa o Android Studio, sincronize seu projeto com o Gradle.

  4. Abra o local.properties no diretório do nível do projeto e adicione o código abaixo. Substitua YOUR_API_KEY pela sua chave de API.

    MAPS_API_KEY=YOUR_API_KEY
    
  5. No seu arquivo AndroidManifest.xml, acesse com.google.android.geo.API_KEY e atualize o atributo android: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.consumerapidemo">
    <uses-permission android:name="android.permission.ACCESS_FINE_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 consumidor no seu app, é necessário incluir texto de atribuição e 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.

As informações de licenças podem ser encontradas no arquivo "third_party_licenses.txt" no arquivo AAR desarquivado.

Consulte https://developers.google.com/android/guides/opensource para saber como incluir avisos de código aberto.

Autenticação do SDK do consumidor

O SDK do consumidor fornece autenticação usando JSON Web Tokens. Um JSON Web Token (JWT) é um token de acesso com base em JSON que fornece uma ou mais declarações em um serviço. Por exemplo, um servidor pode gerar um token com a declaração "conectado como administrador" e fornecê-la a um cliente. O cliente pode usar esse token para provar que está conectado como administrador.

O SDK do consumidor usa o JSON Web Token fornecido pelo aplicativo para se comunicar com o Fleet Engine. Consulte Autenticação e autorização do Fleet Engine para mais informações.

O token de autorização precisa incluir uma declaração tripid:TRIP_ID no cabeçalho authorization do token, em que TRIP_ID é o ID de viagem. Assim, o SDK do consumidor tem acesso aos detalhes da viagem, incluindo a posição do veículo, trajeto e HEC.

Callbacks de token da Web JSON

O SDK do consumidor registra um callback do token de autorização com o aplicativo durante a inicialização. O SDK chama o aplicativo para receber um token referente a todas as solicitações de rede que exigem autorização.

Recomendamos que os tokens de autorização da implementação de callback armazenem em cache e os atualize somente quando o tempo expiry tiver passado. Os tokens precisam ser emitidos com um prazo de validade de uma hora.

O callback do token de autorização especifica qual token de serviço é necessário para o serviço TripService. Ele também fornece o tripId necessário para o contexto.

O exemplo de código a seguir demonstra como implementar um callback do token de autorização.

Java

class JsonAuthTokenFactory implements AuthTokenFactory {

  private static final String TOKEN_URL =
      "https://yourauthserver.example/token";

  private static class CachedToken {
    String tokenValue;
    long expiryTimeMs;
    String tripId;
  }

  private CachedToken token;

  /*
  * This method is called on a background thread. Blocking is OK. However, be
  * aware that no information can be obtained from Fleet Engine until this
  * method returns.
  */
  @Override
  public String getToken(AuthTokenContext context) {
    // If there is no existing token or token has expired, go get a new one.
    String tripId = context.getTripId();
    if (tripId == null) {
      throw new RuntimeException("Trip ID is missing from AuthTokenContext");
    }
    if (token == null || System.currentTimeMillis() > token.expiryTimeMs ||
        !tripId.equals(token.tripId)) {
      token = fetchNewToken(tripId);
    }
    return token.tokenValue;
  }

  private static CachedToken fetchNewToken(String tripId) {
    String url = TOKEN_URL + "/" + tripId;
    CachedToken token = new CachedToken();

    try (Reader r = new InputStreamReader(new URL(url).openStream())) {
      com.google.gson.JsonObject obj
          = com.google.gson.JsonParser.parseReader(r).getAsJsonObject();

      token.tokenValue = obj.get("ServiceToken").getAsString();
      token.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 5 minutes from that time.
      */
      token.expiryTimeMs -= 5 * 60 * 1000;
    } catch (IOException e) {
      /*
      * It's OK to throw exceptions here. The error listeners will receive the
      * error thrown here.
      */
      throw new RuntimeException("Could not get auth token", e);
    }
    token.tripId = tripId;

    return token;
  }
}

Kotlin

class JsonAuthTokenFactory : AuthTokenFactory() {

  private var token: CachedToken? = null

  /*
  * This method is called on a background thread. Blocking is OK. However, be
  * aware that no information can be obtained from Fleet Engine until this
  * method returns.
  */
  override fun getToken(context: AuthTokenContext): String {
    // If there is no existing token or token has expired, go get a new one.
    val tripId = 
      context.getTripId() ?: 
        throw RuntimeException("Trip ID is missing from AuthTokenContext")

    if (token == null || System.currentTimeMillis() > token.expiryTimeMs ||
        tripId != token.tripId) {
      token = fetchNewToken(tripId)
    }

    return token.tokenValue
  }

  class CachedToken(
    var tokenValue: String? = "", 
    var expiryTimeMs: Long = 0,
    var tripId: String? = "",
  )

  private companion object {
    const val TOKEN_URL = "https://yourauthserver.example/token"

    fun fetchNewToken(tripId: String) {
      val url = "$TOKEN_URL/$tripId"
      val token = CachedToken()

      try {
        val reader = InputStreamReader(URL(url).openStream())

        reader.use {
          val obj = com.google.gson.JsonParser.parseReader(r).getAsJsonObject()

          token.tokenValue = obj.get("ServiceToken").getAsString()
          token.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 5 minutes from that time.
          */
          token.expiryTimeMs -= 5 * 60 * 1000
        }
      } catch (e: IOException) {
        /*
        * It's OK to throw exceptions here. The error listeners will receive the
        * error thrown here.
        */
        throw RuntimeException("Could not get auth token", e)
      }

      token.tripId = tripId

      return token
    }
  }
}

Inicializar a API

Antes de seguir estes procedimentos, presume-se que você ativou os serviços adequados e o SDK do consumidor.

Acessar a instância ConsumerApi

Para usar o SDK do consumidor, seu app precisa inicializar ConsumerApi de forma assíncrona. A API é um singleton. O método de inicialização usa um AuthTokenFactory. A fábrica gera novos tokens JWT para o usuário quando necessário.

O providerId é o ID do projeto do Google Cloud. Consulte o Guia do usuário do Fleet Engine para mais informações sobre como criar o projeto.

Seu app precisa implementar o AuthTokenFactory conforme descrito em Autenticação do SDK do consumidor.

Java

Task<ConsumerApi> consumerApiTask = ConsumerApi.initialize(
    this, "myProviderId", authTokenFactory);

consumerApiTask.addOnSuccessListener(
  consumerApi -> this.consumerApi = consumerApi);

Kotlin

val consumerApiTask =
  ConsumerApi.initialize(this, "myProviderId", authTokenFactory)

consumerApiTask?.addOnSuccessListener { consumerApi: ConsumerApi ->
  this@YourActivity.consumerApi = consumerApi
}

Inicializar o SDK do Maps para solicitar o renderizador preferido

O SDK do consumidor v2.0.0 é compatível com o SDK do Maps para Android v18.1.0 e mais recentes. Ela é compatível com solicitações que especificam o renderizador preferido do Google Maps. Confira mais detalhes em Novo renderizador de mapas(opcional).

Adicionar o SDK do Maps como uma dependência

Gradle

Adicione o seguinte ao seu build.gradle:

dependencies {
  //...
  implementation "com.google.android.gms:play-services-maps:18.1.0"
}

Maven

Adicione o seguinte ao seu pom.xml:

 <dependencies>
   ...
   <dependency>
     <groupId>com.google.android.gms</groupId>
     <artifactId>play-services-maps</artifactId>
     <version>18.1.0</version>
   </dependency>
 </dependencies>

Inicializar o SDK do Maps antes de inicializar o SDK do consumidor

Na classe Application ou Activity de inicialização, chame MapsInitializer.initialize() e aguarde o resultado da solicitação do renderizador antes de inicializar o SDK do consumidor.

java

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  initViews();

  MapsInitializer.initialize(getApplicationContext(), Renderer.LATEST,
      new OnMapsSdkInitializedCallback() {
        @Override
        public void onMapsSdkInitialized(Renderer renderer) {
          switch (renderer) {
            case LATEST:
              Log.i("maps_renderer", "LATEST renderer");
              break;
            case LEGACY:
              Log.i("maps_renderer", "LEGACY renderer");
              break;
          }

          initializeConsumerSdk();
        }
      });
}

Kotlin

fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  setContentView(R.layout.main)
  initViews()

  MapsInitializer.initialize(
    getApplicationContext(), Renderer.LATEST,
    object : OnMapsSdkInitializedCallback() {
      fun onMapsSdkInitialized(renderer: Renderer?) {
        when (renderer) {
          LATEST -> Log.i("maps_renderer", "LATEST renderer")
          LEGACY -> Log.i("maps_renderer", "LEGACY renderer")
        }
        initializeConsumerSdk()
      }
    })
  }

Criar a interface do usuário

Você pode usar ConsumerMapFragment ou ConsumerMapView para criar a interface do usuário do aplicativo. ConsumerMapFragment permite que você defina seu mapa usando um Fragment, enquanto ConsumerMapView permite que você use um View. A funcionalidade de compartilhamento de viagens é a mesma em ConsumerMapView e ConsumerMapFragment. Portanto, você pode escolher uma com base se View ou Fragment é melhor para seu app.

Foi adicionado suporte à API 19 (KitKat) e a drawables vetoriais.

Se o design do app exigir suporte a dispositivos com a API 19 (KitKat) e a drawables vetoriais, adicione o código abaixo à atividade. Esse código estende AppCompatActivity para usar os drawables vetoriais no SDK do consumidor.

Java

// ...
import android.support.v7.app.AppCompatActivity;

// ...

public class ConsumerTestActivity extends AppCompatActivity {
  // ...
}

Kotlin

// ...
import android.support.v7.app.AppCompatActivity

// ...

class ConsumerTestActivity : AppCompatActivity() {
  // ...
}

Adicionar o fragmento ou visualização do mapa

Você cria o mapa para exibir o compartilhamento de jornadas em um fragmento do Android ou em uma visualização, que é definido no arquivo XML de layout do app (localizado em /res/layout). O fragmento (ou visualização) fornece acesso ao mapa de compartilhamento de jornada, que pode ser acessado e modificado pelo app. O mapa também fornece um identificador para o ConsumerController, que permite que o app controle e personalize a experiência de compartilhamento da jornada.

Mapa e controlador de compartilhamento da jornada

Defina o mapa de compartilhamento da jornada como um fragmento (usando ConsumerMapFragment) ou como uma visualização (usando ConsumerMapView), conforme mostrado no exemplo de código a seguir. Seu método onCreate() precisa chamar getConsumerGoogleMapAsync(callback), que retorna ConsumerGoogleMap de forma assíncrona no callback. Em seguida, use a ConsumerGoogleMap para mostrar o compartilhamento da jornada, que pode ser atualizada conforme necessário pelo app.

ConsumerMapFragment

Você define o fragmento no arquivo XML de layout do aplicativo, conforme demonstrado no exemplo de código abaixo.

<fragment
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:name="com.google.android.libraries.mapsplatform.transportation.consumer.view.ConsumerMapFragment"
    android:id="@+id/consumer_map_fragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

A chamada para getConsumerGoogleMapAsync() precisa vir do método onCreate().

Java

public class SampleAppActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {

    // Find the ConsumerMapFragment.
    ConsumerMapFragment consumerMapFragment =
        (ConsumerMapFragment) fragmentManager.findFragmentById(R.id.consumer_map_fragment);

    // Initiate the callback that returns the map.
    if (consumerMapFragment != null) {
      consumerMapFragment.getConsumerGoogleMapAsync(
          new ConsumerMapReadyCallback() {
            // The map returned in the callback is used to access the ConsumerController.
            @Override
            public void onConsumerMapReady(@NonNull ConsumerGoogleMap consumerGoogleMap) {
              ConsumerController consumerController = consumerGoogleMap.getConsumerController();
            }
          });
    }
  }

}

Kotlin

class SampleAppActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    // Find the ConsumerMapFragment.
    val consumerMapFragment =
      fragmentManager.findFragmentById(R.id.consumer_map_fragment) as ConsumerMapFragment

    consumerMapFragment.getConsumerGoogleMapAsync(
      object : ConsumerMapReadyCallback() {
        override fun onConsumerMapReady(consumerGoogleMap: ConsumerGoogleMap) {
          val consumerController = consumerGoogleMap.getConsumerController()!!
        }
      }
    )
  }
}
ConsumerMapView

A visualização pode ser usada em um fragmento ou em uma atividade, conforme definido no arquivo XML.

<com.google.android.libraries.mapsplatform.transportation.consumer.view.ConsumerMapView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/consumer_map_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

A chamada para getConsumerGoogleMapAsync() precisa ser de onCreate(). Além do parâmetro de callback, ele requer a atividade ou o fragmento que contém e GoogleMapOptions (que pode ser nulo), contendo atributos de configuração para MapView. A classe base da atividade ou do fragmento precisa ser uma FragmentActivity ou um Fragment de suporte (respectivamente), já que fornece acesso ao próprio ciclo de vida.

Java

public class SampleAppActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    ConsumerMapView mapView = findViewById(R.id.consumer_map_view);

    if (mapView != null) {
      mapView.getConsumerGoogleMapAsync(
          new ConsumerMapReadyCallback() {
            // The map returned in the callback is used to access the ConsumerController.
            @Override
            public void onConsumerMapReady(@NonNull ConsumerGoogleMap consumerGoogleMap) {
              ConsumerController consumerController = consumerGoogleMap.getConsumerController();
            }
          }, this, null);
    }
  }

}

Kotlin

class SampleAppActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    val mapView = findViewById(R.id.consumer_map_view) as ConsumerMapView

    mapView.getConsumerGoogleMapAsync(
      object : ConsumerMapReadyCallback() {
        // The map returned in the callback is used to access the ConsumerController.
        override fun onConsumerMapReady(consumerGoogleMap: ConsumerGoogleMap) {
          val consumerController = consumerGoogleMap.getConsumerController()!!
        }
      },
      /* fragmentActivity= */ this,
      /* googleMapOptions= */ null,
    )
  }
}

Uma MapView em um fragmento é igual ao exemplo acima para MapView em uma atividade, exceto pelo fato de o fragmento inflar o layout que inclui a MapView no método onCreateView() do fragmento.

Java

public class MapViewInFragment extends Fragment {

  @Override
  public View onCreateView(
      @NonNull LayoutInflater layoutInflater,
      @Nullable ViewGroup viewGroup,
      @Nullable Bundle bundle) {
    return layoutInflater.inflate(R.layout.consumer_map_view, viewGroup, false);
  }

}

Kotlin

class MapViewInFragment : Fragment() {
  override fun onCreateView(
    layoutInflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?,
  ): View {
    return layoutInflater.inflate(R.layout.consumer_map_view, viewGroup, false)
  }
}

Ajustar o zoom da câmera para focar uma jornada

O botão padrão Meu local integrado ao SDK do Maps centraliza a câmera no local do dispositivo.

Se há uma sessão ativa de Compartilhamento de jornada, você pode centralizar a câmera para focar na jornada em vez de focar na localização do dispositivo.

Solução integrada do SDK do consumidor para Android: AutoCamera

Para que você possa se concentrar na jornada em vez de na localização do dispositivo, o SDK do consumidor oferece um recurso de câmera automática que é ativado por padrão. A câmera aumenta o zoom para focar o trajeto de compartilhamento da viagem e o waypoint da próxima viagem.

AutoCamera

Como personalizar o comportamento da câmera

Se você precisar de mais controle do comportamento da câmera, desative ou ative a câmera automática usando ConsumerController.setAutoCameraEnabled().

ConsumerController.getCameraUpdate() retorna os limites recomendados da câmera nesse momento. Você pode fornecer esse CameraUpdate como um argumento para GoogleMap.moveCamera() ou GoogleMap.animateCamera().

Acesse mapas e serviço de transporte por aplicativo

Para oferecer suporte ao serviço de transporte por aplicativo e interação com o mapa no seu app, você precisa acessar ConsumerGoogleMap e ConsumerController. ConsumerMapFragment e ConsumerMapView retornam ConsumerGoogleMap de forma assíncrona em ConsumerMapReadyCallback. ConsumerGoogleMap retorna ConsumerController de getConsumerController(). Você pode acessar ConsumerGoogleMap e ConsumerController da seguinte maneira.

Java

private ConsumerGoogleMap consumerGoogleMap;
private ConsumerController consumerController;
private ConsumerMapView consumerMapView;

consumerMapView.getConsumerGoogleMapAsync(
    new ConsumerMapReadyCallback() {
      @Override
      public void onConsumerMapReady(@NonNull ConsumerGoogleMap consumerMap) {
        consumerGoogleMap = consumerMap;
        consumerController = consumerMap.getConsumerController();
      }
    },
    this, null);

Kotlin

var consumerGoogleMap: ConsumerGoogleMap
var consumerController: ConsumerController
val consumerMapView = findViewById(R.id.consumer_map_view) as ConsumerMapView

consumerMapView.getConsumerGoogleMapAsync(
  object : ConsumerMapReadyCallback() {
    override fun onConsumerMapReady(consumerMap: ConsumerGoogleMap) {
      consumerGoogleMap = consumerMap
      consumerController = consumerMap.getConsumerController()
    },
    /* fragmentActivity= */ this,
    /* googleMapOptions= */ null,
  }
)

ConsumerGoogleMap

ConsumerGoogleMap é uma classe wrapper para a classe GoogleMap. Com ele, o app consegue interagir com o mapa usando uma API equivalente a GoogleMap. O uso do mapa do consumidor permite que seu app e transporte compartilhado interajam perfeitamente com o mesmo GoogleMap subjacente. Por exemplo, GoogleMap permite apenas um único registro de callback, mas ConsumerGoogleMap oferece suporte a callbacks registrados duplos. Esses callbacks permitem que o app e o compartilhamento de viagens registrem callbacks em sequência.

ConsumerController

O ConsumerController fornece acesso a funcionalidades de compartilhamento de viagens, como monitorar viagens, controlar o status delas e definir locais.

Configurar o compartilhamento da jornada

Depois que o back-end corresponder um consumidor a um veículo, use JourneySharingSession para iniciar a interface do usuário de compartilhamento da jornada. O compartilhamento de jornada mostra a rota e a localização do veículo correspondente. Depois de implementar o SDK no app, você pode adicionar a funcionalidade para monitorar viagens, detectar atualizações e processar erros. Os procedimentos a seguir pressupõem que os serviços de back-end estejam em vigor e que seus serviços de correspondência de consumidores e veículos estejam operacionais.

  1. Registre um listener em um objeto TripModel para conferir detalhes sobre a viagem, como a HEC (hora estimada de chegada) e a distância que o veículo precisa percorrer antes da chegada.

    Java

    // Create a TripModel instance for listening to updates to the trip specified by this trip name.
    String tripName = ...;
    TripModelManager tripModelManager = consumerApi.getTripModelManager();
    TripModel tripModel = tripModelManager.getTripModel(tripName);
    
    // Create a JourneySharingSession instance based on the TripModel.
    JourneySharingSession session = JourneySharingSession.createInstance(tripModel);
    
    // Add the JourneySharingSession instance on the map for updating the UI.
    consumerController.showSession(session);
    
    // Register for trip update events.
    tripModel.registerTripCallback(new TripModelCallback() {
      @Override
      public void onTripETAToNextWaypointUpdated(
          TripInfo tripInfo, @Nullable Long timestampMillis) {
        // ...
      }
    
      @Override
      public void onTripActiveRouteRemainingDistanceUpdated(
          TripInfo tripInfo, @Nullable Integer distanceMeters) {
        // ...
      }
    
      // ...
    });
    

    Kotlin

    // Create a TripModel instance for listening to updates to the trip specified by this trip name.
    val tripName = "tripName"
    val tripModelManager = consumerApi.getTripModelManager()
    val tripModel = tripModelManager.getTripModel(tripName)
    
    // Create a JourneySharingSession instance based on the TripModel.
    val session = JourneySharingSession.createInstance(tripModel)
    
    // Add the JourneySharingSession instance on the map for updating the UI.
    consumerController.showSession(session)
    
    // Register for trip update events.
    tripModel.registerTripCallback(
      object : TripModelCallback() {
        override fun onTripETAToNextWaypointUpdated(
          tripInfo: TripInfo,
          timestampMillis: Long?,
        ) {
          // ...
        }
    
        override fun onTripActiveRouteRemainingDistanceUpdated(
          tripInfo: TripInfo,
          distanceMeters: Int?,
        ) {
          // ...
        }
    
      // ...
    })
    
  2. Configure sua viagem usando o TripModelOptions.

    Java

    // Set refresh interval to 2 seconds.
    TripModelOptions tripOptions =
        TripModelOptions.builder().setRefreshIntervalMillis(2000).build();
    tripModel.setTripModelOptions(tripOptions);
    

    Kotlin

    // Set refresh interval to 2 seconds.
    val tripOptions = TripModelOptions.builder().setRefreshIntervalMillis(2000).build()
    tripModel.setTripModelOptions(tripOptions)
    

Parar compartilhamento da jornada

Não deixe de interromper o compartilhamento da jornada quando ele não for mais necessário, por exemplo, quando a atividade do host for destruída. Parar o compartilhamento de jornada também interrompe as solicitações de rede para o Fleet Engine e evita vazamentos de memória.

O exemplo de código a seguir demonstra como interromper o compartilhamento de jornadas.

Java

public class MainActivity extends AppCompatActivity
    implements ConsumerViewModel.JourneySharingListener  {

  // Class implementation

  @Override
  protected void onDestroy() {
    super.onDestroy();

    if (journeySharingSession != null) {
      journeySharingSession.stop();
    }
  }
}

Kotlin

class SampleAppActivity : AppCompatActivity(), ConsumerViewModel.JourneySharingListener {

  // Class implementation

  override fun onDestroy() {
    super.onDestroy()

    journeySharingSession?.stop()
  }
}

Processar erros de viagem

O método onTripRefreshError mostra erros que ocorrem durante o monitoramento de viagens. O mapeamento dos erros do SDK para consumidor segue as mesmas diretrizes HTTP/RPC estabelecidas para o Google Cloud Platform. Erros comuns que aparecem durante o monitoramento de viagens incluem:

HTTP RPC Descrição
400 INVALID_ARGUMENT O cliente especificou um nome de viagem inválido. O nome da viagem precisa seguir o formato providers/{provider_id}/trips/{trip_id}. O provider_id precisa ser o ID do projeto do Cloud de propriedade do provedor de serviços.
401 UNAUTHENTICATED Solicitação não autenticada devido a um token JWT inválido. Esse erro ocorrerá se o token JWT estiver assinado sem um ID de viagem ou se o token JWT tiver expirado.
403 PERMISSION_DENIED O cliente não tem permissão suficiente. Esse erro ocorrerá se o token JWT for inválido, o cliente não tiver permissão ou a API não estiver ativada para o projeto do cliente. O token JWT pode estar ausente ou o token está assinado com um ID de viagem que não corresponde ao ID de viagem solicitado.
429 RESOURCE_EXHAUSTED A cota do recurso está em zero ou a taxa de tráfego excede o limite.
503 UNAVAILABLE Serviço indisponível. Geralmente, o servidor está inativo.
504 DEADLINE_EXCEEDED O prazo de solicitação foi excedido. Isso acontecerá somente se o autor da chamada definir um prazo menor do que o prazo padrão do método (ou seja, o prazo solicitado não é suficiente para o servidor processar a solicitação) e a solicitação não for concluída dentro do prazo.

Para mais informações, consulte Tratamento de erros do SDK do consumidor.