แนวคิดขั้นสูง

รับข้อมูล

คุณรับข้อมูลตำแหน่งที่เก็บรวบรวมได้หลายวิธี ในที่นี้เราจะอธิบายเทคนิค 2 อย่าง ในการรับข้อมูลเพื่อใช้กับฟีเจอร์ Snap to Roads ของ Roads API

GPX

GPX เป็นรูปแบบ XML แบบเปิดสำหรับการแชร์เส้นทาง เส้นทางเดิน และจุดอ้างอิงที่อุปกรณ์ GPS บันทึกไว้ ตัวอย่างนี้ใช้ตัวแยกวิเคราะห์ XmlPull ซึ่งเป็นตัวแยกวิเคราะห์ XML ขนาดเล็กที่พร้อมให้บริการทั้งในสภาพแวดล้อมเซิร์ฟเวอร์ Java และสภาพแวดล้อมอุปกรณ์เคลื่อนที่

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

วิธีที่ดีที่สุดในการบันทึกข้อมูล GPS จากอุปกรณ์ Android จะแตกต่างกันไปตามกรณีการใช้งาน โปรดดูคลาสการฝึกอบรม Android เกี่ยวกับ การรับข้อมูลอัปเดตตำแหน่ง รวมถึง ตัวอย่างตำแหน่งของ Google Play บน GitHub

ประมวลผลเส้นทางยาว

เนื่องจากฟีเจอร์ Snap to Roads อนุมานตำแหน่งตามเส้นทางทั้งหมด ไม่ใช่จุดแต่ละจุด คุณจึงต้องระมัดระวังเมื่อประมวลผลเส้นทางยาว (นั่นคือ เส้นทางที่มีจุดมากกว่าขีดจำกัด 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;
}

นี่คือข้อมูลจากด้านบนหลังจากเรียกใช้คำขอ Snap to Roads เส้นสีแดงคือข้อมูลดิบ และเส้นสีน้ำเงินคือข้อมูลที่ Snap แล้ว

ตัวอย่างข้อมูลที่สแนปกับถนน

การใช้โควต้าอย่างมีประสิทธิภาพ

การตอบกลับคำขอ Snap to Roads จะมีรายการรหัสสถานที่ ที่จับคู่กับจุดที่คุณระบุไว้ ซึ่งอาจมีจุดเพิ่มเติมหากคุณ ตั้งค่า interpolate=true

หากต้องการใช้โควต้าที่อนุญาตสำหรับคำขอจำกัดความเร็วอย่างมีประสิทธิภาพ คุณควรค้นหารหัสสถานที่ที่ไม่ซ้ำกันในคำขอเท่านั้น ตัวอย่างนี้ใช้ Java Client for Google Maps Services เพื่อค้นหาข้อมูลจำกัดความเร็วจากรายการรหัสสถานที่

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

นี่คือข้อมูลจากด้านบนที่มีการทำเครื่องหมายข้อมูลจำกัดความเร็วที่รหัสสถานที่ที่ไม่ซ้ำกันแต่ละรายการ

ป้ายจำกัดความเร็วบนแผนที่

การทำงานร่วมกับ API อื่นๆ

ข้อดีอย่างหนึ่งของการแสดงผลรหัสสถานที่ในการตอบกลับSnap to Roads คือคุณสามารถใช้รหัสสถานที่ใน Google Maps Platform API หลายรายการได้ ตัวอย่างนี้ใช้ Java Client for Google Maps Services เพื่อระบุพิกัดทางภูมิศาสตร์ของสถานที่ที่แสดงผลจากคำขอ Snap to Roads ด้านบน

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

ในที่นี้มีการใส่คำอธิบายประกอบเครื่องหมายข้อมูลจำกัดความเร็วด้วยที่อยู่จาก Geocoding API

ที่อยู่ที่เข้ารหัสพิกัดภูมิศาสตร์ซึ่งแสดงบนเครื่องหมาย

โค้ดตัวอย่าง

ข้อควรพิจารณา

โค้ดที่รองรับเอกสารนี้พร้อมให้บริการเป็นแอป Android เดียวเพื่อวัตถุประสงค์ในการอธิบาย ในทางปฏิบัติ คุณไม่ควรเผยแพร่คีย์ API ฝั่งเซิร์ฟเวอร์ในแอป Android เนื่องจากคีย์ของคุณจะไม่ได้รับการปกป้องจากการเข้าถึงที่ไม่ได้รับอนุญาตจากบุคคลที่สาม แต่คุณควรทำให้โค้ดที่เชื่อมต่อกับ API ใช้งานได้เป็นพร็อกซีฝั่งเซิร์ฟเวอร์ และให้แอป Android ส่งคำขอโดยใช้พร็อกซีเพื่อให้แน่ใจว่าคำขอได้รับอนุญาต

ดาวน์โหลด

ดาวน์โหลดโค้ดจาก GitHub