Найти маршрут с Android Google Maps API

Я хочу иметь возможность отображать маршрут между двумя определяемыми пользователем географическими точками с помощью API Карт Google для Android. Я также хочу, чтобы пользователь мог выбирать, какой тип маршрута отображать, будь то ходьба, езда на велосипеде, автомобиль и т. д. Кроме того, я хочу иметь возможность рассчитать время и расстояние, которые потребуются для использования этого маршрута. Я пробовал искать в Интернете и смотреть на другие вопросы о стеке, но безрезультатно. Как бы я это сделал? Как я могу кодировать это.

//----РЕДАКТИРОВАТЬ----//

Я также хотел бы получать информацию о трафике, такую ​​как загруженные маршруты, заторы и т. д.


person Buneme Kyakilika    schedule 13.04.2013    source источник
comment
Я следовал этому stackoverflow.com/questions/11745314/ для получения маршрута. Это первый шаг.   -  person Stochastically    schedule 13.04.2013


Ответы (3)


Пример кода Android Google Maps Routing с использованием библиотеки Wrapper

Используйте запись 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();
        }
    }

}

Константы.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>
person Rahul Raina    schedule 21.09.2016

Вот код, который вам поможет.

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=ВАШ_РЕЖИМ

вождение (по умолчанию) указывает стандартные направления движения с использованием дорожной сети.

ходьба запрашивает маршруты пеших прогулок по пешеходным дорожкам и тротуарам (при наличии).

bicycling запрашивает велосипедные маршруты по велосипедным дорожкам и предпочитаемым улицам (если таковые имеются).

общественный транспорт запрашивает маршруты через маршруты общественного транспорта (где это возможно).

Изменить: о «Я также хотел бы получать информацию о дорожном движении, такую ​​​​как загруженные маршруты, заторы и т. Д.» Я не изучал это, но мой код должен помочь вам начать работу довольно хорошо.

Edit2: нашел это в API-интерфейсе google: «Для маршрутов проезда: клиенты Карт для бизнеса могут указать время отправления, чтобы получить продолжительность поездки с учетом текущих условий движения. Время отправления должно быть установлено в пределах нескольких минут от текущего времени».

person ullstrm    schedule 19.04.2013
comment
привет, можно ли добавить несколько пунктов назначения?? - person Adiyat Mubarak; 29.12.2015

Попробуйте API маршрутов Google. Это веб-сервис, который предоставляет пошаговые инструкции в формате JSON со всей информацией, как добраться из точки А в точку Б на машине, общественном транспорте или пешком.

Для кода перейдите по ссылке в комментарии Stochastically.

person Steve Benett    schedule 13.04.2013
comment
Во введении к API указано, что этот сервис, как правило, предназначен для расчета направлений по статическим (заранее известным) адресам для размещения контента приложения на карте; эта служба не предназначена, например, для реагирования в режиме реального времени на ввод данных пользователем. Для расчета динамических маршрутов (например, в элементе пользовательского интерфейса) обратитесь к документации по службе маршрутов JavaScript API V3. - person Buneme Kyakilika; 13.04.2013
comment
Да, дело в том, что API не предназначен для множественных вызовов в реальном времени. Просто вызовите API один раз, извлеките информацию из JSON и прокручивайте ее, пока не дойдете до нужного места. Как я уже сказал, API предоставляет информацию, но должна быть реализована логика обработки этой информации. - person Steve Benett; 13.04.2013