Acquérir des 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é snap to routes de Roads API.
GPX
GPX est un format XML ouvert permettant de partager des routes, des tracés et des points de cheminement enregistrés par les appareils GPS. Cet exemple utilise l'analyseur XmlPull, un analyseur XML léger disponible à la fois pour le serveur Java et les environnements 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.
Services de localisation Android
La meilleure façon de capturer des données GPS à partir d'un appareil Android dépend de votre cas d'utilisation. Consultez la formation Android sur la réception de mises à jour de position, ainsi que les exemples de localisation Google Play sur GitHub.
Traiter les chemins longs
Étant donné que la fonctionnalité Ancrer aux routes déduit l'emplacement en fonction du chemin complet plutôt que de points individuels, vous devez être prudent lorsque vous traitez les longs trajets (c'est-à-dire les chemins dépassant la limite de 100 points par requête).
Afin de traiter les requêtes individuelles comme un chemin long, vous devez inclure un certain chevauchement, de sorte que les points finaux de la requête précédente soient inclus en tant que premiers points de la requête suivante. Le nombre de points à inclure dépend de la précision de vos données. Vous devez inclure plus de points pour les demandes de faible précision.
Cet exemple utilise le client Java pour les services Google Maps pour envoyer des requêtes paginées, 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. La ligne rouge correspond aux données brutes et la ligne bleue aux données ancrées.
Utilisation efficace des quotas
La réponse à une requête snap to routes inclut une liste d'ID de lieu correspondant aux points que vous avez fournis. Si vous définissez interpolate=true
, des points supplémentaires peuvent être ajoutés.
Pour utiliser efficacement votre quota autorisé pour une requête de limites de vitesse, vous ne devez interroger que les ID de lieu uniques dans votre requête. Cet exemple utilise le client Java pour les services Google Maps pour interroger les limites de vitesse à partir d'une liste d'ID de lieu.
/** * 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.
Interaction avec d'autres API
L'un des avantages des ID de lieu renvoyés dans les réponses snap to Roads est que vous pouvez les utiliser 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 "Snap to Road" 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 repère de limitation de vitesse a été annoté avec l'adresse de l'API Geocoding.
Exemple de code
Points à prendre en compte
Le code utilisé dans cet article est disponible sous la forme d'une application Android unique à des fins d'illustration. En pratique, vous ne devez pas distribuer vos clés API côté serveur dans une application Android, car elles ne peuvent pas être protégées contre les accès non autorisés provenant d'un tiers. Pour sécuriser vos clés, vous devez plutôt déployer le code côté API en tant que proxy côté serveur et faire en sorte que votre application Android envoie des requêtes via le proxy, en vous assurant qu'elles sont autorisées.
Télécharger
Téléchargez le code sur GitHub.