Draw path between two points using Google Maps Android API v2

前端 未结 4 1121
日久生厌
日久生厌 2020-11-22 11:46

Google changed its map API for Android and introduced API V2. The previous codes for drawing path are not working with API V2.

I have managed to draw a path with API

4条回答
  •  孤街浪徒
    2020-11-22 12:15

    Try below solution to draw path with animation and also get time and distance between two points.

    DirectionHelper.java

    public class DirectionHelper {
    
        public List>> parse(JSONObject jObject) {
    
            List>> routes = new ArrayList<>();
            JSONArray jRoutes;
            JSONArray jLegs;
            JSONArray jSteps;
            JSONObject jDistance = null;
            JSONObject jDuration = null;
    
            try {
    
                jRoutes = jObject.getJSONArray("routes");
    
                /** Traversing all routes */
                for (int i = 0; i < jRoutes.length(); i++) {
                    jLegs = ((JSONObject) jRoutes.get(i)).getJSONArray("legs");
                    List path = new ArrayList<>();
    
                    /** Traversing all legs */
                    for (int j = 0; j < jLegs.length(); j++) {
    
                        /** Getting distance from the json data */
                        jDistance = ((JSONObject) jLegs.get(j)).getJSONObject("distance");
                        HashMap hmDistance = new HashMap();
                        hmDistance.put("distance", jDistance.getString("text"));
    
                        /** Getting duration from the json data */
                        jDuration = ((JSONObject) jLegs.get(j)).getJSONObject("duration");
                        HashMap hmDuration = new HashMap();
                        hmDuration.put("duration", jDuration.getString("text"));
    
                        /** Adding distance object to the path */
                        path.add(hmDistance);
    
                        /** Adding duration object to the path */
                        path.add(hmDuration);
    
                        jSteps = ((JSONObject) jLegs.get(j)).getJSONArray("steps");
    
                        /** Traversing all steps */
                        for (int k = 0; k < jSteps.length(); k++) {
                            String polyline = "";
                            polyline = (String) ((JSONObject) ((JSONObject) jSteps.get(k)).get("polyline")).get("points");
                            List list = decodePoly(polyline);
    
                            /** Traversing all points */
                            for (int l = 0; l < list.size(); l++) {
                                HashMap hm = new HashMap<>();
                                hm.put("lat", Double.toString((list.get(l)).latitude));
                                hm.put("lng", Double.toString((list.get(l)).longitude));
                                path.add(hm);
                            }
                        }
                        routes.add(path);
                    }
                }
    
            } catch (JSONException e) {
                e.printStackTrace();
            } catch (Exception e) {
            }
    
    
            return routes;
        }
    
        //Method to decode polyline points
        private List decodePoly(String encoded) {
    
            List 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;
        }
    }
    

    GetPathFromLocation.java

    public class GetPathFromLocation extends AsyncTask>>> {
    
        private Context context;
        private String TAG = "GetPathFromLocation";
        private LatLng source, destination;
        private ArrayList wayPoint;
        private GoogleMap mMap;
        private boolean animatePath, repeatDrawingPath;
        private DirectionPointListener resultCallback;
        private ProgressDialog progressDialog;
    
        //https://www.mytrendin.com/draw-route-two-locations-google-maps-android/
        //https://www.androidtutorialpoint.com/intermediate/google-maps-draw-path-two-points-using-google-directions-google-map-android-api-v2/
    
        public GetPathFromLocation(Context context, LatLng source, LatLng destination, ArrayList wayPoint, GoogleMap mMap, boolean animatePath, boolean repeatDrawingPath, DirectionPointListener resultCallback) {
            this.context = context;
            this.source = source;
            this.destination = destination;
            this.wayPoint = wayPoint;
            this.mMap = mMap;
            this.animatePath = animatePath;
            this.repeatDrawingPath = repeatDrawingPath;
            this.resultCallback = resultCallback;
        }
    
        synchronized public String getUrl(LatLng source, LatLng dest, ArrayList wayPoint) {
    
            String url = "https://maps.googleapis.com/maps/api/directions/json?sensor=false&mode=driving&origin="
                    + source.latitude + "," + source.longitude + "&destination=" + dest.latitude + "," + dest.longitude;
            for (int centerPoint = 0; centerPoint < wayPoint.size(); centerPoint++) {
                if (centerPoint == 0) {
                    url = url + "&waypoints=optimize:true|" + wayPoint.get(centerPoint).latitude + "," + wayPoint.get(centerPoint).longitude;
                } else {
                    url = url + "|" + wayPoint.get(centerPoint).latitude + "," + wayPoint.get(centerPoint).longitude;
                }
            }
            url = url + "&key=" + context.getResources().getString(R.string.google_api_key);
    
            return url;
        }
    
        public int getRandomColor() {
            Random rnd = new Random();
            return Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
        }
    
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            progressDialog = new ProgressDialog(context);
            progressDialog.setMessage("Please wait...");
            progressDialog.setIndeterminate(false);
            progressDialog.setCancelable(false);
            progressDialog.show();
        }
    
        @Override
        protected List>> doInBackground(String... url) {
    
            String data;
    
            try {
                InputStream inputStream = null;
                HttpURLConnection connection = null;
                try {
                    URL directionUrl = new URL(getUrl(source, destination, wayPoint));
                    connection = (HttpURLConnection) directionUrl.openConnection();
                    connection.connect();
                    inputStream = connection.getInputStream();
    
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                    StringBuffer stringBuffer = new StringBuffer();
    
                    String line = "";
                    while ((line = bufferedReader.readLine()) != null) {
                        stringBuffer.append(line);
                    }
    
                    data = stringBuffer.toString();
                    bufferedReader.close();
    
                } catch (Exception e) {
                    Log.e(TAG, "Exception : " + e.toString());
                    return null;
                } finally {
                    inputStream.close();
                    connection.disconnect();
                }
                Log.e(TAG, "Background Task data : " + data);
    
                //Second AsyncTask
    
                JSONObject jsonObject;
                List>> routes = null;
    
                try {
                    jsonObject = new JSONObject(data);
                    // Starts parsing data
                    DirectionHelper helper = new DirectionHelper();
                    routes = helper.parse(jsonObject);
                    Log.e(TAG, "Executing Routes : "/*, routes.toString()*/);
    
                    return routes;
    
                } catch (Exception e) {
                    Log.e(TAG, "Exception in Executing Routes : " + e.toString());
                    return null;
                }
    
            } catch (Exception e) {
                Log.e(TAG, "Background Task Exception : " + e.toString());
                return null;
            }
        }
    
        @Override
        protected void onPostExecute(List>> result) {
            super.onPostExecute(result);
    
            if (progressDialog.isShowing()) {
                progressDialog.dismiss();
            }
    
            ArrayList points;
            PolylineOptions lineOptions = null;
            String distance = "";
            String duration = "";
    
            // Traversing through all the routes
            for (int i = 0; i < result.size(); i++) {
                points = new ArrayList<>();
                lineOptions = new PolylineOptions();
    
                // Fetching i-th route
                List> path = result.get(i);
    
                // Fetching all the points in i-th route
                for (int j = 0; j < path.size(); j++) {
                    HashMap point = path.get(j);
    
                    if (j == 0) {    // Get distance from the list
                        distance = (String) point.get("distance");
                        continue;
                    } else if (j == 1) { // Get duration from the list
                        duration = (String) point.get("duration");
                        continue;
                    }
    
                    double lat = Double.parseDouble(point.get("lat"));
                    double lng = Double.parseDouble(point.get("lng"));
                    LatLng position = new LatLng(lat, lng);
    
                    points.add(position);
                }
    
                // Adding all the points in the route to LineOptions
                lineOptions.addAll(points);
                lineOptions.width(8);
                lineOptions.color(Color.RED);
                //lineOptions.color(getRandomColor());
    
                if (animatePath) {
                    final ArrayList finalPoints = points;
                    ((AppCompatActivity) context).runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            PolylineOptions polylineOptions;
                            final Polyline greyPolyLine, blackPolyline;
                            final ValueAnimator polylineAnimator;
    
                            LatLngBounds.Builder builder = new LatLngBounds.Builder();
                            for (LatLng latLng : finalPoints) {
                                builder.include(latLng);
                            }
                            polylineOptions = new PolylineOptions();
                            polylineOptions.color(Color.RED);
                            polylineOptions.width(8);
                            polylineOptions.startCap(new SquareCap());
                            polylineOptions.endCap(new SquareCap());
                            polylineOptions.jointType(ROUND);
                            polylineOptions.addAll(finalPoints);
                            greyPolyLine = mMap.addPolyline(polylineOptions);
    
                            polylineOptions = new PolylineOptions();
                            polylineOptions.width(8);
                            polylineOptions.color(Color.WHITE);
                            polylineOptions.startCap(new SquareCap());
                            polylineOptions.endCap(new SquareCap());
                            polylineOptions.zIndex(5f);
                            polylineOptions.jointType(ROUND);
    
                            blackPolyline = mMap.addPolyline(polylineOptions);
                            polylineAnimator = ValueAnimator.ofInt(0, 100);
                            polylineAnimator.setDuration(5000);
                            polylineAnimator.setInterpolator(new LinearInterpolator());
                            polylineAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                                @Override
                                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                                    List points = greyPolyLine.getPoints();
                                    int percentValue = (int) valueAnimator.getAnimatedValue();
                                    int size = points.size();
                                    int newPoints = (int) (size * (percentValue / 100.0f));
                                    List p = points.subList(0, newPoints);
                                    blackPolyline.setPoints(p);
                                }
                            });
    
                            polylineAnimator.addListener(new Animator.AnimatorListener() {
                                @Override
                                public void onAnimationStart(Animator animation) {
    
                                }
    
                                @Override
                                public void onAnimationEnd(Animator animation) {
                                    if (repeatDrawingPath) {
                                        List greyLatLng = greyPolyLine.getPoints();
                                        if (greyLatLng != null) {
                                            greyLatLng.clear();
    
                                        }
                                        polylineAnimator.start();
                                    }
                                }
    
                                @Override
                                public void onAnimationCancel(Animator animation) {
                                    polylineAnimator.cancel();
                                }
    
                                @Override
                                public void onAnimationRepeat(Animator animation) {
                                }
                            });
                            polylineAnimator.start();
                        }
                    });
                }
    
                Log.e(TAG, "PolylineOptions Decoded");
            }
    
            // Drawing polyline in the Google Map for the i-th route
            if (resultCallback != null && lineOptions != null)
                resultCallback.onPath(lineOptions, distance, duration);
        }
    }
    

    DirectionPointListener

    public interface DirectionPointListener {
        public void onPath(PolylineOptions polyLine,String distance,String duration);
    }
    

    Now draw path using below code in your Activity

    private GoogleMap mMap;
    private ArrayList wayPoint = new ArrayList<>();
    private SupportMapFragment mapFragment;
    
    mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
            mapFragment.getMapAsync(this);
    
    @Override
        public void onMapReady(GoogleMap googleMap) {
            mMap = googleMap;
    
            mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
                @Override
                public void onMapLoaded() {
                    LatLngBounds.Builder builder = new LatLngBounds.Builder();
    
                    /*Add Source Marker*/
                    MarkerOptions markerOptions = new MarkerOptions();
                    markerOptions.position(source);
                    markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
                    mMap.addMarker(markerOptions);
                    builder.include(source);
    
                    /*Add Destination Marker*/
                    markerOptions = new MarkerOptions();
                    markerOptions.position(destination);
                    markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
                    mMap.addMarker(markerOptions);
                    builder.include(destination);
    
                    LatLngBounds bounds = builder.build();
    
                    int width = mapFragment.getView().getMeasuredWidth();
                    int height = mapFragment.getView().getMeasuredHeight();
                    int padding = (int) (width * 0.15); // offset from edges of the map 10% of screen
    
                    CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, width, height, padding);
    
                    mMap.animateCamera(cu);
    
                    new GetPathFromLocation(context, source, destination, wayPoint, mMap, true, false, new DirectionPointListener() {
                        @Override
                        public void onPath(PolylineOptions polyLine, String distance, String duration) {
                            mMap.addPolyline(polyLine);
                            Log.e(TAG, "onPath :: Distance :: " + distance + " Duration :: " + duration);
    
                            binding.txtDistance.setText(String.format(" %s", distance));
                            binding.txtDuration.setText(String.format(" %s", duration));
                        }
                    }).execute();
                }
            });
        }
    

    OutPut

    I hope this can help you!

    Thank You.

提交回复
热议问题