您已全部設定完成!

若要開始開發,請參閱我們的開發人員文件

啟用 Google Maps Roads API

為協助您開始,我們將先引導您使用「Google 開發人員控制台」來執行一些動作:

  1. 建立或選擇專案
  2. 啟用 Google Maps Roads API
  3. 建立適當的金鑰
繼續

進階概念



注意:下列範例在 Java Client for Google Maps Services 中使用了 Google Maps Roads API。 您可適度修改這些概念,使之適用於您選用的語言。 Python ClientGo ClientNode.js Client 亦可於 GitHub 取得。

取得資料

取得位置資料的方法有許多種。 在這裡,我們會描述兩種能取得與 Google Maps Roads API貼齊道路功能搭配使用之資料的技術。

GPX

GPX 是開放式 XML 型格式,可用於分享由 GPS 裝置擷取的路線、軌跡與途經地點。 此範例使用 XmlPull 剖析器,這是一個可供 Java 伺服器與行動環境使用的輕量化 XML 剖析器。

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

以下是一些載入到地圖上的原始 GPX 資料。

地圖上的原始 GPX 資料

Android 位置服務

從 Android 裝置擷取 GPS 資料的最佳方法,會因使用案例而異。 請參考 Receiving Location Updates 以及 Google Play Location samples on GitHub 的 Android 訓練課程。

處理長路徑

由於貼齊道路功能是根據完整路徑(而非個別的點)來推論位置,您在處理長路徑時便必須更加留意(例如,超過「每個要求可以有 100 點」限制的路徑)。

為了將多個個別要求視為單一長路徑,您應該包括一些重疊的點,以便將上一個要求的最後一個點包含為下一個要求的第一個點。

要包含的點數目將取決於資料的精確度。 您應該為低精確度要求包括更多的點。

此範例使用 Java Client for Google Maps Services 來傳送「已瀏覽」的要求,然後將資料(包含內插計算的點)重新加入到傳回的清單中。

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

以下是執行貼齊道路要求後的上述資料。 紅線是原始資料,而藍線則是貼齊的資料。

已貼齊至道路的資料範例

配額的有效使用

貼齊道路要求的回應包含您所提供地點相對應的地點 ID 清單(如果已設定 interpolate=true,則可能會收到額外的地點)。

針對速度限制要求,如果要有效使用允許的配額,您應該只在您的要求中查詢唯一的地點 ID。 此範例使用 Java Client for Google Maps Services 從地點 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;
}

以下是包含在每個唯一地點 ID 標記之速度限制的上述資料。

地圖上的速度限制號誌

與其他 API 的相互影響

貼齊道路回應中傳回地點 ID 的其中一個好處,就是可以在許多 Google Maps API 上使用這些地點 ID。

此範例使用 Java Client for Google Maps Services 來對一個由上述「貼齊道路」要求傳回的地點進行地理編碼。

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

在這裡,速度限制標記已被加上來自 Google Maps Geocoding API 的地址做為註解。

標記上顯示的地理編碼地址

範例程式碼

注意事項

支援此文章的程式碼,是基於說明之目的以單一 Android 應用程式的形式提供。 實務上,您不應該在 Android 應用程式中散佈伺服器端 API 金鑰,因為您將無法保護您的金鑰不受來自第三方的未經授權存取。 如果要保護金鑰,您應該將面對 API 的程式碼部署為伺服器端 Proxy,並讓您的 Android 應用程式透過 Proxy 傳送要求,以確保這些要求都已獲得授權。

下載

GitHub 下載程式碼。

傳送您對下列選項的寶貴意見...

這個網頁
Google Maps Roads API
Google Maps Roads API
需要協助嗎?請前往我們的支援網頁