Find route with Androids Google Maps API

后端 未结 3 1898
迷失自我
迷失自我 2021-02-14 16:40

I want to be able to display the route between two user-defined geographical points using the Google Maps API for Android. I also want to be ab

相关标签:
3条回答
  • 2021-02-14 17:09

    Here's some code to help you.

    String url= 
    "http://maps.googleapis.com/maps/api/directions/json?origin=" 
    + origin.latitude + "," + origin.longitude +"&destination=" 
    + destination.latitude + "," + destination.longitude + "&sensor=false";
    

    To fetch the data with androidhttpclient, do something like this:

    HttpResponse response;
    HttpGet request;
    AndroidHttpClient client = AndroidHttpClient.newInstance("somename");
    
    request = new HttpGet(url);
    response = client.execute(request);
    
    InputStream source = response.getEntity().getContent();
    String returnValue = buildStringIOutils(source);
    
    return returnValue;
    

    where buildStringIOUtils is:

    private String buildStringIOutils(InputStream is) {
        try {
            return IOUtils.toString(is, "UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
    

    You can then extract the actual polyline from the JSON-response with something like this:

    JSONObject result = new JSONObject(returnValue);
    JSONArray routes = result.getJSONArray("routes");
    
                        long distanceForSegment = routes.getJSONObject(0).getJSONArray("legs").getJSONObject(0).getJSONObject("distance").getInt("value");
    
                        JSONArray steps = routes.getJSONObject(0).getJSONArray("legs")
                                .getJSONObject(0).getJSONArray("steps");
    
                        List<LatLng> lines = new ArrayList<LatLng>();
    
                        for(int i=0; i < steps.length(); i++) {
                            String polyline = steps.getJSONObject(i).getJSONObject("polyline").getString("points");
    
                            for(LatLng p : decodePolyline(polyline)) {
                                lines.add(p);
                            }
                        }
    

    where the method decodePolyline is this:

        /** POLYLINE DECODER - http://jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java **/
        private List<LatLng> decodePolyline(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;
        }
    

    You can then add the polyline to the map with this:

    Polyline polylineToAdd = mMap.addPolyline(new PolylineOptions().addAll(lines).width(3).color(Color.RED));
    

    To change mode, add this to the url (See https://developers.google.com/maps/documentation/directions/): &mode=YOUR_MODE

    driving (default) indicates standard driving directions using the road network.

    walking requests walking directions via pedestrian paths & sidewalks (where available).

    bicycling requests bicycling directions via bicycle paths & preferred streets (where available).

    transit requests directions via public transit routes (where available).

    Edit: About the "I would also like to get traffic information such as busy routes, congestion, etc." I have not looked into this, but my code should get you started pretty good.

    Edit2: Found this in the google directions api: "For Driving Directions: Maps for Business customers can specify the departure_time to receive trip duration considering current traffic conditions. The departure_time must be set to within a few minutes of the current time."

    0 讨论(0)
  • 2021-02-14 17:12

    Android Google Maps Routing example code using Wrapper library

    Use Android Studio Gradle entry:

    compile 'com.github.jd-alexander:library:1.1.0'
    

    MainActivity.java

    import android.Manifest;
    import android.content.pm.PackageManager;
    import android.graphics.Color;
    import android.location.Location;
    import android.location.LocationListener;
    import android.location.LocationManager;
    import android.support.design.widget.FloatingActionButton;
    import android.support.design.widget.Snackbar;
    import android.support.v4.app.ActivityCompat;
    import android.support.v4.app.FragmentActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import com.directions.route.Route;
    import com.directions.route.RouteException;
    import com.directions.route.Routing;
    import com.directions.route.RoutingListener;
    import com.google.android.gms.maps.CameraUpdateFactory;
    import com.google.android.gms.maps.GoogleMap;
    import com.google.android.gms.maps.OnMapReadyCallback;
    import com.google.android.gms.maps.SupportMapFragment;
    import com.google.android.gms.maps.model.LatLng;
    import com.google.android.gms.maps.model.LatLngBounds;
    import com.google.android.gms.maps.model.Marker;
    import com.google.android.gms.maps.model.MarkerOptions;
    import com.google.android.gms.maps.model.Polyline;
    import com.google.android.gms.maps.model.PolylineOptions;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    public class MainActivity extends FragmentActivity implements OnMapReadyCallback, LocationListener, GoogleMap.OnMarkerClickListener, RoutingListener {
    
        private GoogleMap mMap = null;
        private LocationManager locationManager = null;
        private FloatingActionButton fab = null;
        private TextView txtDistance, txtTime;
    
        //Global UI Map markers
        private Marker currentMarker = null;
        private Marker destMarker = null;
        private LatLng currentLatLng = null;
        private Polyline line = null;
    
        //Global flags
        private boolean firstRefresh = true;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_map);
            Constants.POINT_DEST = new LatLng(18.758663, 73.382025);        //Lonavala destination.
            //Load the map fragment on UI
            SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
            mapFragment.getMapAsync(this);
            txtDistance = (TextView)findViewById(R.id.txt_distance);
            txtTime = (TextView)findViewById(R.id.txt_time);
            fab = (FloatingActionButton)findViewById(R.id.fab);
            fab.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    MainActivity.this.getRoutingPath();
                    Snackbar.make(v, "Fetching Route", Snackbar.LENGTH_SHORT).show();
                }
            });
    
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            firstRefresh = true;
            //Ensure the GPS is ON and location permission enabled for the application.
            locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
            if (!PermissionCheck.getInstance().checkGPSPermission(this, locationManager)) {
                //GPS not enabled for the application.
            } else if (!PermissionCheck.getInstance().checkLocationPermission(this)) {
                //Location permission not given.
            } else {
                Toast.makeText(MainActivity.this, "Fetching Location", Toast.LENGTH_SHORT).show();
                try {
                    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
                    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5000, 0, this);
                } catch(Exception e)
                {
                    Toast.makeText(MainActivity.this, "ERROR: Cannot start location listener", Toast.LENGTH_SHORT).show();
                }
            }
        }
    
        @Override
        protected void onPause() {
            if (locationManager != null) {
                //Check needed in case of  API level 23.
    
                if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                }
                try {
                    locationManager.removeUpdates(this);
                } catch (Exception e) {
                }
            }
            locationManager = null;
            super.onPause();
        }
    
        @Override
        protected void onStop() {
            super.onStop();
        }
    
        @Override
        public void onMapReady(GoogleMap googleMap)
        {
            mMap = googleMap;
            //mMap.getUiSettings().setZoomControlsEnabled(true);
            mMap.getUiSettings().setCompassEnabled(true);
            mMap.getUiSettings().setAllGesturesEnabled(true);
            mMap.setOnMarkerClickListener(this);
        }
    
        /**
         * @desc LocationListener Interface Methods implemented.
         */
    
        @Override
        public void onLocationChanged(Location location)
        {
            double lat = location.getLatitude();
            double lng = location.getLongitude();
            currentLatLng = new LatLng(lat, lng);
            if(firstRefresh)
            {
                //Add Start Marker.
                currentMarker = mMap.addMarker(new MarkerOptions().position(currentLatLng).title("Current Position"));//.icon(BitmapDescriptorFactory.fromResource(R.drawable.location)));
                firstRefresh = false;
                destMarker = mMap.addMarker(new MarkerOptions().position(Constants.POINT_DEST).title("Destination"));//.icon(BitmapDescriptorFactory.fromResource(R.drawable.location)));
                mMap.moveCamera(CameraUpdateFactory.newLatLng(Constants.POINT_DEST));
                mMap.animateCamera(CameraUpdateFactory.zoomTo(15));
                getRoutingPath();
            }
            else
            {
                currentMarker.setPosition(currentLatLng);
            }
        }
    
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {}
    
        @Override
        public void onProviderEnabled(String provider) {}
    
        @Override
        public void onProviderDisabled(String provider) {}
    
        /**
         * @desc MapMarker Interface Methods Implemented.
         */
    
        @Override
        public boolean onMarkerClick(Marker marker)
        {
            if(marker.getTitle().contains("Destination"))
            {
                //Do some task on dest pin click
            }
            else if(marker.getTitle().contains("Current"))
            {
                //Do some task on current pin click
            }
            return false;
        }
    
        /**
         *@desc Routing Listener interface methods implemented.
         **/
        @Override
        public void onRoutingFailure(RouteException e)
        {
            Toast.makeText(MainActivity.this, "Routing Failed", Toast.LENGTH_SHORT).show();
        }
    
        @Override
        public void onRoutingStart() { }
    
        @Override
        public void onRoutingSuccess(ArrayList<Route> list, int i)
        {
            try
            {
                //Get all points and plot the polyLine route.
                List<LatLng> listPoints = list.get(0).getPoints();
                PolylineOptions options = new PolylineOptions().width(5).color(Color.BLUE).geodesic(true);
                Iterator<LatLng> iterator = listPoints.iterator();
                while(iterator.hasNext())
                {
                    LatLng data = iterator.next();
                    options.add(data);
                }
    
                //If line not null then remove old polyline routing.
                if(line != null)
                {
                    line.remove();
                }
                line = mMap.addPolyline(options);
    
                //Show distance and duration.
                txtDistance.setText("Distance: " + list.get(0).getDistanceText());
                txtTime.setText("Duration: " + list.get(0).getDurationText());
    
                //Focus on map bounds
                mMap.moveCamera(CameraUpdateFactory.newLatLng(list.get(0).getLatLgnBounds().getCenter()));
                LatLngBounds.Builder builder = new LatLngBounds.Builder();
                builder.include(currentLatLng);
                builder.include(Constants.POINT_DEST);
                LatLngBounds bounds = builder.build();
                mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));
            }
            catch (Exception e) 
            {
                Toast.makeText(MainActivity.this, "EXCEPTION: Cannot parse routing response", Toast.LENGTH_SHORT).show();
            }
        }
    
        @Override
        public void onRoutingCancelled() 
        {
            Toast.makeText(MainActivity.this, "Routing Cancelled", Toast.LENGTH_SHORT).show();
        }
    
        /**
         * @method getRoutingPath
         * @desc Method to draw the google routed path.
         */
        private void getRoutingPath()
        {
            try
            {
                //Do Routing
                Routing routing = new Routing.Builder()
                        .travelMode(Routing.TravelMode.DRIVING)
                        .withListener(this)
                        .waypoints(currentLatLng, Constants.POINT_DEST)
                        .build();
                routing.execute();
            }
            catch (Exception e)
            {
                Toast.makeText(MainActivity.this, "Unable to Route", Toast.LENGTH_SHORT).show();
            }
        }
    
    }
    

    Constants.java

    /**
     * @class Constants
     * @desc Constant class for holding values at runtime.
     */
    public class Constants
    {
    
        //Map LatLong points
        public static LatLng POINT_DEST = null;
    
    }
    

    activity_map.xml

    <android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <LinearLayout android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <LinearLayout
            android:id="@+id/viewA"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="0.1"
            android:orientation="horizontal">
    
            <fragment
                android:id="@+id/map"
                android:name="com.google.android.gms.maps.SupportMapFragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                tools:context="com.packagename.MainActivity" />
    
    
        </LinearLayout>
    
        <LinearLayout
            android:id="@+id/viewB"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="0.9"
            android:gravity="center|left"
            android:paddingLeft="20dp"
            android:background="#FFFFFF"
            android:orientation="vertical" >
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="16dp"
                android:text="Distance ?"
                android:paddingTop="3dp"
                android:paddingLeft="3dp"
                android:paddingBottom="3dp"
                android:id="@+id/txt_distance" />
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="17dp"
                android:paddingLeft="3dp"
                android:text="Duration ?"
                android:id="@+id/txt_time" />
    
        </LinearLayout>
    
    </LinearLayout>
    
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:clickable="true"
        android:src="@android:drawable/ic_dialog_map"
        app:layout_anchor="@id/viewA"
        app:layout_anchorGravity="bottom|right|end"/>
    
    </android.support.design.widget.CoordinatorLayout>
    
    0 讨论(0)
  • 2021-02-14 17:22

    Try the Google Directions API. It's a web service, which gives turn-by-turn guides in JSON-Format with all information to get from point A to B by car, transit or your feet.

    To code that follow the link in the comment of Stochastically.

    0 讨论(0)
提交回复
热议问题