使用 Google Maps Android API v2 在两点之间绘制路径

Posted

技术标签:

【中文标题】使用 Google Maps Android API v2 在两点之间绘制路径【英文标题】:Draw path between two points using Google Maps Android API v2 【发布时间】:2013-01-20 02:09:35 【问题描述】:

Google 更改了其 android 地图 API 并引入了 API V2。之前的绘制路径代码不适用于 API V2。

我已经设法使用 API V2 绘制了一条路径。我已经搜索了很多解决方案,但没有找到任何答案。所以我正在分享它的答案。

【问题讨论】:

嗨 zeeshan 我可以使用 google maps android API V2 获取我附近的地方吗?或者我们只能使用 google places API ???任何想法 【参考方案1】:

首先,我们将获得必须在它们之间绘制路线的源点和目的地点。然后我们将这些属性传递给下面的函数。

 public String makeURL (double sourcelat, double sourcelog, double destlat, double destlog )
        StringBuilder urlString = new StringBuilder();
        urlString.append("http://maps.googleapis.com/maps/api/directions/json");
        urlString.append("?origin=");// from
        urlString.append(Double.toString(sourcelat));
        urlString.append(",");
        urlString.append(Double.toString( sourcelog));
        urlString.append("&destination=");// to
        urlString.append(Double.toString( destlat));
        urlString.append(",");
        urlString.append(Double.toString( destlog));
        urlString.append("&sensor=false&mode=driving&alternatives=true");
        urlString.append("&key=YOUR_API_KEY");
        return urlString.toString();
 

此函数将生成我们将发送的 url 以获取 Direction API 响应。然后我们将解析该响应。解析器类是

public class JSONParser 

    static InputStream is = null;
    static JSONObject jObj = null;
    static String json = "";
    // constructor
    public JSONParser() 
    
    public String getJSONFromUrl(String url) 

        // Making HTTP request
        try 
            // defaultHttpClient
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpPost httpPost = new HttpPost(url);

            HttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            is = httpEntity.getContent();           

         catch (UnsupportedEncodingException e) 
            e.printStackTrace();
         catch (ClientProtocolException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();
        
        try 
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    is, "iso-8859-1"), 8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) 
                sb.append(line + "\n");
            

            json = sb.toString();
            is.close();
         catch (Exception e) 
            Log.e("Buffer Error", "Error converting result " + e.toString());
        
        return json;

    

这个解析器会返回给我们字符串。我们会这样称呼它。

JSONParser jParser = new JSONParser();
String json = jParser.getJSONFromUrl(url);

现在我们将把这个字符串发送到我们的 drawpath 函数。绘制路径函数是

public void drawPath(String  result) 

    try 
            //Tranform the string into a json object
           final JSONObject json = new JSONObject(result);
           JSONArray routeArray = json.getJSONArray("routes");
           JSONObject routes = routeArray.getJSONObject(0);
           JSONObject overviewPolylines = routes.getJSONObject("overview_polyline");
           String encodedString = overviewPolylines.getString("points");
           List<LatLng> list = decodePoly(encodedString);
           Polyline line = mMap.addPolyline(new PolylineOptions()
                                    .addAll(list)
                                    .width(12)
                                    .color(Color.parseColor("#05b1fb"))//Google maps blue color
                                    .geodesic(true)
                    );
           /*
           for(int z = 0; z<list.size()-1;z++)
                LatLng src= list.get(z);
                LatLng dest= list.get(z+1);
                Polyline line = mMap.addPolyline(new PolylineOptions()
                .add(new LatLng(src.latitude, src.longitude), new LatLng(dest.latitude,   dest.longitude))
                .width(2)
                .color(Color.BLUE).geodesic(true));
            
           */
     
    catch (JSONException e) 

    
 

以上代码将在 mMap 上绘制路径。 decodePoly 的代码是

private List<LatLng> decodePoly(String encoded) 

    List<LatLng> poly = new ArrayList<LatLng>();
    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;

由于方向调用可能需要时间,所以我们将在异步任务中完成所有这些。 我的异步任务是

private class connectAsyncTask extends AsyncTask<Void, Void, String>
    private ProgressDialog progressDialog;
    String url;
    connectAsyncTask(String urlPass)
        url = urlPass;
    
    @Override
    protected void onPreExecute() 
        // TODO Auto-generated method stub
        super.onPreExecute();
        progressDialog = new ProgressDialog(MainActivity.this);
        progressDialog.setMessage("Fetching route, Please wait...");
        progressDialog.setIndeterminate(true);
        progressDialog.show();
    
    @Override
    protected String doInBackground(Void... params) 
        JSONParser jParser = new JSONParser();
        String json = jParser.getJSONFromUrl(url);
        return json;
    
    @Override
    protected void onPostExecute(String result) 
        super.onPostExecute(result);   
        progressDialog.hide();        
        if(result!=null)
            drawPath(result);
        
    

我希望它会有所帮助。

【讨论】:

没有直接删除路径的方法。我们必须手动删除它。 我将该类添加到我的存储库中,并对其进行了修改以允许多个点并为指示设置标记。 github.com/tato469/Android/tree/master/routes%20googleMaps%20v2 上面的代码创建了太多的短折线,这有时会使地图变得迟钝....我们有更好的选择,只需通过替换上面代码中的以下代码来创建一行,PolylineOptions options = new PolylineOptions().width(5).color(Color.BLUE).geodesic(true); for (int z = 0; z &lt; list.size(); z++) LatLng point = list.get(z); options.add(point); line = myMap.addPolyline(options); 如果您收到错误Requests to this API must be over SSL,请将http 更改为https 我必须在Google Developers Console 中启用适用于Android 的Google Places API 并创建一个服务器密钥,并将其作为key 参数放入makeURL 函数中,否则我得到This IP, site or mobile application is not authorized to use this API key。此外,如 AlvaroSantisteban 所述,将 url 更改为 https 而不是 http【参考方案2】:

不知道我是否应该把这个作为答案......

我使用@Zeeshan0026 的解决方案来绘制路径...问题是,如果我绘制一次路径,然后我确实尝试再次绘制路径,两条路径都会显示,并且会继续...路径显示均匀当标记被删除时......而理想情况下,一旦绘制新路径/标记被删除,旧路径不应该在那里......

通过其他一些关于 SO 的问题,我有以下解决方案

我在Zeeshan的类中添加如下函数

 public void clearRoute()

         for(Polyline line1 : polylines)
         
             line1.remove();
         

         polylines.clear();

     

在我的地图活动中,在绘制路径之前,我调用了这个函数。根据我的应用程序的示例用法是

private Route rt;

rt.clearRoute();

            if (src == null) 
                Toast.makeText(getApplicationContext(), "Please select your Source", Toast.LENGTH_LONG).show();
            else if (Destination == null) 
                Toast.makeText(getApplicationContext(), "Please select your Destination", Toast.LENGTH_LONG).show();
            else if (src.equals(Destination)) 
                Toast.makeText(getApplicationContext(), "Source and Destinatin can not be the same..", Toast.LENGTH_LONG).show();
            else

                rt.drawRoute(mMap, MapsMainActivity.this, src,
                        Destination, false, "en");
            

您可以根据自己的要求使用rt.clearRoute();.. 希望它可以节省其他人的几分钟,并帮助一些初学者解决这个问题..

完整的类代码

见github

编辑: 这是来自 mainactivity 的部分代码..

case R.id.mkrbtn_set_dest:
                    Destination = selmarker.getPosition();
                    destmarker = selmarker;
                    desShape = createRouteCircle(Destination, false);

                    if (src == null) 
                        Toast.makeText(getApplicationContext(),
                                "Please select your Source first...",
                                Toast.LENGTH_LONG).show();
                     else if (src.equals(Destination)) 
                        Toast.makeText(getApplicationContext(),
                                "Source and Destinatin can not be the same..",
                                Toast.LENGTH_LONG).show();
                     else 

                        if (isNetworkAvailable()) 
                            rt.drawRoute(mMap, MapsMainActivity.this, src,
                                    Destination, false, "en");
                            src = null;
                            Destination = null;

                         else 
                            Toast.makeText(
                                    getApplicationContext(),
                                    "Internet Connection seems to be OFFLINE...!",
                                    Toast.LENGTH_LONG).show();

                        

                    

                    break;

编辑 2 根据 cmets

用法:

//variables as data members
GoogleMap mMap;
private Route rt;
static LatLng src;
static LatLng Destination;
//MapsMainActivity is my activity
//false for interim stops for traffic, google
// en language for html description returned

rt.drawRoute(mMap, MapsMainActivity.this, src,
                            Destination, false, "en");

【讨论】:

您好 Zaffar,可以看到您的 MapsMainActivity 课程吗?我是 Android 新手,并试图理解这段代码。我不确定您如何将所有参数传递给 drawroute() 方法。感谢您的帮助 谢谢 Zaffar,但我仍然没有看到很多这些变量是在哪里创建的,即 destmarker。 Destination 类中有什么?我会看看再试一次。【参考方案3】:

在下面的代码 midpointsList 是一个航点的 ArrayList

private String getMapsApiDirectionsUrl(GoogleMap googleMap, LatLng startLatLng, LatLng endLatLng, ArrayList<LatLng> midpointsList) 
    String origin = "origin=" + startLatLng.latitude + "," + startLatLng.longitude;

    String midpoints = "";
    for (int mid = 0; mid < midpointsList.size(); mid++) 
        midpoints += "|" + midpointsList.get(mid).latitude + "," + midpointsList.get(mid).longitude;
    

    String waypoints = "waypoints=optimize:true" + midpoints + "|";

    String destination = "destination=" + endLatLng.latitude + "," + endLatLng.longitude;
    String key = "key=AIzaSyCV1sOa_7vASRBs6S3S6t1KofFvDhjohvI";

    String sensor = "sensor=false";
    String params = origin + "&" + waypoints + "&" + destination + "&" + sensor + "&" + key;
    String output = "json";
    String url = "https://maps.googleapis.com/maps/api/directions/" + output + "?" + params;


    Log.e("url", url);
    parseDirectionApidata(url, googleMap);
    return url;

然后把这个url复制粘贴到你的浏览器中查看下面的代码就是解析这个url

    private void parseDirectionApidata(String url, final GoogleMap googleMap) 

    final JSONObject jsonObject = new JSONObject();

    try 

        AppUtill.getJsonWithHTTPPost(ViewMapActivity.this, 1, new ServiceCallBack() 
            @Override
            public void serviceCallBack(int id, JSONObject jsonResult) throws JSONException 

                if (jsonResult != null) 

                    Log.e("jsonRes", jsonResult.toString());

                    String status = jsonResult.optString("status");

                    if (status.equalsIgnoreCase("ok")) 
                        drawPath(jsonResult, googleMap);
                    

                 else 

                    Toast.makeText(ViewMapActivity.this, "Unable to parse Directions Data", Toast.LENGTH_LONG).show();
                

            
        , url, jsonObject);

     catch (Exception e) 
        e.printStackTrace();

    

然后将结果传递给drawPath方法

    public void drawPath(JSONObject jObject, GoogleMap googleMap) 

    List<List<HashMap<String, String>>> routes = new ArrayList<List<HashMap<String, String>>>();
    JSONArray jRoutes = null;
    JSONArray jLegs = null;
    JSONArray jSteps = null;
    List<LatLng> list = null;
    try 

        Toast.makeText(ViewMapActivity.this, "Drawing Path...", Toast.LENGTH_SHORT).show();
        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<HashMap<String, String>>();

            /** Traversing all legs */
            for (int j = 0; j < jLegs.length(); j++) 
                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 = decodePoly(polyline);
                
                Log.e("list", list.toString());
                routes.add(path);
                Log.e("routes", routes.toString());
                if (list != null) 
                    Polyline line = googleMap.addPolyline(new PolylineOptions()
                            .addAll(list)
                            .width(12)
                            .color(Color.parseColor("#FF0000"))//Google maps blue color #05b1fb
                            .geodesic(true)
                    );
                
            
        
     catch (JSONException e) 
        e.printStackTrace();
    



  private List<LatLng> decodePoly(String encoded) 

    List<LatLng> poly = new ArrayList<LatLng>();
    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;

decode poly 函数是将 Directions API 提供的点(纬度和经度)以编码形式解码

【讨论】:

【参考方案4】:

尝试以下解决方案来使用动画绘制路径,并获取两点之间的时间和距离

DirectionHelper.java

public class DirectionHelper 

    public List<List<HashMap<String, String>>> parse(JSONObject jObject) 

        List<List<HashMap<String, String>>> 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<String, String> hmDistance = new HashMap<String, String>();
                    hmDistance.put("distance", jDistance.getString("text"));

                    /** Getting duration from the json data */
                    jDuration = ((JSONObject) jLegs.get(j)).getJSONObject("duration");
                    HashMap<String, String> hmDuration = new HashMap<String, String>();
                    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<LatLng> list = decodePoly(polyline);

                        /** Traversing all points */
                        for (int l = 0; l < list.size(); l++) 
                            HashMap<String, String> 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<LatLng> decodePoly(String encoded) 

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

GetPathFromLocation.java

public class GetPathFromLocation extends AsyncTask<String, Void, List<List<HashMap<String, String>>>> 

    private Context context;
    private String TAG = "GetPathFromLocation";
    private LatLng source, destination;
    private ArrayList<LatLng> 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<LatLng> 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<LatLng> 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<List<HashMap<String, String>>> 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<List<HashMap<String, String>>> 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<List<HashMap<String, String>>> result) 
        super.onPostExecute(result);

        if (progressDialog.isShowing()) 
            progressDialog.dismiss();
        

        ArrayList<LatLng> 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<HashMap<String, String>> path = result.get(i);

            // Fetching all the points in i-th route
            for (int j = 0; j < path.size(); j++) 
                HashMap<String, String> 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<LatLng> 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<LatLng> points = greyPolyLine.getPoints();
                                int percentValue = (int) valueAnimator.getAnimatedValue();
                                int size = points.size();
                                int newPoints = (int) (size * (percentValue / 100.0f));
                                List<LatLng> 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<LatLng> 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);

现在在您的 Activity 中使用以下代码绘制路径

private GoogleMap mMap;
private ArrayList<LatLng> 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();
            
        );
    

输出

【讨论】:

以上是关于使用 Google Maps Android API v2 在两点之间绘制路径的主要内容,如果未能解决你的问题,请参考以下文章

无法通过 gradle 导入 com.google.maps.android:android-maps-utils

错误:com.google.maps.android.kml 包不存在

import com.google.android.maps.geopoint 无法解析

Android:使用 Google API 获取实时方向,还是与 Google Maps 通信?

com.google.android.gms:play-services-maps 的最佳 sdk 版本是啥?

Android:无法使用 Google Maps Fragment 进行共享元素转换