مفاهیم پیشرفته

داده‌ها را بدست آورید

روش‌های زیادی برای به دست آوردن داده‌های مکانی جمع‌آوری‌شده وجود دارد. در اینجا دو تکنیک برای به دست آوردن داده‌ها جهت استفاده با ویژگی snap to roads از Roads API را شرح می‌دهیم.

جی پی ایکس

GPX یک فرمت باز مبتنی بر XML برای به اشتراک گذاری مسیرها، مسیرها و نقاط مسیر ثبت شده توسط دستگاه‌های GPS است. این مثال از تجزیه‌گر XmlPull ، یک تجزیه‌گر 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 روی نقشه

سرویس‌های مکان‌یابی اندروید

بهترین روش برای دریافت داده‌های GPS از دستگاه اندروید بسته به مورد استفاده شما متفاوت است. نگاهی به کلاس آموزشی اندروید در مورد دریافت به‌روزرسانی‌های موقعیت مکانی و همچنین نمونه‌های موقعیت مکانی گوگل پلی در گیت‌هاب بیندازید.

مسیرهای طولانی را پردازش کنید

از آنجایی که ویژگی snap to roads مکان را بر اساس کل مسیر و نه نقاط منفرد استنباط می‌کند، باید هنگام پردازش مسیرهای طولانی (یعنی مسیرهایی که بیش از محدودیت ۱۰۰ نقطه در هر درخواست هستند) مراقب باشید.

برای اینکه درخواست‌های منفرد را به عنوان یک مسیر طولانی در نظر بگیرید، باید مقداری همپوشانی را در نظر بگیرید، به طوری که نقاط پایانی درخواست قبلی به عنوان نقاط اولیه درخواست بعدی در نظر گرفته شوند. تعداد نقاطی که باید در نظر گرفته شوند به دقت داده‌های شما بستگی دارد. برای درخواست‌های با دقت پایین، باید نقاط بیشتری را در نظر بگیرید.

این مثال از کلاینت جاوا برای سرویس‌های نقشه‌های گوگل برای ارسال درخواست‌های صفحه‌بندی‌شده استفاده می‌کند و سپس داده‌ها، شامل نقاط درون‌یابی‌شده، را دوباره به لیست برگردانده‌شده متصل می‌کند.

/**
 * 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 تنظیم کنید، احتمالاً نقاط بیشتری نیز اضافه خواهد شد.

برای استفاده کارآمد از سهمیه مجاز خود برای درخواست محدودیت سرعت، باید فقط شناسه‌های مکان منحصر به فرد را در درخواست خود جستجو کنید. این مثال از کلاینت جاوا برای سرویس‌های نقشه‌های گوگل برای جستجوی محدودیت‌های سرعت از لیستی از شناسه‌های مکان استفاده می‌کند.

/**
 * 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 برگردانده می‌شوند این است که می‌توانید از شناسه مکان در بسیاری از APIهای پلتفرم نقشه‌های گوگل استفاده کنید. این مثال از کلاینت جاوا برای سرویس‌های نقشه‌های گوگل برای ژئوکد کردن مکانی که از درخواست snap to road فوق برگردانده شده است، استفاده می‌کند.

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

در اینجا نشانگر محدودیت سرعت با آدرسی از API مربوط به Geocoding حاشیه‌نویسی شده است.

آدرس جغرافیایی نشان داده شده روی نشانگر

کد نمونه

ملاحظات

کدی که از این سند پشتیبانی می‌کند، برای اهداف توضیحی به صورت یک برنامه اندروید واحد در دسترس است. در عمل، شما نباید کلیدهای API سمت سرور خود را در یک برنامه اندروید توزیع کنید، زیرا کلید شما نمی‌تواند در برابر دسترسی غیرمجاز از شخص ثالث ایمن شود. در عوض، برای ایمن‌سازی کلیدهای خود، باید کد API-محور را به عنوان یک پروکسی سمت سرور مستقر کنید و از برنامه اندروید خود بخواهید که درخواست‌ها را با استفاده از پروکسی ارسال کند تا مطمئن شوید که درخواست‌ها مجاز هستند.

دانلود

کد را از گیت‌هاب دانلود کنید.