Thu thập dữ liệu
Có nhiều cách để lấy dữ liệu vị trí đã thu thập. Ở đây, chúng ta mô tả 2 kỹ thuật thu thập dữ liệu để sử dụng với tính năng căn chỉnh theo đường của Roads API.
GPX
GPX là một định dạng mở dựa trên XML để chia sẻ các tuyến đường, đường đi và điểm đánh dấu do thiết bị GPS ghi lại. Ví dụ này sử dụng trình phân tích cú pháp XmlPull, một trình phân tích cú pháp XML gọn nhẹ có sẵn cho cả máy chủ Java và môi trường di động.
/** * 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; }
Dưới đây là một số dữ liệu GPX thô được tải lên bản đồ.
Dịch vụ vị trí trên Android
Cách tốt nhất để thu thập dữ liệu GPS từ một thiết bị Android sẽ khác nhau tuỳ thuộc vào trường hợp sử dụng của bạn. Hãy xem lớp học đào tạo về Android về Nhận thông tin cập nhật về vị trí, cũng như các mẫu vị trí của Google Play trên GitHub.
Xử lý các đường dẫn dài
Vì tính năng căn chỉnh theo đường suy luận vị trí dựa trên toàn bộ đường dẫn, thay vì các điểm riêng lẻ, nên bạn cần cẩn thận khi xử lý các đường dẫn dài (tức là đường dẫn vượt quá giới hạn 100 điểm cho mỗi yêu cầu).
Để coi các yêu cầu riêng lẻ là một đường dẫn dài, bạn nên đưa vào một số điểm trùng lặp, sao cho các điểm cuối cùng của yêu cầu trước được đưa vào làm các điểm đầu tiên của yêu cầu tiếp theo. Số lượng điểm cần đưa vào tuỳ thuộc vào độ chính xác của dữ liệu. Bạn nên thêm nhiều điểm hơn cho các yêu cầu có độ chính xác thấp.
Ví dụ này sử dụng Java Client for Google Maps Services để gửi các yêu cầu được phân trang, sau đó kết hợp lại dữ liệu (bao gồm cả các điểm được nội suy) vào danh sách được trả về.
/** * 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; }
Sau đây là dữ liệu từ trên sau khi chạy các yêu cầu khớp với đường. Đường màu đỏ là dữ liệu thô và đường màu xanh dương là dữ liệu được điều chỉnh.
Sử dụng hạn mức hiệu quả
Phản hồi cho yêu cầu căn chỉnh theo đường bao gồm danh sách mã địa điểm liên kết với các điểm mà bạn cung cấp, có thể có thêm các điểm nếu bạn đặt interpolate=true
.
Để sử dụng hiệu quả hạn mức được phép cho yêu cầu về giới hạn tốc độ, bạn chỉ nên truy vấn mã địa điểm duy nhất trong yêu cầu của mình. Ví dụ này sử dụng Java Client for Google Maps Services để truy vấn giới hạn tốc độ từ danh sách mã địa điểm.
/** * 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; }
Dưới đây là dữ liệu từ ví dụ trên, trong đó giới hạn tốc độ được đánh dấu tại mỗi mã địa điểm riêng biệt.
Tương tác với các API khác
Một trong những lợi ích của việc nhận được mã địa điểm trong các phản hồi snap to roads (gắn vào đường) là bạn có thể sử dụng mã địa điểm này trên nhiều API của Google Maps Platform. Ví dụ này sử dụng Java Client for Google Maps Services để mã hoá địa lý một địa điểm được trả về từ yêu cầu chụp nhanh đến đường ở trên.
/** * 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; }
Ở đây, điểm đánh dấu giới hạn tốc độ đã được chú thích bằng địa chỉ từ Geocoding API.
Mã mẫu
Lưu ý
Mã hỗ trợ tài liệu này có sẵn dưới dạng một ứng dụng Android duy nhất cho mục đích minh hoạ. Trên thực tế, bạn không nên phân phối khoá API phía máy chủ trong một ứng dụng Android vì khoá của bạn không được bảo mật để chống lại hành vi truy cập trái phép của bên thứ ba. Thay vào đó, để bảo mật khoá, bạn nên triển khai mã hướng đến API dưới dạng một proxy phía máy chủ và yêu cầu ứng dụng Android của bạn gửi yêu cầu bằng proxy để đảm bảo các yêu cầu được uỷ quyền.
Tải xuống
Tải mã xuống từ GitHub.