使用Android的Google Maps API查找路线

我希望能够使用Google Maps API for Android显示两个用户定义的地理点之间的路线。 我还希望能够让用户select要显示的路线types,无论是步行,骑自行车,汽车等。另外,我希望能够计算使用此路线所需的时间和距离。 我试过search网页,看着其他的stackoverflow问题,但无济于事。 我将如何去做这件事? 我将如何能够编码这个。

// – – 编辑 – – //

我也想获得路况,拥堵等交通信息。

Solutions Collecting From Web of "使用Android的Google Maps API查找路线"

Android谷歌地图路由示例代码使用包装库

使用Android Studio Gradle条目:

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> 

这里有一些代码可以帮助你。

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

要使用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; 

其中buildStringIOUtils是:

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

然后,您可以从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); } } 

其中的方法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; } 

然后,您可以使用以下命令将折线添加到地图上:

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

要更改模式,请将其添加到url(请参阅https://developers.google.com/maps/documentation/directions/):&mode = YOUR_MODE

驾驶(默认)表示使用道路networking的标准行车路线。

步行要求通过人行道和人行道(如果有的话)的步行路线。

骑自行车需要通过自行车道和首选的街道(如有)骑自行车路线。

通过公共交通路线(如果有的话)的过境请求指示。

编辑:关于“我也想得到交通信息,如繁忙路线,拥堵等” 我没有看到这个,但我的代码应该让你开始相当不错。

编辑2:在google的方向findapi:“对于行车路线:商务地图客户可以指定出发时间来考虑当前的交通状况,接收行程时间,离开时间必须设置在当前时间的几分钟之内。

尝试Google路线API 。 这是一个Web服务,它提供JSON格式的转弯指南,所有的信息都可以通过汽车,公交或者你的脚从A点到B点。

要按照随机评论中的链接进行编码。