我希望能够使用适用于
Android的Google Maps API在两个用户定义的地理点之间显示路线.我还希望能够让用户选择要显示的路线类型,无论是步行,骑车,汽车等.此外,我希望能够计算使用此路线所需的时间和距离.我试过在网上搜索并查看其他stackoverflow问题,但无济于事.我怎么会这样呢?我怎么能编码这个.
// – – 编辑 – – //
我还想得到交通信息,如繁忙的路线,拥堵等.
解决方法
使用Wrapper库的Android Google Maps Routing示例代码
使用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,this);
- locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,5000,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>