7

Chcę być w stanie wyświetlić trasę między dwoma zdefiniowanymi przez użytkownika zdefiniowanymi przez użytkownika przy użyciu interfejsu API Google Maps API dla Androida. Chciałbym również móc pozwolić użytkownikowi wybrać rodzaj trasy do wyświetlenia, czy to pieszo, rowerem, samochodem itp. Dodatkowo, chcę być w stanie obliczyć czas i dystans potrzebny do skorzystania z tej trasy. Próbowałem wyszukiwać w sieci i przeglądać inne pytania dotyczące stackoverflow, ale bezskutecznie. Jak bym to zrobił? Jak będę w stanie to zrobić kod.Znajdź trasę z Androidem Google Maps API

// EDIT ---- ---- //

Chciałbym również, aby uzyskać informacje o ruchu drogowym, takich jak ruchliwych trasach, przeciążenia itp

+0

I po to http://stackoverflow.com/questions/11745314/why-retrieving-google-directions-for-android-using-kml-data -nie-nie-działa-anymo, aby uzyskać trasę. To pierwszy krok. – Stochastically

Odpowiedz

3

Android Google Maps Routing przykład kodu z wykorzystaniem biblioteki Wrapper

Użyj Android Studio Gradle wpis:

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> 
3

Spróbuj Google Directions API. Jest to serwis internetowy, który zapewnia przewodnik po zakrętach w formacie JSON z wszystkimi informacjami, aby dostać się z punktu A do B samochodem, tranzytem lub stopami.

Aby wpisać kod pod linkiem w komentarzu Stochastically.

+2

We wstępie do API stwierdza: "Usługa ta jest ogólnie zaprojektowana do obliczania kierunków dla adresów statycznych (znanych z wyprzedzeniem) do umieszczania treści aplikacji na mapie, usługa ta nie jest zaprojektowana do odpowiadania w czasie rzeczywistym na dane wejściowe użytkownika, na przykład: w przypadku obliczeń dynamicznych kierunków (na przykład w elemencie interfejsu użytkownika) zapoznaj się z dokumentacją usługi JavaScript V3 Directions Service. " – AndroidDev

+0

Tak, chodzi o to, że interfejs API nie jest przeznaczony do wykonywania wielu połączeń w czasie rzeczywistym. Wystarczy zadzwonić do API raz, wyodrębnić informacje z JSON i przechodzić przez nie dopóki nie dotrzesz. Jak powiedziałem, że API podaje informacje, ale logika do obsługi tych informacji musi zostać zaimplementowana. –

+0

Czy widziałeś zmianę? – AndroidDev

6

Oto kod, który może Ci pomóc.

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

Aby pobrać dane z androidhttpclient, zrób coś takiego:

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; 

gdzie buildStringIOUtils jest:

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

Następnie można wyodrębnić rzeczywiste łamaną z JSON odpowiedzi z coś takiego:

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); 
         } 
        } 

gdzie metoda decodePolyline to:

/** 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; 
    } 

Można następnie dodać łamaną do mapy z tym:

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

Aby zmienić tryb, dodać do adresu URL (Patrz https://developers.google.com/maps/documentation/directions/): & Tryb = YOUR_MODE

Jazda (domyślnie) wskazuje standardowe kierunki jazdy za pomocą sieci dróg.

wskazówki dotyczące pieszych wędrówek pieszych ze ścieżkami dla pieszych & chodniki (jeśli są dostępne).

jazda rowerem wymaga wskazówek dojazdu rowerem ścieżkami rowerowymi & preferowane ulice (jeśli są dostępne).

Wskazówki dotyczące wniosków tranzytowych drogami transportu publicznego (jeśli są dostępne).

Edytuj: Informacje na temat "Chciałbym również uzyskać informacje o ruchu drogowym, takie jak ruchliwe trasy, zatłoczenie itp." Nie analizowałem tego, ale mój kod powinien zacząć dobrze.

Edit2: Znalazłem to w google kierunkach API: „wskazówek dojazdu. Mapy dla klientów biznesowych można określić DEPARTURE_TIME otrzymywać czas trwania podróży biorąc pod uwagę aktualne warunki ruchu drogowym DEPARTURE_TIME musi być ustawiony w ciągu kilku minut od Obecny czas."

+0

cześć, czy można dodać wiele miejsc docelowych? –