Pronto!

Para começar a desenvolver, acesse nossa documentação do desenvolvedor.

Ativar a Google Maps Roads API

Para começar, orientaremos você pelo Console do Desenvolvedor do Google para realizar algumas atividades:

  1. Criar ou selecionar um projeto
  2. Ativar a Google Maps Roads API
  3. Criar chaves apropriadas
Continuar

Conceitos avançados

Observação: os exemplos abaixo usam a Google Maps Roads API no Java Client for Google Maps Services. É possível adaptar os conceitos para a linguagem que você escolher usar. O Python Client, o Go Client e o Node.js Client também estão disponíveis no GitHub.

Adquirir dados

Há diversas maneiras de se obter dados de localização coletados. Neste documento, descrevemos duas técnicas de aquisição de dados a usar com o recurso Snap to Roads da Google Maps Roads API.

GPX

GPX é um formato aberto baseado em XML para compartilhar rotas, percursos e pontos de referência capturados por dispositivos GPS. Este exemplo usa o analisador XmlPull, um analisador de XML leve disponível para servidores Java e ambientes de dispositivos móveis.

/**
 * Parses the waypoint (wpt tags) data into native objects from a GPX stream.
 */
private List<LatLng> loadGpxData(XmlPullParser parser, InputStream gpxIn)
        throws XmlPullParserException, IOException {
    // We use a List<> as we need subList for paging later
    List<LatLng> latLngs = new ArrayList<>();
    parser.setInput(gpxIn, null);
    parser.nextTag();

    while (parser.next() != XmlPullParser.END_DOCUMENT) {
        if (parser.getEventType() != XmlPullParser.START_TAG) {
            continue;
        }

        if (parser.getName().equals("wpt")) {
            // Save the discovered latitude/longitude attributes in each <wpt>.
            latLngs.add(new LatLng(
                    Double.valueOf(parser.getAttributeValue(null, "lat")),
                    Double.valueOf(parser.getAttributeValue(null, "lon"))));
        }
        // Otherwise, skip irrelevant data
    }

    return latLngs;
}

Veja a seguir alguns dados GPX brutos carregados em um mapa.

Dados GPX brutos em um mapa

Serviços de localização do Android

A melhor forma de capturar dados de GPS em um dispositivo Android varia de acordo com o uso. Dê uma olhada no treinamento Android de Como receber atualizações da localização e em Exemplos de localização Google Play no GitHub.

Processar caminhos longos

Como o recurso Snap to Roads deduz a localização com base em todo o caminho, em vez de em pontos individuais, é preciso ter atenção ao processar caminhos longos (ou seja, caminhos com mais de 100 pontos por solicitação).

Para tratar solicitações individuais como um único caminho longo, você deve incluir sobreposições, de forma que os pontos finais da solicitação anterior sejam incluídos como os primeiros pontos da solicitação seguinte. O número de pontos a incluir depende da precisão dos dados. Você deve incluir mais pontos em solicitações de baixa precisão.

Este exemplo usa o Java Client for Google Maps Services para enviar solicitações “paginadas” e, em seguida, junta os dados novamente, incluindo pontos interpolados, na lista retornada.

/**
 * Snaps the points to their most likely position on roads using the Roads API.
 */
private List<SnappedPoint> snapToRoads(GeoApiContext context) throws Exception {
    List<SnappedPoint> snappedPoints = new ArrayList<>();

    int offset = 0;
    while (offset < mCapturedLocations.size()) {
        // Calculate which points to include in this request. We can't exceed the API's
        // maximum and we want to ensure some overlap so the API can infer a good location for
        // the first few points in each request.
        if (offset > 0) {
            offset -= PAGINATION_OVERLAP;   // Rewind to include some previous points.
        }
        int lowerBound = offset;
        int upperBound = Math.min(offset + PAGE_SIZE_LIMIT, mCapturedLocations.size());

        // Get the data we need for this page.
        LatLng[] page = mCapturedLocations
                .subList(lowerBound, upperBound)
                .toArray(new LatLng[upperBound - lowerBound]);

        // Perform the request. Because we have interpolate=true, we will get extra data points
        // between our originally requested path. To ensure we can concatenate these points, we
        // only start adding once we've hit the first new point (that is, skip the overlap).
        SnappedPoint[] points = RoadsApi.snapToRoads(context, true, page).await();
        boolean passedOverlap = false;
        for (SnappedPoint point : points) {
            if (offset == 0 || point.originalIndex >= PAGINATION_OVERLAP - 1) {
                passedOverlap = true;
            }
            if (passedOverlap) {
                snappedPoints.add(point);
            }
        }

        offset = upperBound;
    }

    return snappedPoints;
}

Veja os dados do exemplo acima depois de executar as solicitações de Snap to Roads. A linha vermelha representa os dados brutos e a linha azul, os dados do Snap to Roads.

Exemplos de dados que passaram pelo recurso Snap to Roads

Uso eficiente da cota

A resposta de uma solicitação de Snap to Roads contém uma lista de IDs de local que mapeiam os pontos fornecidos, possivelmente com pontos adicionais se você definir interpolate=true.

Para usar sua cota com eficiência em uma solicitação de limite de velocidade, você só deve fazer consultas de IDs de local exclusivos de sua solicitação. Este exemplo usa o Java Client for Google Maps Services para consultar limites de velocidade com uma lista de IDs de local.

/**
 * Retrieves speed limits for the previously-snapped points. This method is efficient in terms
 * of quota usage as it will only query for unique places.
 *
 * Note: Speed limit data is only available for requests using an API key enabled for a
 * Google Maps APIs Premium Plan license.
 */
private Map<String, SpeedLimit> getSpeedLimits(GeoApiContext context, List<SnappedPoint> points)
        throws Exception {
    Map<String, SpeedLimit> placeSpeeds = new HashMap<>();

    // Pro tip: Save on quota by filtering to unique place IDs.
    for (SnappedPoint point : points) {
        placeSpeeds.put(point.placeId, null);
    }

    String[] uniquePlaceIds =
            placeSpeeds.keySet().toArray(new String[placeSpeeds.keySet().size()]);

    // Loop through the places, one page (API request) at a time.
    for (int i = 0; i < uniquePlaceIds.length; i += PAGE_SIZE_LIMIT) {
        String[] page = Arrays.copyOfRange(uniquePlaceIds, i,
                Math.min(i + PAGE_SIZE_LIMIT, uniquePlaceIds.length));

        // Execute!
        SpeedLimit[] placeLimits = RoadsApi.speedLimits(context, page).await();
        for (SpeedLimit sl : placeLimits) {
            placeSpeeds.put(sl.placeId, sl);
        }
    }

    return placeSpeeds;
}

Veja a seguir os dados do exemplo acima com os limites de velocidade marcados em cada ID de local exclusivo.

Placas de limite de velocidade em um mapa

Interoperação com outras APIs

Um dos benefícios de se retornar IDs de local nas respostas de Snap to Roads é que é possível usá-los em diversas Google Maps APIs. Este exemplo usa o Java Client for Google Maps Services para geocodificar um local retornado da solicitação de Snap to Roads acima.

/**
 * Geocodes a snapped point using the place ID.
 */
private GeocodingResult geocodeSnappedPoint(GeoApiContext context, SnappedPoint point) throws Exception {
    GeocodingResult[] results = GeocodingApi.newRequest(context)
            .place(point.placeId)
            .await();

    if (results.length > 0) {
        return results[0];
    }
    return null;
}

Nesse caso, o marcador de limite de velocidade foi anotado com o endereço da Google Maps Geocoding API.

Endereço geocodificado mostrado em um marcador

Exemplo de código

Considerações

O código por trás deste artigo está disponível como um aplicativo Android para fins ilustrativos. Na prática, você não deve distribuir suas chaves de API de servidor em um aplicativo Android, já que não é possível protegê-la contra acesso não autorizado por parte de terceiros. Em vez disso, para proteger as chaves, você deve implantar códigos voltados para a API como um proxy de servidor e fazer com que o aplicativo Android envie solicitações pelo proxy, garantindo que as solicitações sejam autorizadas.

Download

Faça o download do código no GitHub.

Enviar comentários sobre…

Google Maps Roads API
Google Maps Roads API
Precisa de ajuda? Acesse nossa página de suporte.