83

Google は Android 用の地図 API を変更し、API V2 を導入しました。パスを描画するための以前のコードは、API V2 では機能しません。

API V2でパスを描くことができました。私は解決策をたくさん探しましたが、答えは見つかりませんでした。だから私はその答えを共有しています。

4

4 に答える 4

171

まず最初に、ルートを描画する必要がある始点と終点を取得します。次に、これらの属性を以下の関数に渡します。

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

この関数は、Direction API の応答を取得するために送信する URL を作成します。次に、その応答を解析します。パーサークラスは

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

それが役立つことを願っています。

于 2013-02-05T07:58:24.157 に答える
3

これを答えにするべきかどうかわからない...

@ Zeeshan0026のソリューションを使用してパスを描画しました...そして問題は、パスを一度描画してからもう一度パスを描画しようとすると、2つのパスが両方とも表示され、これが続くことでした...マーカーがあった場合でもパスが表示されます削除されました...理想的には、新しいパスが描画されたりマーカーが削除されたりすると、古いパスはそこにあるべきではありません..

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を編集

利用方法 :

//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");
于 2015-06-16T21:53:02.410 に答える
0

以下のソリューションを試して、アニメーションでパスを描画し、2 点間の時間と距離も取得してください。

方向ヘルパー.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);
    }
}

方向点リスナー

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

アクティビティで以下のコードを使用してパスを描画します

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

出力

ここに画像の説明を入力

于 2020-06-01T15:05:32.650 に答える