📜 ⬆️ ⬇️

Routes on Google Maps in the Android application - some clarifications

Since I am a novice developer in this field, then at the first stage I use ready-made ideas to understand the essence of solving typical problems. At the moment, it became necessary for me to lay a schematic route between two points on Google maps. The most interesting analogue for solving the problem, found on the Internet, was the following: " Routes on Google Maps in the Android application ." However, upon its further consideration and implementation, some pitfalls appeared, which I want to tell about.

First, there was the problem of setting two markers to indicate the starting and ending points. Maybe this is done crookedly, but I chose the following solution - control over their availability with the transfer of data when setting. It turned out like this:

//      map.setOnMapClickListener(new GoogleMap.OnMapClickListener() { //   @Override public void onMapClick(LatLng latlng) { if ((fromMarker == false) && (toMarker == false)) { MarkerOptions markerOptions = new MarkerOptions(); markerOptions.position(latlng); markerOptions.title("" + latlng.latitude + " " + latlng.longitude); BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory. fromResource(R.drawable.a_marker); markerOptions.icon(bitmapDescriptor); // "from - "  "to - " - ,  ,      from=""+latlng.latitude+","+latlng.longitude; map.addMarker(markerOptions); fromMarker = true; } else { if ((fromMarker == true) && (toMarker == false)) { MarkerOptions markerOptions = new MarkerOptions(); markerOptions.position(latlng); markerOptions.title("" + latlng.latitude + " " + latlng.longitude); BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory. fromResource(R.drawable.b_marker); markerOptions.icon(bitmapDescriptor); to=""+latlng.latitude+","+latlng.longitude; map.addMarker(markerOptions); toMarker = true; } else { if ((fromMarker == true) && (toMarker == true)) { map.clear(); fromMarker = false; toMarker = false; } } } } }); 

After checking the installation of markers and memorizing the source and destination coordinates, there was a question about the implementation of the display route. The implementation proposed in the above article “Routes on Google Maps in an Android application” turned out to be not quite workable.

First, an error occurred when requesting a map.googleapis.com site. The error was expressed in the impossibility of executing a GET request with transmission to the main thread. The check was performed on a device with Android 5.0. According to the description, the author of the example makes a synchronous GET request, which has the form:
')
 public interface RouteApi { @GET("/maps/api/directions/json") RouteResponse getRoute( @Query(value = "origin", encodeValue = false) String position, @Query(value = "destination", encodeValue = false) String destination, @Query("sensor") boolean sensor, @Query("language") String language); } 

Since it was Retrofit that gave the error, on the basis of which all requests and parsing of the JSON response were built, it was decided to sort it out. For information, I used the article “Retrofit - a library for working with REST API” at the link java-help.ru/retrofit-library .

Remembering that earlier in the articles it was written about the undesirability of working in a synchronous mode when accessing the network, it was decided to redo the request into an asynchronous version. The result is:

  //    public interface RouteApi { @GET("/maps/api/directions/json") void getRoute( @Query(value = "origin", encodeValue = false) String position, @Query(value = "destination", encodeValue = false) String destination, @Query("sensor") boolean sensor, @Query("language") String language, Callback<RouteResponse> cb ); } 

Accordingly, there have been changes in the further code. Instead:

 RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("https://maps.googleapis.com") .build(); RouteApi routeService = restAdapter.create(RouteApi.class); RouteResponse routeResponse = routeService.getRoute(position, destination, true, "ru"); 

Happened:

  //    API RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("https://maps.googleapis.com") .setLogLevel(RestAdapter.LogLevel.FULL) .build(); RouteApi routeService = restAdapter.create(RouteApi.class); //    () routeService.getRoute(from, to, true, "ru", new Callback<RouteResponse>() { public void success(RouteResponse arg0, retrofit.client.Response arg1) { } public void failure(RetrofitError arg0) { } }); 

After that, upon request, the JSON response without errors began to return.

In the future, it remains only to select a route from the entire code and reflect it on the map. The author of the cited article mentions that in order to get route points it is necessary to use the PolyUtil class. I quote: "... PolyUtil contains a decode () method that accepts the Points string and returns a set of LatLng objects, nodes of our route. This is enough for us to draw our route on the map." However, there is no sample application of the method in the article. In my implementation, it looks like this:

  //    () routeService.getRoute(from, to, true, "ru", new Callback<RouteResponse>() { public void success(RouteResponse arg0, retrofit.client.Response arg1) { //  ,      LatLng List<LatLng> mPoints = PolyUtil.decode(arg0.getPoints()); 

Then you can already build a polyline using the method described by the author.

The final application code will be as follows:

 package com.example.gpstest; import android.location.LocationManager; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.view.View; import com.google.android.gms.location.LocationListener; import com.google.android.gms.maps.CameraUpdate; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.BitmapDescriptor; import com.google.android.gms.maps.model.BitmapDescriptorFactory; 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.PolylineOptions; import com.google.maps.android.PolyUtil; import java.util.List; import retrofit.Callback; import retrofit.RestAdapter; import retrofit.RetrofitError; import retrofit.http.GET; import retrofit.http.Query; public class MainActivity extends FragmentActivity { SupportMapFragment mapFragment; GoogleMap map; private LocationManager locationManager; private LocationListener locationListener; Marker label; boolean fromMarker, toMarker; String from, to,result; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); fromMarker = false; toMarker = false; //    mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); map = mapFragment.getMap(); map.getUiSettings().setZoomControlsEnabled(true); map.setMyLocationEnabled(true); if (map == null) { return; } //    //  ,   ,    -  B,    -     map.setOnMapClickListener(new GoogleMap.OnMapClickListener() { @Override public void onMapClick(LatLng latlng) { if ((fromMarker == false) && (toMarker == false)) { MarkerOptions markerOptions = new MarkerOptions(); markerOptions.position(latlng); markerOptions.title("" + latlng.latitude + " " + latlng.longitude); BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.drawable.a_marker); markerOptions.icon(bitmapDescriptor); from=""+latlng.latitude+","+latlng.longitude; map.addMarker(markerOptions); fromMarker = true; } else { if ((fromMarker == true) && (toMarker == false)) { MarkerOptions markerOptions = new MarkerOptions(); markerOptions.position(latlng); markerOptions.title("" + latlng.latitude + " " + latlng.longitude); BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.drawable.b_marker); markerOptions.icon(bitmapDescriptor); to=""+latlng.latitude+","+latlng.longitude; map.addMarker(markerOptions); toMarker = true; } else { if ((fromMarker == true) && (toMarker == true)) { map.clear(); fromMarker = false; toMarker = false; } } } } }); } //    public class RouteResponse { public List<Route> routes; public String getPoints() { return this.routes.get(0).overview_polyline.points; } class Route { OverviewPolyline overview_polyline; } class OverviewPolyline { String points; } } //    public interface RouteApi { @GET("/maps/api/directions/json") void getRoute( @Query(value = "origin", encodeValue = false) String position, @Query(value = "destination", encodeValue = false) String destination, @Query("sensor") boolean sensor, @Query("language") String language, Callback<RouteResponse> cb ); } //    public void showRoute(View view ) { //    API RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("https://maps.googleapis.com") .setLogLevel(RestAdapter.LogLevel.FULL) .build(); RouteApi routeService = restAdapter.create(RouteApi.class); //    () routeService.getRoute(from, to, true, "ru", new Callback<RouteResponse>() { public void success(RouteResponse arg0, retrofit.client.Response arg1) { //  ,      LatLng List<LatLng> mPoints = PolyUtil.decode(arg0.getPoints()); //  PolylineOptions line = new PolylineOptions(); line.width(4f).color(R.color.colorPrimary); LatLngBounds.Builder latLngBuilder = new LatLngBounds.Builder(); for (int i = 0; i < mPoints.size(); i++) { line.add((LatLng) mPoints.get(i)); latLngBuilder.include((LatLng) mPoints.get(i)); } map.addPolyline(line); int size = getResources().getDisplayMetrics().widthPixels; LatLngBounds latLngBounds = latLngBuilder.build(); CameraUpdate track = CameraUpdateFactory.newLatLngBounds(latLngBounds, size, size, 25); map.moveCamera(track); } //    public void failure(RetrofitError arg0) { } }); } } 

The result of the work below on the screen:



Links to materials that are used in solving the problem:

Retrofit - library for working with REST API
A type-safe HTTP client for Android and Java
Routes on Google Maps in the Android application

Source: https://habr.com/ru/post/275019/


All Articles