Open maps generating route

0

Good, I am developing an android app, in it I have an instance of google maps where I draw several markers.

If I only paint one, the map shows me the tools where I can give it and that I open the map application with the route between my position and the marker that I have pressed, but when painting several markers this option is removed, I would like call that function from another fragment, passing the position to where I want it to generate the route. Is it possible to do this? How could he do it?

I load the map:

    @Override
public void onMapReady(GoogleMap map) {
    googleMap = map;
    googleMap.setMapType(MAP_TYPE_NORMAL);
    //googleMap.getUiSettings().setMapToolbarEnabled(false); //desactiva la opción de abrir google maps para ir al marcador

    CameraPosition camPos = new CameraPosition.Builder()
            .target(l)   //Centramos el mapa en Madrid
            .zoom(12)         //Establecemos el zoom en 19
            .bearing(0)      //Establecemos la orientación con el noreste arriba
            .tilt(70)         //Bajamos el punto de vista de la cámara 70 grados
            .build();

    CameraUpdate camUpd3 = CameraUpdateFactory.newCameraPosition(camPos);

    googleMap.addMarker(new MarkerOptions().position(
            new LatLng(l.latitude, l.longitude))
            .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN))

    );
    for(int i=0;i<centros.size();i++){
        googleMap.addMarker(new MarkerOptions().position(
                new LatLng(centros.get(i).getLat(),centros.get(i).getLon())).title(centros.get(i).getNombre())
                .snippet(centros.get(i).getDire()).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
        );
    }

    googleMap.animateCamera(camUpd3);



    googleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
        @Override
        public boolean onMarkerClick(Marker marker) {
            Toast.makeText(getActivity(),
                    "id: "+marker.getId(),
                    Toast.LENGTH_LONG).show();

            CentroAcciones fragmentCentro = new CentroAcciones();
            getFragmentManager().beginTransaction().replace(R.id.container, fragmentCentro).commit();

            return false;
        }
    });
}

Actions Center

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    rootView = inflater.inflate(centroacciones, container, false);
    //TODO: obtiene null en las referencias a los botones

    llamar=(Button) rootView.findViewById(R.id.llamar);
    llamar.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //Toast.makeText(getActivity(),"Boton llamar",Toast.LENGTH_LONG).show();
            try {
                //TODO: obtener el tlf del centro que recibe como parámetro
                String phone="1234567890";
                Intent call = new Intent(Intent.ACTION_DIAL);
                call.setData(Uri.parse("tel:"+phone));  //String phone
                startActivity(call);
            } catch (Exception e) {
                //Log.e("Excepción", e+"");
                Toast.makeText(getActivity(),"No se encontró aplicación para llamar.",Toast.LENGTH_SHORT).show();
            }
        }
    });
    llegar=(Button) rootView.findViewById(R.id.llegar);
    llegar.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Toast.makeText(getActivity(),"Boton llegar",Toast.LENGTH_LONG).show();
        }
    });

    solicitar=(Button) rootView.findViewById(R.id.solicitud);
    solicitar.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View view) {
            centrosolicitar =new CentroSolicitar();
            getFragmentManager().beginTransaction().replace(R.id.container, centrosolicitar).commit();
        }

    });

    return rootView;
}

in this on create I have three options, call, route and request, call me launches the dialer with the phone, request me throw another fragment with their actions and my question is focused on route, since that is where I would like to launch google maps with the route from my position to the longitude-latitude of that center.

Thanks

    
asked by Ruben Manzano 27.12.2016 в 12:43
source

2 answers

1

The steps:

  • You can trace the route by making a request to the Google Directions API
  • Decode the string using the library android-maps-utils with the method PolyUtil.decode .
  • Add the decoded points to the map:

    List<LatLng> decodedPoints = PolyUtil.decode(polylineString);
    PolylineOptions options = new PolylineOptions();
    options.width(6);
    options.color(Color.RED);
    options.addAll(decodedPoints);
    
    map.addPolyline(options);
    

But if you want to save time you can use this library made by akexorcist . The only problem with this library is that it uses HtttpClient , which is a deprecated method. This is solved by changing the code a bit, replacing the code of the class Navigator with the following: :

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;


import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;

import android.content.Context;
import android.graphics.Color;
import android.os.AsyncTask;

public class Navigator {
    @SuppressWarnings("unused")
    private Context context;
    private LatLng startPosition, endPosition;
    private String mode;
    private GoogleMap map;
    private Directions directions;
    private int pathColor = Color.BLUE;
    private int pathBorderColor = Color.BLACK;
    private int secondPath = Color.CYAN;
    private int thirdPath = Color.RED;
    private float pathWidth = 14;
    private OnPathSetListener listener;
    private boolean alternatives = false;
    private long arrivalTime;
    private String avoid;
    private ArrayList<Polyline> lines = new ArrayList<Polyline>();

    public Navigator(GoogleMap map, LatLng startLocation, LatLng endLocation){
        this.startPosition = startLocation;
        this.endPosition = endLocation;
        this.map = map;
    }

    public interface OnPathSetListener{
        public void onPathSetListener(Directions directions);
    }

    public void setOnPathSetListener(OnPathSetListener listener){
        this.listener = listener;
    }

    /**
     * Gets the starting location for the directions 
     */
    public LatLng getStartPoint(){
        return startPosition;
    }

    /**
     * Gets the end location for the directions 
     * 
     */
    public LatLng getEndPoint(){
        return endPosition;
    }

    /**
     * Get's driving directions from the starting location to the ending location
     * 
     * @param showDialog 
     *  Set to true if you want to show a ProgressDialog while retrieving directions
     *  @param findAlternatives
     *  give alternative routes to the destination
     *  
     */
    public void findDirections(boolean findAlternatives){
        this.alternatives = findAlternatives;
        new PathCreator().execute();
    }

    /**
     * Sets the type of direction you want (driving,walking,biking or mass transit). This MUST be called before getting the directions
     * If using "transit" mode you must provide an arrival time
     * 
     * @param mode
     * The type of directions you want (driving,walking,biking or mass transit)
     * @param arrivalTime
     * If selected mode it "transit" you must provide and arrival time (milliseconds since January 1, 1970 UTC). If arrival time is not given
     * the current time is given and may return unexpected results.
     */
    public void setMode(int mode, long arrivalTime,int avoid){
        switch(mode){

        case 0:
            this.mode = "driving";
            break;
        case 1:
            this.mode = "transit";
            this.arrivalTime = arrivalTime;
            break;
        case 2:
            this.mode = "bicycling";
            break;
        case 3:
            this.mode = "walking";
            break;
        default:
            this.mode = "driving";
            break;
        }

        switch(avoid){
        case 0:
            this.avoid = "tolls";
            break;
        case 1:
            this.avoid = "highways";
            break;
        default:
            break;
        }
    }

    /**
     * Get all direction information
     * @return
     */
    public Directions getDirections(){
        return directions;
    }

    /**
     * Change the color of the path line, must be called before calling findDirections().
     * @param firstPath
     * Color of the first line, default color is blue.
     * @param secondPath
     * Color of the second line, default color is cyan
     * @param thirdPath
     * Color of the third line, default color is red
     * 
     */
    public void setPathColor(int firstPath,int secondPath, int thirdPath){
        pathColor = firstPath;
    }

    public void setPathBorderColor(int firstPath,int secondPath, int thirdPath){
        pathBorderColor = firstPath;
    }

    /**
     * Change the width of the path line
     * @param width
     * Width of the line, default width is 3
     */
    public void setPathLineWidth(float width){
        pathWidth = width;
    }

    private Polyline showPath(Route route,int color){
        return map.addPolyline(new PolylineOptions().addAll(route.getPath()).color(color).width(pathWidth));
    }

    private Polyline showBorderPath(Route route, int color){
        return map.addPolyline(new PolylineOptions().addAll(route.getPath()).color(color).width(pathWidth + 10));
    }

    public ArrayList<Polyline> getPathLines(){
        return lines;
    }

    private class PathCreator extends AsyncTask<Void,Void,Directions>{

        @Override
        protected Directions doInBackground(Void... params) {
            if(mode == null){
                mode = "driving";
            }

                String url = "https://maps.googleapis.com/maps/api/directions/json?"
                        + "origin=" + startPosition.latitude + "," + startPosition.longitude
                        + "&destination=" + endPosition.latitude + "," + endPosition.longitude
                        + "&sensor=false&units=metric&mode="+mode+"&alternatives="+String.valueOf(alternatives)+"&key=AIzaSyByacMXwL8ItVkRTQqoKiWroAUg2xeNs34";

                if(mode.equals("transit")){
                    if(arrivalTime > 0){
                        url += url + "&arrival_time="+arrivalTime;
                    }else{
                        url += url + "&departure_time="+System.currentTimeMillis();
                    }
                }

                if(avoid != null){
                    url += url+"&avoid="+avoid;
                }

                try {
/*
                    HttpClient httpClient = new DefaultHttpClient();
                    HttpContext localContext = new BasicHttpContext();
                    HttpPost httpPost = new HttpPost(url);
                    HttpResponse response = httpClient.execute(httpPost, localContext);

                    if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){

                        String s = EntityUtils.toString(response.getEntity());
                        return new Directions(s);
                    }
                    return null;
*/

                    URL urlDef = new URL(url);
                    HttpURLConnection conn = (HttpURLConnection) urlDef.openConnection();
                    conn.setRequestMethod("POST");

                    // para activar el metodo post
                    conn.setDoOutput(true);
                    conn.setDoInput(true);

                    InputStream is = conn.getInputStream();
                    BufferedReader rd = new BufferedReader(new InputStreamReader(is));
                    String line;
                    StringBuffer response = new StringBuffer();
                    while((line = rd.readLine()) != null) {
                        response.append(line);
                        response.append('\r');
                    }
                    rd.close();
                    String s = response.toString();
                    return new Directions(s);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            return null;
        }

        @Override
        protected void onPostExecute(Directions directions){

            if(directions != null){
                Navigator.this.directions = directions;
                for(int i=0; i<directions.getRoutes().size(); i++){
                    Route r = directions.getRoutes().get(i);
                    if(i == 0){
                        lines.add(showBorderPath(r,pathBorderColor));
                        lines.add(showPath(r,pathColor));
                    }else if(i == 1){
                        lines.add(showBorderPath(r,pathBorderColor));
                        lines.add(showPath(r,secondPath));
                    }else if(i == 3){
                        lines.add(showBorderPath(r,pathBorderColor));
                        lines.add(showPath(r,thirdPath));
                    }
                }

                if(listener != null){
                    listener.onPathSetListener(directions);
                }

            }
        }

    }

}

And in your map code (suppose it is displayed when you press a menu icon):

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    if (id == R.id.trying)
    {
        // caminando
        LatLng inicioR =  new LatLng(19.0436, -98.1981);
        LatLng finalR =  new LatLng(19.0500, -98.1981);
        Navigator nav = new Navigator(map,inicioR,finalR);
        nav.findDirections(false);
        // por efecto es manejando, ponemos la config para ir caminando
        nav.setMode(3,0,2);
        nav.setPathLineWidth(2); // aunque es 1, por defecto es 10+1
        nav.setPathBorderColor(Color.RED, 0, 0);
    }
    else
    if ( id == R.id.driving )
    {
        // manejando
        LatLng inicioR =  new LatLng(19.0436, -98.1981);
        LatLng finalR =  new LatLng(19.0500, -98.1981);
        Navigator nav = new Navigator(map,inicioR,finalR);
        nav.findDirections(false);
        // por efecto es manejando, aun si ponemos la config
        nav.setMode(0,0,2);
        nav.setPathLineWidth(2); // aunque es 1, por defecto es 10+1
        nav.setPathBorderColor(Color.GREEN, 0, 0);
    }
    return super.onOptionsItemSelected(item);
}

Update: Apparently the new version of the library already has new implementations with libraries for new versions of android, so the modification of the library navigator is enough.

    
answered by 27.12.2016 в 17:02
0

You have to use Polyline

Polyline line = map.addPolyline(new PolylineOptions()
            .add(new LatLng(tu_latitud, tu_longitud), new LatLng(destino.latitude, destino.longitude))
            .width(4)
            .color(Color.GREEN));

EDITING

If you want to open the native map directly

Uri gmmIntentUri = Uri.parse("google.navigation:q="+destino.latitud+","+destino.longitud+"&mode=d");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
mapIntent.setPackage("com.google.android.apps.maps");
startActivity(mapIntent);

Where mode =

  • d = auto
  • w = on foot
  • b = bicycle
answered by 27.12.2016 в 14:09