计算路点之间的总距离android google api

时间:2017-06-02 08:20:08

标签: android google-maps google-maps-api-3 google-distancematrix-api

我开发了一个应用程序,用于绘制起点和目的地之间的路线,用户也可以沿着该路径标记一些路标,并且路线将被正确绘制。但是我只能在地图上标记2个位置时才能获得距离。如果我标记2,3个位置它将不会给我距离。这些是我的代码,

public class DirectionsJSONParser {

/** Receives a JSONObject and returns a list of lists containing latitude and longitude */
public List<List<HashMap<String,String>>> parse(JSONObject jObject){

    List<List<HashMap<String, String>>> routes = new ArrayList<List<HashMap<String,String>>>();
    JSONArray jRoutes = null;
    JSONArray jLegs = null;
    JSONArray jSteps = null;
    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<HashMap<String, String>>();

            /** 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<String, String>();
                        hm.put("lat", Double.toString(((LatLng)list.get(l)).latitude) );
                        hm.put("lng", Double.toString(((LatLng)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
 * Courtesy : jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java
 * */
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 String downloadUrl(String strUrl) throws IOException {
    String data = "";
    InputStream iStream = null;
    HttpURLConnection urlConnection = null;
    try{
        URL url = new URL(strUrl);

        // Creating an http connection to communicate with url
        urlConnection = (HttpURLConnection) url.openConnection();

        // Connecting to url
        urlConnection.connect();

        // Reading data from url
        iStream = urlConnection.getInputStream();

        BufferedReader br = new BufferedReader(new InputStreamReader(iStream));

        StringBuffer sb  = new StringBuffer();

        String line = "";
        while( ( line = br.readLine())  != null){
            sb.append(line);
        }

        data = sb.toString();

        br.close();

    }catch(Exception e){
        Log.d("Error downloading url", e.toString());
    }finally{
        iStream.close();
        urlConnection.disconnect();
    }
    return data;
}



// Fetches data from url passed
private class DownloadTask extends AsyncTask<String, Void, String> {

    // Downloading data in non-ui thread
    @Override
    protected String doInBackground(String... url) {

        // For storing data from web service
        String data = "";

        try{
            // Fetching the data from web service
            data = downloadUrl(url[0]);
        }catch(Exception e){
            Log.d("Background Task",e.toString());
        }
        return data;
    }

    // Executes in UI thread, after the execution of
    // doInBackground()
    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);

        ParserTask parserTask = new ParserTask();

        // Invokes the thread for parsing the JSON data
        parserTask.execute(result);

    }
}

/** A class to parse the Google Places in JSON format */
private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String,String>>> >{

    // Parsing the data in non-ui thread
    @Override
    protected List<List<HashMap<String, String>>> doInBackground(String... jsonData) {

        JSONObject jObject;
        List<List<HashMap<String, String>>> routes = null;

        try{
            jObject = new JSONObject(jsonData[0]);
            DirectionsJSONParser parser = new DirectionsJSONParser();

            // Starts parsing data
            routes = parser.parse(jObject);
        }catch(Exception e){
            e.printStackTrace();
        }
        return routes;
    }

    // Executes in UI thread, after the parsing process
    @Override
    protected void onPostExecute(List<List<HashMap<String, String>>> result) {
        ArrayList<LatLng> points = null;
        PolylineOptions lineOptions = null;
        MarkerOptions markerOptions = new MarkerOptions();
        String distance = "";
        String duration = "";

        if(result.size()<1){
            Toast.makeText(getBaseContext(), "No Points", Toast.LENGTH_SHORT).show();
            return;
        }

        // Traversing through all the routes
        for(int i=0;i<result.size();i++){
            points = new ArrayList<LatLng>();
            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(2);
            lineOptions.color(Color.RED);
        }

        tvDistanceDuration.setText("Distance:"+distance + ", Duration:"+duration);

        // Drawing polyline in the Google Map for the i-th route
        map.addPolyline(lineOptions);
    }

}
  

我以前要求的网址

 String parameters = str_origin+"&"+str_dest+"&"+sensor+"&"+waypoints;

    // Output format
    String output = "json";

    // Building the url to the web service
    String url = "https://maps.googleapis.com/maps/api/directions/"+output+"?"+parameters;

Error I found when I used 4 points with 2 way points

这是在线上的onPostExecute方法,

 double lat = Double.parseDouble(point.get("lat"));
 double lng = Double.parseDouble(point.get("lng"));
 LatLng position = new LatLng(lat, lng);

我在这里做错了什么?

1 个答案:

答案 0 :(得分:1)

你应该通过改造来尝试这个。

将此代码置于MainActivity中的按钮单击: -

<强> MainActivity.java

public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener, OnMapReadyCallback {

    private static final String LOG_TAG = "TAG1";
    private static final String KEY = "Enter Your Key";
    String displayResponseSource = "";
    String displayResponseDestination = "";
    private Button btn_search;
    private GoogleMap map;
    private APIInterface apiInterface;
    private SupportMapFragment mapFragment;
    private AutoCompleteTextView autoCompViewSource;
    private AutoCompleteTextView autoCompViewDestination;
    private String autocompletetextSource = "";
    private String autocompletetextDestination = "";
    private LatLng maplocationdestination;
    private LatLng maplocationsource;
    private double longitudeSource;
    private double latitudeSource;
    private double latitudeDestination;
    private double longitudeDestination;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        autoCompViewSource = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextViewSource);
        autoCompViewDestination = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextViewDestination);
        btn_search = (Button) findViewById(R.id.btn_search);
        autoCompViewSource.setAdapter(new GooglePlacesAutocompleteAdapterSource(this, R.layout.lv_item));
        autoCompViewSource.setOnItemClickListener(this);
        autoCompViewDestination.setAdapter(new GooglePlacesAutocompleteAdapterDestination(this, R.layout.lv_item));
        autoCompViewDestination.setOnItemClickListener(this);

        mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);

    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        map = googleMap;

        btn_search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                autocompletetextSource = autoCompViewSource.getText().toString();
                autocompletetextDestination = autoCompViewDestination.getText().toString();

                apiInterface = APIClient.getClient().create(APIInterface.class);

                Call<ModelLatLong> call = apiInterface.getResponse(autocompletetextSource, KEY);
//                autocompletetext,KEY
                call.enqueue(new Callback<ModelLatLong>() {


                    @Override
                    public void onResponse(Call<ModelLatLong> call, Response<ModelLatLong> response) {

                        Log.i("TAG", response.code() + "");

                        ModelLatLong resource = response.body();
                        ArrayList<Results> resultsList = resource.getResults();

                        for (Results results : resultsList) {
                            longitudeSource = results.getGeometry().getLocation().getLng();
                            latitudeSource = results.getGeometry().getLocation().getLat();
                            Log.i("TAG1", displayResponseSource + "HI");
                        }
                        displayResponseSource = latitudeSource+ "," + longitudeSource;


//                        Toast.makeText(MainActivity.this, displayResponseSource, Toast.LENGTH_SHORT).show();

                        maplocationsource = new LatLng(latitudeSource, longitudeSource);

                        map.addMarker(new MarkerOptions()
                                .position(maplocationsource)
                                .snippet(autocompletetextSource)).showInfoWindow();

                        CameraUpdate center = CameraUpdateFactory.newLatLngZoom(maplocationsource, 14);
                        map.animateCamera(center);

                    }

                    @Override
                    public void onFailure(Call<ModelLatLong> call, Throwable t) {
                        Log.i("TAG1", "Failed");
                        call.cancel();
                    }
                });

                Call<ModelLatLong> calldes = apiInterface.getResponse(autocompletetextDestination, KEY);
//                autocompletetext,KEY
                calldes.enqueue(new Callback<ModelLatLong>() {

                    @Override
                    public void onResponse(Call<ModelLatLong> call, Response<ModelLatLong> response) {

                        Log.i("TAG", response.code() + "");

                        ModelLatLong resourcedes = response.body();
                        ArrayList<Results> resultsListdes = resourcedes.getResults();

                        for (Results results : resultsListdes) {
                            longitudeDestination = results.getGeometry().getLocation().getLng();
                            latitudeDestination = results.getGeometry().getLocation().getLat();
                            Log.i("TAG1", displayResponseDestination + "HI");
                        }
                        displayResponseDestination = latitudeDestination + "," + longitudeDestination;

//                        Toast.makeText(MainActivity.this, displayResponseDestination, Toast.LENGTH_SHORT).show();

                        maplocationdestination = new LatLng(latitudeDestination, longitudeDestination);

                        map.addMarker(new MarkerOptions()
                                .position(maplocationdestination)
                                .snippet(autocompletetextSource)).showInfoWindow();

                        CameraUpdate center = CameraUpdateFactory.newLatLngZoom(maplocationdestination, 14);
                        map.animateCamera(center);

                    }

                    @Override
                    public void onFailure(Call<ModelLatLong> call, Throwable t) {
                        Log.i("TAG1", "Failed");
                        call.cancel();
                    }
                });

                Call<ModelRoutes> calldistance = apiInterface.getResponseDistance(Get Your Source Latitude and Longitude Here(Eg. 20.9127766,73.7531254), Get Your Destination Latitude and Longitude Here in String(Eg. 23.0098149, 72.5035273), KEY);
                calldistance.enqueue(new Callback<ModelRoutes>() {


                    @Override
                    public void onResponse(Call<ModelRoutes> call, Response<ModelRoutes> response) {

                        String displayResponse = "";

                        ModelRoutes resourcedis = response.body();
                        Log.i("TAG", response.code() + "Hello");
                        ArrayList<Routes> routesList = resourcedis.getRoutes();
                        for (Routes routes : routesList) {
                            ArrayList<Legs> legsList = routes.getLegs();
                            for (Legs legs : legsList) {
                                String killoMeter = legs.getDistance().getText();
                                double timeDistance = legs.getDistance().getValue();
                                displayResponse += "\n Killometer : " + killoMeter + "\n Time Duration : " + timeDistance + "\n";
                                Log.i("TAG1", displayResponse + "HI");
                            }
                        }


                        Toast.makeText(MainActivity.this, displayResponse, Toast.LENGTH_SHORT).show();


                    }

                    @Override
                    public void onFailure(Call<ModelRoutes> call, Throwable t) {
                        Log.i("TAG1", "Failed");
                        call.cancel();
                    }
                });

            }
        });
    }

    public void onItemClick(AdapterView adapterView, View view, int position, long id) {
        String str = (String) adapterView.getItemAtPosition(position);
//        Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
    }

    public static ArrayList autocomplete(String input) {
        ArrayList resultList = null;

        HttpURLConnection conn = null;
        StringBuilder jsonResults = new StringBuilder();
        try {
            StringBuilder sb = new StringBuilder("https://maps.googleapis.com/maps/api/place/autocomplete/json");
            sb.append("?key=Enter Your Key Here");
            sb.append("&input=" + URLEncoder.encode(input, "utf8"));

            URL url = new URL(sb.toString());
            conn = (HttpURLConnection) url.openConnection();
            InputStreamReader in = new InputStreamReader(conn.getInputStream());

            int read;
            char[] buff = new char[1024];
            while ((read = in.read(buff)) != -1) {
                jsonResults.append(buff, 0, read);
            }
        } catch (MalformedURLException e) {
            Log.e(LOG_TAG, "Error processing Places API URL", e);
            return resultList;
        } catch (IOException e) {
            Log.e(LOG_TAG, "Error connecting to Places API", e);
            return resultList;
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }

        try {
            JSONObject jsonObj = new JSONObject(jsonResults.toString());
            JSONArray predsJsonArray = jsonObj.getJSONArray("predictions");

            resultList = new ArrayList(predsJsonArray.length());
            for (int i = 0; i < predsJsonArray.length(); i++) {
                System.out.println(predsJsonArray.getJSONObject(i).getString("description"));
                resultList.add(predsJsonArray.getJSONObject(i).getString("description"));
            }
        } catch (JSONException e) {
            Log.e(LOG_TAG, "Cannot process JSON results", e);
        }

        return resultList;
    }

    class GooglePlacesAutocompleteAdapterSource extends ArrayAdapter implements Filterable {
        private ArrayList resultList;

        public GooglePlacesAutocompleteAdapterSource(Context context, int textViewResourceId) {
            super(context, textViewResourceId);
        }

        @Override
        public int getCount() {
            return resultList.size();
        }

        @Override
        public Object getItem(int index) {
            return resultList.get(index);
        }

        @Override
        public Filter getFilter() {
            Filter filter = new Filter() {
                @Override
                protected FilterResults performFiltering(CharSequence constraint) {
                    FilterResults filterResults = new FilterResults();
                    if (constraint != null) {
                        resultList = autocomplete(constraint.toString());

                        filterResults.values = resultList;
                        filterResults.count = resultList.size();
                    }
                    return filterResults;
                }

                @Override
                protected void publishResults(CharSequence constraint, Filter.FilterResults results) {
                    if (results != null && results.count > 0) {
                        notifyDataSetChanged();
                    } else {
                        notifyDataSetInvalidated();
                    }
                }
            };
            return filter;
        }
    }

    class GooglePlacesAutocompleteAdapterDestination extends ArrayAdapter implements Filterable {
        private ArrayList resultList;

        public GooglePlacesAutocompleteAdapterDestination(Context context, int textViewResourceId) {
            super(context, textViewResourceId);
        }

        @Override
        public int getCount() {
            return resultList.size();
        }

        @Override
        public Object getItem(int index) {
            return resultList.get(index);
        }

        @Override
        public Filter getFilter() {
            Filter filter = new Filter() {
                @Override
                protected FilterResults performFiltering(CharSequence constraint) {
                    FilterResults filterResults = new FilterResults();
                    if (constraint != null) {
                        resultList = autocomplete(constraint.toString());

                        filterResults.values = resultList;
                        filterResults.count = resultList.size();
                    }
                    return filterResults;
                }

                @Override
                protected void publishResults(CharSequence constraint, Filter.FilterResults results) {
                    if (results != null && results.count > 0) {
                        notifyDataSetChanged();
                    } else {
                        notifyDataSetInvalidated();
                    }
                }
            };
            return filter;
        }
    }
}

<强> ModelRoutes.java

public class ModelRoutes extends Legs {

    ArrayList<Routes> routes = null;

    public ArrayList<Routes> getRoutes() {
        return routes;
    }

    public void setRoutes(ArrayList<Routes> routes) {
        this.routes = routes;
    }
}

<强> Routes.java

public class Routes extends Legs{

    ArrayList<Legs> legs = null;

    public ArrayList<Legs> getLegs() {
        return legs;
    }

    public void setLegs(ArrayList<Legs> legs) {
        this.legs = legs;
    }
}

<强> Legs.java

public class Legs  {

    Distances distance;
    Durations duration;

    public Distances getDistance() {
        return distance;
    }

    public void setDistance(Distances distance) {
        this.distance = distance;
    }

    public Durations getDuration() {
        return duration;
    }

    public void setDuration(Durations duration) {
        this.duration = duration;
    }

    public class Distances{
        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }

        public double getValue() {
            return value;
        }

        public void setValue(double value) {
            this.value = value;
        }

        String text;
        double value;

    }

    public class Durations{
        String text;
        double value;

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }

        public double getValue() {
            return value;
        }

        public void setValue(double value) {
            this.value = value;
        }
    }

}

<强> APIClient.java

public class APIClient {
    private static Retrofit retrofit = null;

    static Retrofit getClient() {

        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();


        retrofit = new Retrofit.Builder()
                .baseUrl("https://maps.googleapis.com")
                .addConverterFactory(GsonConverterFactory.create())
                .client(client)
                .build();



        return retrofit;
    }
}

<强> APIInterface.java

public interface APIInterface {
    @GET("/maps/api/geocode/json")
    Call<ModelLatLong> getResponse(
            @Query("address") String str,
            @Query("key") String str2);


    @GET("/maps/api/directions/json")
    Call<ModelRoutes> getResponseDistance(
            @Query("origin") String str,
            @Query("destination") String str1,
            @Query("key") String str2);
}

<强> ModelLatLong.java

public class ModelLatLong extends Results {
    private ArrayList<Results> results=null;

    public ArrayList<Results> getResults() {
        return results;
    }

    public void setResults(ArrayList<Results> results) {
        this.results = results;
    }
}

<强> Results.java

public class Results extends Geometry{
    private Geometry geometry;

    public Geometry getGeometry() {
        return this.geometry;
    }

    public void setGeometry(Geometry geometry) {
        this.geometry = geometry;
    }

}

<强> Geometry.java

public class Geometry extends Location{
    private Location location;

    public Location getLocation() {
        return this.location;
    }

    public void setLocation(Location location) {
        this.location = location;
    }
}

<强> Location.java

public class Location {
    private double lat;
    private double lng;

    public double getLat() {
        return lat;
    }

    public void setLat(double lat) {
        this.lat = lat;
    }

    public double getLng() {
        return lng;
    }

    public void setLng(double lng) {
        this.lng = lng;
    }
}

<强> activity_main.xml中

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.gmapplaceapi.MainActivity">

    <AutoCompleteTextView
        android:id="@+id/autoCompleteTextViewSource"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Please enter Source place"
        >

        <requestFocus />
    </AutoCompleteTextView>

    <AutoCompleteTextView
        android:id="@+id/autoCompleteTextViewDestination"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:layout_below="@+id/autoCompleteTextViewSource"
        android:hint="Please enter Destination place"
        >

        <requestFocus />
    </AutoCompleteTextView>

    <Button
        android:id="@+id/btn_search"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Search"
        android:layout_below="@+id/autoCompleteTextViewDestination"/>

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:layout_below="@+id/btn_search"
        tools:context="com.example.mapwithmarker.MapsMarkerActivity" />

</RelativeLayout>

<强> lv_item.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="3dp"
    android:textSize="20dp" />

不要忘记将Internet权限放在清单文件中。