Possible Duplicate:
Google Maps output=kml broken?

可能重复:谷歌地图输出= kml坏了吗?

I started to get Error when I'm trying to retrieve Google Directions using KML data since few days. The Error seems that the URL I'm requesting doesn't retreieve KML data anymore, it returns a whole page. I followed this in order to achieve that.

几天后,当我尝试使用KML数据检索Google方向时,我开始出现错误。错误似乎我要求的URL不再修复KML数据,它返回整页。为此,我遵循了这一点。

What is the solution for this? Is there any alternatives?

这是什么解决方案?还有其他选择吗?

1 个解决方案

#1


89

Update:

更新:

Since Android Google Maps v2 is now used, the code needs to be adjusted to work on v2 maps which can be found here.

由于现在使用的是Android Google地图v2,因此需要调整代码以适用于v2地图,可在此处找到。


Original Answer:

原答案:

This way of extracting the Google Directions from Google by parsing the KML file is no longer available since 27 July 2012 (because Google has changed the structure of retrieving Google Directions, now you can only get it by JSON or XML), it is time to migrate your code to JSON instead of KML.

自2012年7月27日以来,这种通过解析KML文件从Google中提取Google方向的方式已不再可用(因为Google已经更改了检索Google方向的结构,现在您只能通过JSON或XML获取),现在是时候了将代码迁移到JSON而不是KML。

I did it by creating 6 classes like this:

我通过创建这样的6个类来完成它:

Parser.java:

Parser.java:

public interface Parser {
        public Route parse();
}

XMLParser.java:

XMLParser.java:

public class XMLParser {
        // names of the XML tags
        protected static final String MARKERS = "markers";
        protected static final String MARKER = "marker";

        protected URL feedUrl;

        protected XMLParser(final String feedUrl) {
                try {
                        this.feedUrl = new URL(feedUrl);
                } catch (MalformedURLException e) {
                        //Log.e(e.getMessage(), "XML parser - " + feedUrl);
                }
        }

        protected InputStream getInputStream() {
                try {
                        return feedUrl.openConnection().getInputStream();
                } catch (IOException e) {
                        //Log.e(e.getMessage(), "XML parser - " + feedUrl);
                        return null;
                }
        }
}

Segment.java:

Segment.java:

public class Segment {
        /** Points in this segment. **/
        private GeoPoint start;
        /** Turn instruction to reach next segment. **/
        private String instruction;
        /** Length of segment. **/
        private int length;
        /** Distance covered. **/
        private double distance;

        /**
         * Create an empty segment.
         */

        public Segment() {
        }


        /**
         * Set the turn instruction.
         * @param turn Turn instruction string.
         */

        public void setInstruction(final String turn) {
                this.instruction = turn;
        }

        /**
         * Get the turn instruction to reach next segment.
         * @return a String of the turn instruction.
         */

        public String getInstruction() {
                return instruction;
        }

        /**
         * Add a point to this segment.
         * @param point GeoPoint to add.
         */

        public void setPoint(final GeoPoint point) {
                start = point;
        }

        /** Get the starting point of this 
         * segment.
         * @return a GeoPoint
         */

        public GeoPoint startPoint() {
                return start;
        }

        /** Creates a segment which is a copy of this one.
         * @return a Segment that is a copy of this one.
         */

        public Segment copy() {
                final Segment copy = new Segment();
                copy.start = start;
                copy.instruction = instruction;
                copy.length = length;
                copy.distance = distance;
                return copy;
        }

        /**
         * @param length the length to set
         */
        public void setLength(final int length) {
                this.length = length;
        }

        /**
         * @return the length
         */
        public int getLength() {
                return length;
        }

        /**
         * @param distance the distance to set
         */
        public void setDistance(double distance) {
                this.distance = distance;
        }

        /**
         * @return the distance
         */
        public double getDistance() {
                return distance;
        }

}

Route.java:

Route.java:

public class Route {
        private String name;
        private final List<GeoPoint> points;
        private List<Segment> segments;
        private String copyright;
        private String warning;
        private String country;
        private int length;
        private String polyline;

        public Route() {
                points = new ArrayList<GeoPoint>();
                segments = new ArrayList<Segment>();
        }

        public void addPoint(final GeoPoint p) {
                points.add(p);
        }

        public void addPoints(final List<GeoPoint> points) {
                this.points.addAll(points);
        }

        public List<GeoPoint> getPoints() {
                return points;
        }

        public void addSegment(final Segment s) {
                segments.add(s);
        }

        public List<Segment> getSegments() {
                return segments;
        }

        /**
         * @param name the name to set
         */
        public void setName(final String name) {
                this.name = name;
        }

        /**
         * @return the name
         */
        public String getName() {
                return name;
        }

        /**
         * @param copyright the copyright to set
         */
        public void setCopyright(String copyright) {
                this.copyright = copyright;
        }

        /**
         * @return the copyright
         */
        public String getCopyright() {
                return copyright;
        }

        /**
         * @param warning the warning to set
         */
        public void setWarning(String warning) {
                this.warning = warning;
        }

        /**
         * @return the warning
         */
        public String getWarning() {
                return warning;
        }

        /**
         * @param country the country to set
         */
        public void setCountry(String country) {
                this.country = country;
        }

        /**
         * @return the country
         */
        public String getCountry() {
                return country;
        }

        /**
         * @param length the length to set
         */
        public void setLength(int length) {
                this.length = length;
        }

        /**
         * @return the length
         */
        public int getLength() {
                return length;
        }


        /**
         * @param polyline the polyline to set
         */
        public void setPolyline(String polyline) {
                this.polyline = polyline;
        }

        /**
         * @return the polyline
         */
        public String getPolyline() {
                return polyline;
        }

}

GoogleParser.java:

GoogleParser.java:

public class GoogleParser extends XMLParser implements Parser {
        /** Distance covered. **/
        private int distance;

        public GoogleParser(String feedUrl) {
                super(feedUrl);
        }

        /**
         * Parses a url pointing to a Google JSON object to a Route object.
         * @return a Route object based on the JSON object.
         */

        public Route parse() {
                // turn the stream into a string
                final String result = convertStreamToString(this.getInputStream());
                //Create an empty route
                final Route route = new Route();
                //Create an empty segment
                final Segment segment = new Segment();
                try {
                        //Tranform the string into a json object
                        final JSONObject json = new JSONObject(result);
                        //Get the route object
                        final JSONObject jsonRoute = json.getJSONArray("routes").getJSONObject(0);
                        //Get the leg, only one leg as we don't support waypoints
                        final JSONObject leg = jsonRoute.getJSONArray("legs").getJSONObject(0);
                        //Get the steps for this leg
                        final JSONArray steps = leg.getJSONArray("steps");
                        //Number of steps for use in for loop
                        final int numSteps = steps.length();
                        //Set the name of this route using the start & end addresses
                        route.setName(leg.getString("start_address") + " to " + leg.getString("end_address"));
                        //Get google's copyright notice (tos requirement)
                        route.setCopyright(jsonRoute.getString("copyrights"));
                        //Get the total length of the route.
                        route.setLength(leg.getJSONObject("distance").getInt("value"));
                        //Get any warnings provided (tos requirement)
                        if (!jsonRoute.getJSONArray("warnings").isNull(0)) {
                                route.setWarning(jsonRoute.getJSONArray("warnings").getString(0));
                        }
                        /* Loop through the steps, creating a segment for each one and
                         * decoding any polylines found as we go to add to the route object's
                         * map array. Using an explicit for loop because it is faster!
                         */
                        for (int i = 0; i < numSteps; i++) {
                                //Get the individual step
                                final JSONObject step = steps.getJSONObject(i);
                                //Get the start position for this step and set it on the segment
                                final JSONObject start = step.getJSONObject("start_location");
                                final GeoPoint position = new GeoPoint((int) (start.getDouble("lat")*1E6), 
                                        (int) (start.getDouble("lng")*1E6));
                                segment.setPoint(position);
                                //Set the length of this segment in metres
                                final int length = step.getJSONObject("distance").getInt("value");
                                distance += length;
                                segment.setLength(length);
                                segment.setDistance(distance/1000);
                                //Strip html from google directions and set as turn instruction
                                segment.setInstruction(step.getString("html_instructions").replaceAll("<(.*?)*>", ""));
                                //Retrieve & decode this segment's polyline and add it to the route.
                                route.addPoints(decodePolyLine(step.getJSONObject("polyline").getString("points")));
                                //Push a copy of the segment to the route
                                route.addSegment(segment.copy());
                        }
                } catch (JSONException e) {
                        Log.e(e.getMessage(), "Google JSON Parser - " + feedUrl);
                }
                return route;
        }

        /**
         * Convert an inputstream to a string.
         * @param input inputstream to convert.
         * @return a String of the inputstream.
         */

        private static String convertStreamToString(final InputStream input) {
        final BufferedReader reader = new BufferedReader(new InputStreamReader(input));
        final StringBuilder sBuf = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sBuf.append(line);
            }
        } catch (IOException e) {
                Log.e(e.getMessage(), "Google parser, stream2string");
        } finally {
            try {
                input.close();
            } catch (IOException e) {
                Log.e(e.getMessage(), "Google parser, stream2string");
            }
        }
        return sBuf.toString();
    }

        /**
         * Decode a polyline string into a list of GeoPoints.
         * @param poly polyline encoded string to decode.
         * @return the list of GeoPoints represented by this polystring.
         */

        private List<GeoPoint> decodePolyLine(final String poly) {
                int len = poly.length();
                int index = 0;
                List<GeoPoint> decoded = new ArrayList<GeoPoint>();
                int lat = 0;
                int lng = 0;

                while (index < len) {
                int b;
                int shift = 0;
                int result = 0;
                do {
                        b = poly.charAt(index++) - 63;
                        result |= (b & 0x1f) << shift;
                        shift += 5;
                } while (b >= 0x20);
                int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
                lat += dlat;

                shift = 0;
                result = 0;
                do {
                        b = poly.charAt(index++) - 63;
                        result |= (b & 0x1f) << shift;
                        shift += 5;
                } while (b >= 0x20);
                        int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
                        lng += dlng;

                decoded.add(new GeoPoint(
                        (int) (lat*1E6 / 1E5), (int) (lng*1E6 / 1E5)));
                }

                return decoded;
                }
}

RouteOverlay.java:

RouteOverlay.java:

public class RouteOverlay extends Overlay {
        /** GeoPoints representing this routePoints. **/
        private final List<GeoPoint> routePoints;
        /** Colour to paint routePoints. **/
        private int colour;
        /** Alpha setting for route overlay. **/
        private static final int ALPHA = 120;
        /** Stroke width. **/
        private static final float STROKE = 4.5f;
        /** Route path. **/
        private final Path path;
        /** Point to draw with. **/
        private final Point p;
        /** Paint for path. **/
        private final Paint paint;


        /**
         * Public constructor.
         * 
         * @param route Route object representing the route.
         * @param defaultColour default colour to draw route in.
         */

        public RouteOverlay(final Route route, final int defaultColour) {
                super();
                routePoints = route.getPoints();
                colour = defaultColour;
                path = new Path();
                p = new Point();
                paint = new Paint();
        }

        @Override
        public final void draw(final Canvas c, final MapView mv,
                        final boolean shadow) {
                super.draw(c, mv, shadow);

                paint.setColor(colour);
                paint.setAlpha(ALPHA);
                paint.setAntiAlias(true);
                paint.setStrokeWidth(STROKE);
                paint.setStyle(Paint.Style.STROKE);

                redrawPath(mv);
                c.drawPath(path, paint);
        }

        /**
         * Set the colour to draw this route's overlay with.
         * 
         * @param c  Int representing colour.
         */
        public final void setColour(final int c) {
                colour = c;
        }

        /**
         * Clear the route overlay.
         */
        public final void clear() {
                routePoints.clear();
        }

        /**
         * Recalculate the path accounting for changes to
         * the projection and routePoints.
         * @param mv MapView the path is drawn to.
         */

        private void redrawPath(final MapView mv) {
                final Projection prj = mv.getProjection();
                path.rewind();
                final Iterator<GeoPoint> it = routePoints.iterator();
                prj.toPixels(it.next(), p);
                path.moveTo(p.x, p.y);
                while (it.hasNext()) {
                        prj.toPixels(it.next(), p);
                        path.lineTo(p.x, p.y);
                }
                path.setLastPoint(p.x, p.y);
        }

}

And then you do this inside the Activity that includes the Map:

然后在包含Map的Activity中执行此操作:

1-Add this function:

1 - 添加此功能:

private Route directions(final GeoPoint start, final GeoPoint dest) {
    Parser parser;
    //https://developers.google.com/maps/documentation/directions/#JSON <- get api
    String jsonURL = "http://maps.googleapis.com/maps/api/directions/json?";
    final StringBuffer sBuf = new StringBuffer(jsonURL);
    sBuf.append("origin=");
    sBuf.append(start.getLatitudeE6()/1E6);
    sBuf.append(',');
    sBuf.append(start.getLongitudeE6()/1E6);
    sBuf.append("&destination=");
    sBuf.append(dest.getLatitudeE6()/1E6);
    sBuf.append(',');
    sBuf.append(dest.getLongitudeE6()/1E6);
    sBuf.append("&sensor=true&mode=driving");
    parser = new GoogleParser(sBuf.toString());
    Route r =  parser.parse();
    return r;
}

2- Add this in onCreate() function:

2-在onCreate()函数中添加它:

MapView mapView = (MapView) findViewById(R.id.mapview); //or you can declare it directly with the API key
Route route = directions(new GeoPoint((int)(26.2*1E6),(int)(50.6*1E6)), new GeoPoint((int)(26.3*1E6),(int)(50.7*1E6)));
RouteOverlay routeOverlay = new RouteOverlay(route, Color.BLUE);
mapView.getOverlays().add(routeOverlay);
mapView.invalidate();

EDIT: If you get an exception, please use directions() function in an AsyncTask to avoid network processing on the UI thread.

编辑:如果出现异常,请使用AsyncTask中的directions()函数来避免UI线程上的网络处理。

更多相关文章

  1. Android开源代码解读の地图照片应用Panoramio的实现详解(六)
  2. Android百度地图定位定到了海里,定到了非洲
  3. 我怎样才能获得移动方向
  4. 【Android】策略模式封装百度地图路线规划模块
  5. java 百度地图判断两点距离1
  6. 程序员的发展方向有哪些

随机推荐

  1. 【android】用camera实现view的伪3D的效
  2. H5调用Android原生Api
  3. Android View绘制及事件(一)屏幕的视图层级
  4. android sdk 中apidemo如何加载到eclipse
  5. Android(安卓)studio导入eclipse项目
  6. TextView属性大全!技术干货
  7. 关于移动端踩过的坑
  8. Android NDK 使用第一步,编译c文件,声明jni
  9. 谈谈Android的那些事
  10. 从Android界面开发谈起