المفاهيم المتقدمة

الحصول على البيانات

هناك طرق عديدة للحصول على بيانات الموقع الجغرافي التي تم جمعها. نصف هنا طريقتَين للحصول على البيانات لاستخدامها مع ميزة "الربط بالطرق" في 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.

معالجة المسارات الطويلة

بما أنّ ميزة الربط بالطرق تستنتج الموقع الجغرافي استنادًا إلى المسار الكامل، وليس إلى نقاط فردية، عليك توخي الحذر عند معالجة المسارات الطويلة (أي المسارات التي تتجاوز الحدّ الأقصى المسموح به وهو 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;
}

في ما يلي البيانات من أعلاه بعد تشغيل طلبات "الربط بالطرق". الخط الأحمر هو البيانات الأولية والخط الأزرق هو البيانات المرتبطة.

مثال على البيانات التي تم محاذاتها مع الطرق

الاستخدام الفعّال للحصة

يتضمّن الردّ على طلب الربط بالطرق قائمة بمعرّفات الأماكن التي تتطابق مع النقاط التي قدّمتها، وقد يتضمّن نقاطًا إضافية إذا ضبطت 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;
}

في ما يلي البيانات من أعلاه مع وضع علامات على حدود السرعة عند كل معرّف مكان فريد.

إشارات حدود السرعة على الخريطة

التفاعل مع واجهات برمجة التطبيقات الأخرى

من المزايا التي يوفّرها عرض معرّفات الأماكن في ردود الربط بالطرق أنّه يمكنك استخدام معرّف المكان في العديد من واجهات برمجة التطبيقات في Google Maps Platform. يستخدم هذا المثال 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;
}

تم هنا إضافة تعليق توضيحي إلى علامة حدّ السرعة باستخدام العنوان من Geocoding API.

عنوان تم ترميزه جغرافيًا ويظهر على علامة

نموذج الرموز البرمجية

الاعتبارات

تتوفّر الرموز البرمجية التي تدعم هذا المستند كتطبيق Android واحد لأغراض التوضيح. في الواقع، لا يجب توزيع مفاتيح واجهة برمجة التطبيقات من جهة الخادم في تطبيق Android لأنّه لا يمكن حماية مفتاحك من الوصول غير المصرّح به من جهة خارجية. بدلاً من ذلك، لحماية مفاتيحك، عليك نشر الرمز البرمجي الذي يواجه واجهة برمجة التطبيقات كوكيل من جهة الخادم، وجعل تطبيق Android يرسل الطلبات باستخدام الوكيل، للتأكّد من أنّ الطلبات مسموح بها.

تنزيل

يمكنك تنزيل الرمز البرمجي من GitHub.