Es kann losgehen!

Bevor Sie mit der Entwicklung beginnen, lesen Sie bitte unsere Entwicklerdokumentation.

Die Google Maps Roads API aktivieren

Zum Einstieg führen wir Sie durch die Google Developers Console, wo Sie vorab Folgendes tun müssen:

  1. Ein Projekt erstellen oder auswählen
  2. Die Google Maps Roads API aktivieren
  3. Zugehörige Schlüssel erstellen
Weiter

Weiterführende Konzepte

Hinweis: In den folgenden Beispielen wird die Google Maps Roads API im Java Client for Google Maps Services verwendet. Sie können die Konzepte an Ihre bevorzugte Sprache anpassen. Der Python Client, der Go Client und der Node.js Client stehen ebenfalls auf GitHub zur Verfügung.

Daten erfassen

Es gibt viele Möglichkeiten, um an erfasste Standortdaten zu kommen. Im Folgenden werden zwei Techniken beschrieben, mit denen Daten zur Verwendung mit der Funktion Snap to Roads der Google Maps Roads API erfasst werden können.

GPX

GPX ist ein offenes, XML-basiertes Format für den Austausch von Routen, Tracks und Wegpunkten, die von GPS-Geräten erfasst wurden. In diesem Beispiel wird der Parser XmlPull verwendet, ein einfacher XML-Parser, der sowohl für Java-Server als auch für mobile Umgebungen verfügbar ist.

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

Im Folgenden sehen Sie GPX-Rohdaten, die in eine Karte geladen wurden.

Raw GPX data on a map

Android-Standortdienste

Wie Sie GPS-Daten von einem Android-Geräten am besten erfassen, hängt von Ihrem Anwendungsfall ab. Sehen Sie sich den Android-Schulungskurs Empfangen von Standortaktualisierungen sowie die Google Play-Standortbeispiele auf GitHub an.

Lange Pfade verarbeiten

Da die Funktion Snap to Roads den Standort vom gesamten Pfad und nicht von einzelnen Punkten ableitet, müssen Sie beim Verarbeiten langer Pfade (d. h. von Pfaden, die über die Beschränkung auf 100 Punkte pro Anforderung hinausgehen), vorsichtig vorgehen.

Damit die einzelnen Anforderungen als ein einziger langer Pfad behandelt werden, sollten Sie Überlappungen herstellen: Verwenden Sie beispielsweise die letzten Punkte der vorhergehenden Anforderung als erste Punkte der folgenden Anforderung. Wie viele Punkte Sie einschließen sollten, ist von der Genauigkeit Ihrer Daten abhängig. Bei weniger genauen Anforderungen sollten Sie mehr Punkte einschließen.

In diesem Beispiel wird der Java Client for Google Maps Services verwendet, um Anforderungen in einzelnen Abschnitten zu senden. Anschließend werden die Daten, einschließlich der interpolierten Punkte, in der zurückgegebenen Liste wieder verbunden.

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

Im Folgenden sehen Sie die obigen Daten nach dem Ausführen von Snap-to-Road-Anforderungen. Die rote Linie stellt die Rohdaten dar und die blaue die an die Straßen angehefteten („Snapped“) Daten.

Beispiel für an Straßen angeheftete Daten

Effiziente Nutzung Ihres Kontingents

Die Antwort auf eine Snap-to-Roads-Anfrage enthält eine Liste mit Orts-IDs zu den von Ihnen angegebenen Punkten, eventuell mit zusätzlichen Punkten, falls Sie interpolate=true festgelegt haben.

Um Ihr Kontingent an Anforderungen zur Geschwindigkeitsbegrenzung effizient zu nutzen, sollten Sie in den Anforderungen nur eindeutige Orts-IDs abfragen. In diesem Beispiel wird der Java Client for Google Maps Services verwendet, um Geschwindigkeitsbegrenzungen aus einer Liste mit Orts-IDs abzufragen.

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

Im Folgenden sehen Sie die obigen Daten mit der zu jeder eindeutigen Orts-ID angegebenen zulässigen Höchstgeschwindigkeit.

Verkehrszeichen mit zulässiger Höchstgeschwindigkeit in einer Karte

Verwendung in anderen APIs

Einer der Vorteile der Möglichkeit, mit den Snap-to-Road-Antworten Orts-IDs zurückgeben zu lassen, ist, dass Sie die Orts-ID in vielen der Google Maps APIs verwenden können. In diesem Beispiel wird der Java Client for Google Maps Services verwendet, um ein Geocoding für den in der obigen Snap-to-Road-Anforderung zurückgegebenen Ort durchzuführen.

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

Hier wurde der Marker für die Geschwindigkeitsbegrenzung mit der Adresse aus der Google Maps Geocoding API versehen.

Durch Geocoding ermittelte Adresse an einem Marker

Beispielcode

Überlegungen

Der Code zu diesem Artikel ist zur Veranschaulichung als einzelne Android-App verfügbar. In der Praxis sollten Sie Ihre serverseitigen API-Schlüssel nicht in Android-Apps bereitstellen, da der Schlüssel nicht vor unbefugtem Zugriff durch Dritte geschützt werden kann. Stattdessen sollten Sie den Schlüssel schützen, indem Sie den API-Code als serverseitigen Proxy bereitstellen und die Android-App Anforderungen über den Proxy senden lassen. So stellen Sie sicher, dass die Anforderungen autorisiert sind.

Download

Laden Sie den Code von GitHub herunter.

Feedback geben zu...

Google Maps Roads API
Google Maps Roads API