java - studio - Encontrar ruta con Androids Google Maps API
onmarkerclicklistener example android (3)
Pruebe la API de Google Directions . Es un servicio web, que ofrece guías paso a paso en formato JSON con toda la información para llegar del punto A al B en automóvil, tránsito o por los pies.
Para codificar, siga el enlace en el comentario de Estocásticamente.
Quiero poder mostrar la ruta entre dos puntos geográficos definidos por el usuario usando la API de Google Maps para Android. También quiero permitir que el usuario elija qué tipo de ruta mostrar, ya sea caminando, en bicicleta, en automóvil, etc. Además, quiero poder calcular el tiempo y la distancia que tomaría usar esta ruta. Intenté buscar en la web y buscar otras preguntas sobre el stackoverflow, pero fue en vano. ¿Cómo voy a hacer esto? ¿Cómo podría codificar esto?
//----EDITAR----//
También me gustaría obtener información de tráfico, como rutas congestionadas, congestión, etc.
Aquí hay un código para ayudarte.
String url=
"http://maps.googleapis.com/maps/api/directions/json?origin="
+ origin.latitude + "," + origin.longitude +"&destination="
+ destination.latitude + "," + destination.longitude + "&sensor=false";
Para buscar los datos con androidhttpclient, haz algo como esto:
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;
donde buildStringIOUtils es:
private String buildStringIOutils(InputStream is) {
try {
return IOUtils.toString(is, "UTF-8");
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
A continuación, puede extraer la polilínea real de la respuesta JSON con algo como esto:
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);
}
}
donde el método decodePolyline es este:
/** 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;
}
A continuación, puede agregar la polilínea al mapa con esto:
Polyline polylineToAdd = mMap.addPolyline(new PolylineOptions().addAll(lines).width(3).color(Color.RED));
Para cambiar el modo, agrégalo a la url (Consulta https://developers.google.com/maps/documentation/directions/ ): & mode = YOUR_MODE
conducir (por defecto) indica las direcciones de manejo estándar usando la red de carreteras.
caminar solicita indicaciones para caminar a través de senderos peatonales y aceras (donde esté disponible).
Andar en bicicleta solicita indicaciones para ir en bicicleta a través de carriles para bicicletas y calles preferidas (donde estén disponibles).
el tránsito solicita indicaciones a través de rutas de tránsito público (donde esté disponible).
Editar: Acerca de "También me gustaría obtener información de tráfico, como rutas ocupadas, congestión, etc." No he investigado esto, pero mi código debería hacerte empezar bastante bien.
Edit2: esto se encuentra en la api de direcciones de google: "Para indicaciones de conducción: los clientes de Maps for Business pueden especificar el tiempo de salida para recibir la duración del viaje considerando las condiciones actuales del tráfico. El tiempo de salida debe configurarse dentro de unos minutos de la hora actual".
Código de ejemplo de enrutamiento de Android Google Maps utilizando la biblioteca Wrapper
Utilice la entrada de 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>