简体   繁体   English

使用Androids Google Maps API查找路线

[英]Find route with Androids Google Maps API

I want to be able to display the route between two user-defined geographical points using the Google Maps API for Android. 我希望能够使用适用于Android的Google Maps API在两个用户定义的地理点之间显示路线。 I also want to be able to let the user choose what type of route to display, whether it be walking, cycling, car etc. Additionally, I want to be able to calculate the time and distance it would take to use this route. 我还希望能够让用户选择要显示的路线类型,无论是步行,骑车,汽车等。此外,我希望能够计算使用此路线所需的时间和距离。 I've tried searching the web and looking at other stackoverflow questions, but to no avail. 我试过在网上搜索并查看其他stackoverflow问题,但无济于事。 How would I go about this? 我该怎么做? How would I be able to code this. 我怎么能编码这个。

//----EDIT----// // - - 编辑 - - //

I would also like to get traffic information such as busy routes, congestion, etc. 我还想得到交通信息,如繁忙的路线,拥堵等。

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: 要使用androidhttpclient获取数据,请执行以下操作:

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: 其中buildStringIOUtils是:

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: 然后,您可以使用以下内容从JSON响应中提取实际折线:

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: 其中decodePolyline方法是这样的:

    /** 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 要更改模式,请将其添加到网址(请参阅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." 编辑2:在谷歌方向api中找到这个:“对于行车路线:商业地图客户可以指定出发时间以考虑当前的交通状况来接收行程持续时间。出发时间必须设置在当前时间的几分钟内。”

Android Google Maps Routing example code using Wrapper library 使用Wrapper库的Android Google Maps Routing示例代码

Use Android Studio Gradle entry: 使用Android Studio Gradle条目:

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

MainActivity.java 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 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 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>

Try the Google Directions API . 试试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. 这是一个Web服务,它提供JSON格式的转弯指南,所有信息都可以通过汽车,公交或您的脚从A点到B点。

To code that follow the link in the comment of Stochastically. 要跟随Stochastically评论中的链接进行编码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM