Concepts avancés

Acquisition de données

Il existe plusieurs manières d'obtenir des données de géolocalisation collectées. Nous décrivons ici deux techniques d'acquisition de données à utiliser avec la fonctionnalité Accès direct aux routes le Roads API.

GPX

GPX est un format XML ouvert qui permet de partager des itinéraires, des tracés et des points de cheminement. capturées par les GPS. Cet exemple utilise l'analyseur XmlPull, Analyseur XML léger disponible pour les environnements de serveur Java et mobiles

/**
 * 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;
}

Voici quelques données GPX brutes chargées sur une carte.

Données GPX brutes sur une carte

Services de localisation Android

La meilleure façon de collecter des données GPS à partir d'un appareil Android dépend de votre de ce cas d'utilisation. Consultez la formation Android sur la réception de position mises à jour, ainsi que les exemples de localisation Google Play sur GitHub

Traiter des chemins longs

Étant donné que la fonctionnalité Aligner sur les routes détermine le lieu à partir du tracé complet, plutôt que sur des points individuels, vous devez faire attention chemins (c'est-à-dire les chemins dépassant la limite de 100 points par requête).

Pour traiter les requêtes individuelles comme un chemin unique, vous devez inclure certains chevauchements, de sorte que les derniers points de la demande précédente soient inclus comme premiers points de la requête suivante. Nombre de points à inclure dépend de l'exactitude de vos données. Vous devriez inclure plus de points pour les requêtes peu précises.

Cet exemple utilise le client Java pour les services Google Maps afin d'envoyer des requêtes paginées et puis réintègre les données, y compris les points interpolés, dans la liste renvoyée.

/**
 * 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;
}

Voici les données ci-dessus après avoir exécuté les requêtes Snap to Roads. Le rouge la ligne correspond aux données brutes et la ligne bleue aux données ancrées.

Exemple de données alignées sur les routes

Utilisation efficace des quotas

La réponse à une requête snap to routes inclut une liste d'ID de lieu. qui correspondent aux points que vous avez fournis, éventuellement avec des points supplémentaires si vous définissez interpolate=true.

Afin d'utiliser efficacement votre quota autorisé pour une demande de limitation de vitesse, vous ne devez rechercher que des identifiants de lieu uniques dans votre demande. Cet exemple utilise le client Java pour les services Google Maps afin d'interroger les limites de vitesse à partir d'une liste de lieux ID.

/**
 * 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;
}

Voici les données ci-dessus, avec les limitations de vitesse indiquées pour chaque identifiant de lieu unique.

Panneaux de limitation de vitesse sur une carte

Interagir avec d'autres API

L'un des avantages du renvoi des identifiants de lieu dans la fonction Aligner sur les routes est que vous pouvez utiliser l'identifiant de lieu dans de nombreuses API Google Maps Platform. Cet exemple utilise le client Java pour les services Google Maps. pour géocoder un lieu renvoyé par la requête de tracé sur la route ci-dessus.

/**
 * 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;
}

Ici, le indicateur de limitation de vitesse est annoté avec l'adresse de API Geocoding.

Adresse géocodée affichée sur un repère

Exemple de code

Remarques

Le code sous-jacent à cet article est disponible en tant qu'application Android unique pour à des fins d'illustration. En pratique, vous ne devez pas distribuer vos fichiers Clés API dans une application Android, car elles ne peuvent pas être protégées contre des accès non autorisés l'accès d'un tiers. Pour sécuriser vos clés, vous devez plutôt déployer le code API en tant que proxy côté serveur et faire en sorte que votre application Android envoie des requêtes via le proxy, en s'assurant que les requêtes sont autorisées.

Télécharger

Téléchargez le code sur GitHub.