【问题标题】:Google Maps Android V2 and Direction APIGoogle Maps Android V2 和 Direction API
【发布时间】:2012-12-17 15:09:13
【问题描述】:

我正在开发一个应用程序,我需要知道当前用户位置和兴趣点之间的路径。

我使用的是 android 2.3.3、google maps android v2 和 direction api。 我的问题是我找到的所有代码都是旧版本的地图,我也尝试调整代码但我失败了。我尝试在 LatLng 中更改 GeoPoint(此新版本不支持)。 问题是我无法显示路径,为此我创建了一条新的折线并将其添加到地图中。

我发布我的代码:

解析器:

public interface Parser {
    public Route parse();
}

XML解析器

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

JsonParser(解析google方向json)

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

    public JsonParser(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 LatLng position = new LatLng(start.getDouble("lat"), start.getDouble("lng"));
                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 LatLng.
     * @param poly polyline encoded string to decode.
     * @return the list of GeoPoints represented by this polystring.
     */

    private List<LatLng> decodePolyLine(final String poly) {
        int len = poly.length();
        int index = 0;
        List<LatLng> decoded = new LinkedList<LatLng>();
        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 LatLng((lat / 1E5),(lng / 1E5)));
        }

        return decoded;
    }
}

路线(保存 json 信息)

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

    public Route() {
        points = new LinkedList<LatLng>();
        segments = new LinkedList<Segment>();
    }

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

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

    public List<LatLng> 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;
     }

}

细分:

public class Segment {
    /** Points in this segment. **/
    private LatLng 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 LatLng to add.
     */

    public void setPoint(LatLng point) {
            start = point;
    }

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

    public LatLng 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;
    }

}

我的MainActivity(由于用户本地化,有326行代码,你可以在google developer site上找到,所以我们可以假设有两个静态点A和B,我想从A到B):

public class MainActivity extends FragmentActivity{
    private GoogleMap map;
    private Marker currentLocation;
    private PolylineOptions pathLine;
    private LatLng imhere = new LatLng(41.8549038,12.4618208);
        private LatLng poi = new LatLng(41.89000,12.49324);


    private LocationManager mLocationManager;
    private Handler mHandler;
    private boolean mUseBoth;
    private Context context;
    // Keys for maintaining UI states after rotation.
    private static final String KEY_BOTH = "use_both";
    // UI handler codes.
    private static final int UPDATE_LATLNG = 2;

    private static final int FIVE_SECONDS = 5000;
    private static final int THREE_METERS = 3;
    private static final int TWO_MINUTES = 1000 * 60 * 2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
        Marker colosseoMarker  = map.addMarker(new MarkerOptions()
        .position(colosseo)
        .title("Start")
        .snippet("poi")
        .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher)));

                Marker current pos = map.addMarker(new MarkerOptions()
        .position(imhere)
        .title("i'm here")
        .snippet("here!")
        .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher)));

        context =this ;
        map.setOnMarkerClickListener(new OnMarkerClickListener() {

            @Override
            public boolean onMarkerClick(Marker marker) {
                final String[] options = {"Calcola il Percorso"};
                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                builder.setTitle("Ottieni Informazioni aggiuntive");
                builder.setPositiveButton("Calcola Percorso",new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog,int id) {
                        LatLng start = new LatLng(imhere.latitude,imhere.longitude);
                        LatLng dest = new LatLng(poi.latitude, poi.longitude);
                        Route route = drawPath(start, dest);

                        List<LatLng> list= route.getPoints();

if(pathLine!= null) pathline =null;                         
pathLine = new PolylineOptions();

                        pathLine.addAll(list);
                        pathLine.color(Color.rgb(0,191,255));

                        map.addPolyline(pathLine);

                    }
                  });

                AlertDialog alert = builder.create();
                alert.show();
                Toast.makeText(MainActivity.this, marker.getSnippet(),Toast.LENGTH_SHORT).show();
                return true;
            }
        });


                    map.animateCamera(CameraUpdateFactory.newLatLngZoom(imhere, 12));
                }
            }
        };
        // Get a reference to the LocationManager object.
        mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    }


     private Route drawPath(LatLng start, LatLng dest) {
            Parser parser;
            String jsonURL = "http://maps.google.com/maps/api/directions/json?";
            final StringBuffer sBuf = new StringBuffer(jsonURL);
            sBuf.append("origin=");
            sBuf.append(start.latitude);
            sBuf.append(',');
            sBuf.append(start.longitude);
            sBuf.append("&destination=");
            sBuf.append(dest.latitude);
            sBuf.append(',');
            sBuf.append(dest.longitude);
            sBuf.append("&sensor=true&mode=walking");
            parser = new JsonParser(sBuf.toString());
            Route r =  parser.parse();
            return r;
        }
}

每个建议都被接受

【问题讨论】:

  • 在 JsonParser 中我改变了 decoded.add(new LatLng((lat*1E6 / 1E5),(lng*1E6 / 1E5)));带解码的.add(new LatLng((lat/ 1E5),(lng / 1E5)));获得双倍(我认为......)并且它的工作,但有时当我要求它重新设置路径时应用程序停止工作
  • Activity 中的一些问题。使用drawPath 的JSON 调用应该在AsyncTask 中完成。在使用map 之前,请确保它已准备好使用,请参阅SDK 中的示例代码setUpMapIfNeeded 建议在onResume() 中运行。 map.clear()在重绘之前清除地图。
  • 是的,谢谢,我使用AsyncTask,现在更好了。现在我正在尝试使用setUpMapIfNeededmap.clear()
  • 试试这个解决方案 [这里][1] 我认为它对你有用 [1]:stackoverflow.com/questions/14495030/…
  • 我完全按照你的方式解决了。只是一个问题,你为什么要加倍?它也可以在没有的情况下工作(我知道是因为我不投)。只是想知道:) 无论如何谢谢你

标签: android google-maps-mobile google-maps-android-api-2


【解决方案1】:

如果您不需要自定义代码,请尝试使用此库 https://github.com/jd-alexander/Google-Directions-Android,只需几行代码即可完成您需要的操作。

【讨论】:

    【解决方案2】:

    我正在做以下事情。我想这会对你有所帮助。

     Marker interestedMarker;
        private void plot_direction(){
            if (currentSelectedPin !=null) {
                LatLng origin = new LatLng(currentLocation.getLatitude(),currentLocation.getLongitude());
                new GoogleMapDirection(getActivity(), origin, interestedMarker.getPosition(), new DirectionListener() {
                    @Override
                    public void onDirectionPointsReceived(ArrayList<RouteModel> routeList, String distance, String duration) {
                        PolylineOptions lineOptions = null;
                        for (RouteModel route : routeList) {
                            lineOptions = new PolylineOptions();
                            lineOptions.addAll(route.getSteps());
                            lineOptions.width(20);
                            lineOptions.color(ContextCompat.getColor(getContext(), R.color.map_route));
                        }
    
                        //For removing existing line
                        if (routeMap!=null){
                            routeMap.remove();
                        }
                        if(lineOptions != null) {
                            routeMap = mMap.addPolyline(lineOptions);
                        }
                    }
                });
            }
        }
    

    GoogleMapDirection 类如下

    public class GoogleMapDirection {
        private DirectionListener listener;
        public GoogleMapDirection(final Activity activity, LatLng source, LatLng destination, DirectionListener listener){
            this.listener=listener;
            String url = null;
            try {
                url = "https://maps.googleapis.com/maps/api/directions/json?origin="+ URLEncoder.encode(Double.toString(source.latitude) + "," + Double.toString(source.longitude), "UTF-8") + "&destination=" + URLEncoder.encode(Double.toString(destination.latitude) + "," + Double.toString(destination.longitude), "UTF-8") + "&mode=driving&sensor=false&key=" + Config.GOOGLE_API_BROWSER_KEY;
                Print.d(url);
            } catch (UnsupportedEncodingException e) {
                Print.exception(e);
            }
    
            JSONObject parameters = new JSONObject();
            VolleyJsonBodyRequest.execute(activity, url, parameters, new VolleyResponseListener() {
                @Override
                public void onResponse(JSONObject response) {
                    try {
                        if (response.getString("status").equals("OK")) {
                            String distance = "NA";
                            String duration = "NA";
                            if (response.has("routes")){
                                JSONArray routesJArray = response.getJSONArray("routes");
                                if (routesJArray.length()>0){
                                    if (routesJArray.getJSONObject(0).has("legs")){
                                        JSONArray legsJArray = routesJArray.getJSONObject(0).getJSONArray("legs");
                                        if (legsJArray.length()>0){
                                            JSONObject firstLegsJObj = legsJArray.getJSONObject(0);
                                            if (firstLegsJObj.has("distance")){
                                                distance = firstLegsJObj.getJSONObject("distance").getString("text");
                                            }
                                            if (firstLegsJObj.has("duration")){
                                                duration = firstLegsJObj.getJSONObject("duration").getString("text");
                                            }
    
    
                                        }
                                    }
                                }
                            }
                            GoogleResponseParserTask task = new GoogleResponseParserTask(distance,duration);
                            task.execute(response);
                        }
                    } catch (JSONException e) {
                        Print.exception(e);
                        DialogWindow.showOK(activity, Config.MESSAGE_INVALID_RESPONSE_FORMAT, new DialogListenerOK() {
                            @Override
                            public void onOK() {
    
                            }
                        });
                    }
                }
                @Override
                public void onErrorResponse(VolleyResponseError error) {
                    Print.e(error.getDetails());
                    DialogWindow.showOK(activity, error.getMessage(), new DialogListenerOK() {
                        @Override
                        public void onOK() {
    
                        }
                    });
                }
            });
        }
    
    
        /**
         * A class to parse the Google Places in JSON format
         */
        private class GoogleResponseParserTask extends AsyncTask<JSONObject, Integer, ArrayList<RouteModel>> {
    
            String distance;
            String duration;
            private GoogleResponseParserTask(String distance, String duration){
                this.distance=distance;
                this.duration=duration;
    
            }
            @Override
            protected ArrayList<RouteModel> doInBackground(JSONObject... jsonResponse) {
                ArrayList<RouteModel> routes = null;
                try {
                    routes = parse(jsonResponse[0]);
                } catch (Exception e) {
                    Print.exception(e);
                }
                return routes;
            }
            @Override
            protected void onPostExecute(ArrayList<RouteModel> result) {
                listener.onDirectionPointsReceived(result,distance,duration);
            }
        }
    
    
        /** Receives a JSONObject and returns a list of lists containing latitude and longitude */
        public ArrayList<RouteModel> parse(JSONObject jObject){
    
            ArrayList<RouteModel> routeList = new ArrayList<>() ;
            JSONArray jRoutes;
            JSONArray jLegs;
            JSONArray jSteps;
    
            try {
    
                jRoutes = jObject.getJSONArray("routes");
    
                /** Traversing all routes */
                for(int i=0;i<jRoutes.length();i++){
                    jLegs = ( (JSONObject)jRoutes.get(i)).getJSONArray("legs");
                    ArrayList<LatLng> pointList = new ArrayList<>();
    
                    /** Traversing all legs */
                    for(int j=0;j<jLegs.length();j++){
                        jSteps = ((JSONObject)jLegs.get(j)).getJSONArray("steps");
                        JSONObject jDistance = ((JSONObject) jLegs.get(j)).getJSONObject("distance");
                        JSONObject jDuration = ((JSONObject) jLegs.get(j)).getJSONObject("duration");
    
                        String distance = jDistance.getString("text");
                        String duration = jDuration.getString("text");
    
                        /** Traversing all steps */
                        for(int k=0;k<jSteps.length();k++){
                            String polyline = (String)((JSONObject)((JSONObject)jSteps.get(k)).get("polyline")).get("points");
                            ArrayList<LatLng> stepList = decodePoly(polyline);
    
                            /** Traversing all points */
                            for(int l=0;l<stepList.size();l++){
                                LatLng point = new LatLng((stepList.get(l)).latitude, (stepList.get(l)).longitude);
                                pointList.add(point);
                            }
                        }
                        RouteModel routeModel = new RouteModel();
                        routeModel.setSteps(pointList);
                        routeModel.setDistance(distance);
                        routeModel.setDuration(duration);
                        routeList.add(routeModel);
                    }
                }
    
            } catch (JSONException e) {
                e.printStackTrace();
            }catch (Exception e){
            }
    
    
            return routeList;
        }
    
    
        /**
         * Method to decode polyline points
         * Courtesy : http://jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java
         * */
        private ArrayList<LatLng> decodePoly(String encoded) {
    
            ArrayList<LatLng> poly = new ArrayList<>();
            int index = 0, len = encoded.length();
            int lat = 0, lng = 0;
    
            while (index < len) {
                int b, shift = 0, result = 0;
                do {
                    b = encoded.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 = encoded.charAt(index++) - 63;
                    result |= (b & 0x1f) << shift;
                    shift += 5;
                } while (b >= 0x20);
                int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
                lng += dlng;
    
                LatLng p = new LatLng((((double) lat / 1E5)),
                        (((double) lng / 1E5)));
                poly.add(p);
            }
    
            return poly;
        }
    

    【讨论】:

      猜你喜欢
      • 2013-03-24
      • 2023-04-02
      • 1970-01-01
      • 2016-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-30
      相关资源
      最近更新 更多