i'm having performance issues adding polylines and thought that maybe it'll be possible to add them in a separate class extending AsyncTask. However as i learned that UI elements can't be added in such way (and polylines are UI elements).
Why i'm having performance issues while drawing polylines? Well, my polylines are drawn not from pos A to pos B but from my current location to destination (which is hardcoded for the sake of application atm). So the polylines are drawn when onLocationChange listener is executed and thus my application requires lots of proccessing power.
Any ideas how to use AsyncTask on this occasion?
This is the main class:
mMap.setOnMyLocationChangeListener(new GoogleMap.OnMyLocationChangeListener() {
#Override
public void onMyLocationChange(Location arg0) {
// Get positions!
currentPOS = new LatLng(arg0.getLatitude(), arg0.getLongitude());
LatLng dst = new LatLng(58.378249, 26.714673);
CameraUpdate yourLocation = CameraUpdateFactory.newLatLngZoom(currentPOS, 13);
mMap.animateCamera(yourLocation);
mMap.addMarker(new MarkerOptions().position(dst).title("SCHOOL!"));
/*
// Remove comments to add marker to Liivi 2!
mMap.addMaker(new MarkerOptions().position(currentPOS).title("My POS"));
*/
if (currentPOS != null) {
//This is supposed to show directions
DirectionAPI directionAPI = new DirectionAPI(currentPOS, dst);
GoogleResponse googleResponse = null;
try {
googleResponse = (GoogleResponse) directionAPI.execute().get();
} catch (InterruptedException e) {
Log.e("CATCH","INTERRUPDED");
e.printStackTrace();
} catch (ExecutionException e) {
Log.e("CATCH","EXECUTIONEXCEPTION");
e.printStackTrace();
}
if (googleResponse.isOk()){
DrivingDirection drivingDirection = new DrivingDirection(googleResponse.getJsonObject());
polyline = drivingDirection.getTotalPolyline();
new drawPath(mMap,polyline).execute();
}
}
}
});
This is the Async for path drawing (which will result in an error due to UI conflict):
import android.graphics.Color;
import android.os.AsyncTask;
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 java.util.ArrayList;
/**
* Created by Kevin on 7.10.2015.
*/
public class drawPath extends AsyncTask{
private static ArrayList<LatLng> polyline;
private static GoogleMap mMap;
public drawPath(GoogleMap map, ArrayList<LatLng> polyline){
this.mMap = map;
this.polyline = polyline;
}
#Override
protected Object doInBackground(Object[] params) {
for (int i = 0; i < polyline.size() - 1; i++) {
LatLng src = polyline.get(i);
LatLng dest = polyline.get(i + 1);
// mMap is the Map Object
Polyline line = mMap.addPolyline(
new PolylineOptions().add(
new LatLng(src.latitude, src.longitude),
new LatLng(dest.latitude,dest.longitude)
).width(2).color(Color.BLUE).geodesic(true)
);
}
return null;
}
}
I solved this issue in a way that i did not add every polyline map separately but whole polyline. For example, before i had my location about 4km away from destination and it had 280 polylines between. On every onLocationChange these polylines were drawn one-by-one to map. Now they're all added at once - AsyncTask will create polylines in the background and in the post-execute they will be added.
#Override
protected Object doInBackground(Object[] params) {
PolylineOptions options = new PolylineOptions().width(5).color(Color.BLUE).geodesic(true);
for (int z = 0; z < polyline.size(); z++) {
LatLng point = polyline.get(z);
options.add(point);
}
return options;
}
protected void onPostExecute(Object result) {
Polyline line = mMap.addPolyline((PolylineOptions) result);
}
you can use this code
ublic class DrawrootTask extends AsyncTask<String, String, String> {
private Context context;
public static boolean flagCompleted = false;
private GoogleMap googleMap;
private double source_lat = 0.0;
private double source_long = 0.0;
private double dest_lat = 0.0;
private double dest_long = 0.0;
Userdata userdata;
String tag = "DrawRootTask";
private ProgressDialog progressDialog;
public static double dist, time;
private Polyline line;
String distanceText = "";
String durationText = "";
public DrawrootTask(Context context, LatLng source, LatLng destination,
GoogleMap googleMap) {
source_lat = source.latitude;
source_long = source.longitude;
dest_lat = destination.latitude;
dest_long = destination.longitude;
this.googleMap = googleMap;
this.context = context;
userdata = Userdata.getinstance(context);
}
protected void onPreExecute() {
// // TODO Auto-generated method stub
super.onPreExecute();
progressDialog = new ProgressDialog(context);
progressDialog.setMessage(context.getResources().getString(
R.string.please_wait));
progressDialog.setIndeterminate(true);
progressDialog.show();
}
#Override
protected String doInBackground(String... params) {
String json = "";
// constructor
StringBuilder urlString = new StringBuilder();
urlString.append("http://maps.googleapis.com/maps/api/directions/json");
HashMap<String, String> keyValue = new HashMap<String, String>();
urlString.append("?origin=");// from
urlString.append(Double.toString(source_lat));
urlString.append(",");
urlString.append(Double.toString(source_long));
urlString.append("&destination=");// to
urlString.append(Double.toString(dest_lat));
urlString.append(",");
urlString.append(Double.toString(dest_long));
urlString.append("&sensor=false&mode=driving&alternatives=true");
// defaultHttpClient
String url = urlString.toString();
FetchUrl fetchurl = new FetchUrl();
json = fetchurl.fetchUrl(url, keyValue);
Log.e("Buffer Error", json);
return json;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
try {
progressDialog.dismiss();
final JSONObject json = new JSONObject(result);
JSONArray routeArray = json.getJSONArray("routes");
JSONObject routes = routeArray.getJSONObject(0);
JSONObject overviewPolylines = routes
.getJSONObject("overview_polyline");
String encodedString = overviewPolylines.getString("points");
List<LatLng> list = decodePoly(encodedString);
for (int z = 0; z < list.size() - 1; z++) {
LatLng src = list.get(z);
LatLng dest = list.get(z + 1);
line = googleMap.addPolyline(new PolylineOptions()
.add(new LatLng(src.latitude, src.longitude),
new LatLng(dest.latitude, dest.longitude))
// .width(8).color(Color.BLUE).geodesic(true));
.width(8)
.color(context.getResources().getColor(
R.color.actionbar_color)).geodesic(true));
Log.i("draw root", "" + "" + line.toString());
}
JSONArray legs = routes.getJSONArray("legs");
JSONObject steps = legs.getJSONObject(0);
JSONObject duration = steps.getJSONObject("duration");
JSONObject distance = steps.getJSONObject("distance");
distanceText = distance.getString("text");
durationText = duration.getString("text");
Log.i("draw root", "" + distance.toString());
dist = Double.parseDouble(distance.getString("text").replaceAll(
"[^\\.0123456789]", ""));
time = Double.parseDouble(duration.getString("text").replaceAll(
"[^\\.0123456789]", ""));
userdata.setDistance(distanceText);
userdata.setTime(durationText);
Log.d(tag, "distace is " + dist + " time is " + time);
flagCompleted = true;
} catch (JSONException e) {
Log.d("draw root", "" + e);
}
}
private List<LatLng> decodePoly(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;
}
}
Related
I have added a waypoint and drawn the polyline from start to destination through the waypoint. But an extra straight line is drawn from start to destination. How can I remove it ?
The code below shows the ParserTask and getDirections URL.
private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {
// Parsing the data in non-ui thread
#Override
protected List<List<HashMap<String, String>>> doInBackground(String... jsonData) {
JSONObject jObject;
List<List<HashMap<String, String>>> routes = null;
try {
jObject = new JSONObject(jsonData[0]);
DirectionsJSONParser parser = new DirectionsJSONParser();
routes = parser.parse(jObject);
Log.d("routes", routes.toString());
Log.d("jObject", jObject.toString());
} catch (Exception e) {
e.printStackTrace();
}
return routes;
}
#Override
protected void onPostExecute(List<List<HashMap<String, String>>> result) {
ArrayList<LatLng> points = new ArrayList<LatLng>();;
PolylineOptions lineOptions = new PolylineOptions();;
lineOptions.width(2);
lineOptions.color(Color.RED);
MarkerOptions markerOptions = new MarkerOptions();
// Traversing through all the routes
for(int i=0;i<result.size();i++){
// Fetching i-th route
List<HashMap<String, String>> path = result.get(i);
for (int j = 0; j < path.size(); j++) {
HashMap<String, String> point = path.get(j);
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
points.add(position);
}
lineOptions.addAll(points);
lineOptions.width(12);
lineOptions.color(Color.RED);
lineOptions.geodesic(true);
}
// Drawing polyline in the Google Map for the i-th route
mMap.addPolyline(lineOptions);
}
}
private String getDirectionsUrl(LatLng origin_start, LatLng dest, LatLng waypoint_xx) {
String origin = "origin=" + origin_start.latitude + "," + origin_start.longitude;
//String waypointss = "waypoints=optimize:true|" + waypoint_xx.latitude + "," + waypoint_xx.longitude ;
String destination = "destination=" + dest.latitude + "," + dest.longitude;
// Waypoints
String waypoints = "";
for(int i=2;i<markerPoints.size();i++){
LatLng point = (LatLng) markerPoints.get(i);
if(i==2)
waypoints = "waypoints=";
waypoints += point.latitude + "," + point.longitude + "|";
}
String sensor = "sensor=false";
String alternative = "alternatives=false";
String params = origin + "&" + destination + "&" + alternative + "&" + sensor + "&" + waypoints ;
String output = "json";
String url = "https://maps.googleapis.com/maps/api/directions/"
+ output + "?" + params;
return url;
}
This code is the Directions JSON Parser
public class DirectionsJSONParser {
/** Receives a JSONObject and returns a list of lists containing latitude and longitude */
public List<List<HashMap<String,String>>> parse(JSONObject jObject){
List<List<HashMap<String, String>>> routes = new ArrayList<List<HashMap<String,String>>>() ;
JSONArray jRoutes = null;
JSONArray jLegs = null;
JSONArray jSteps = null;
try {
jRoutes = jObject.getJSONArray("routes");
/** Traversing all routes */
for(int i=0;i<jRoutes.length();i++){
jLegs = ( (JSONObject)jRoutes.get(i)).getJSONArray("legs");
List path = new ArrayList<HashMap<String, String>>();
/** Traversing all legs */
for(int j=0;j<jLegs.length();j++){
jSteps = ( (JSONObject)jLegs.get(j)).getJSONArray("steps");
/** Traversing all steps */
for(int k=0;k<jSteps.length();k++){
String polyline = "";
polyline = (String)((JSONObject)((JSONObject)jSteps.get(k)).get("polyline")).get("points");
List list = decodePoly(polyline);
/** Traversing all points */
for(int l=0;l <list.size();l++){
HashMap<String, String> hm = new HashMap<String, String>();
hm.put("lat", Double.toString(((LatLng)list.get(l)).latitude) );
hm.put("lng", Double.toString(((LatLng)list.get(l)).longitude) );
path.add(hm);
}
}
routes.add(path);
}
}
} catch (JSONException e) {
e.printStackTrace();
}catch (Exception e){
}
return routes;
}
/**
* Method to decode polyline points
* Courtesy : http://jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java
* */
private List decodePoly(String encoded) {
List poly = new ArrayList();
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;
}
}
This is the Download Task
private class DownloadTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... url) {
String data = "";
try {
data = downloadUrl(url[0]);
} catch (Exception e) {
Log.d("Background Task", e.toString());
}
Log.d("parserTask data", data.toString());
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
ParserTask parserTask = new ParserTask();
Log.d("parserTask result", result.toString());
parserTask.execute(result);
}
}
And finally the onMapReady method
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
UiSettings uiSettings = googleMap.getUiSettings();
//uiSettings.setCompassEnabled(false);
uiSettings.setZoomControlsEnabled(true);
//-------------
// mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
//Initialize Google Play Services
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
//Location Permission already granted
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
} else {
//Request Location Permission
checkLocationPermission();
}
}
else {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
//-------------
DatabaseReference myRef = FirebaseDatabase.getInstance().getReference().child("location");
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(MapsActivity.this)
.setSmallIcon(R.drawable.applogo)
.setContentTitle("Trip Request")
.setContentText("Click to accept trip!");
manager = (NotificationManager) MapsActivity.this.getSystemService( MapsActivity.this.NOTIFICATION_SERVICE );
manager.notify(0, builder.build());
// sendNotification();
startLatFB = (Double) dataSnapshot.child("startLat").getValue();
startLonFB = (Double) dataSnapshot.child("startLon").getValue();
endLatFB = (Double) dataSnapshot.child("endLat").getValue();
endLonFB = (Double) dataSnapshot.child("endLon").getValue();
Log.d("startLat", startLatFB.toString());
Log.d("startLon", startLonFB.toString());
Log.d("endLat", endLatFB.toString());
Log.d("endLon", endLonFB.toString());
if (markerPoints.size() > 1) {
markerPoints.clear();
mMap.clear();
}
double startLat = startLatFB; //SLIIT
double startLon = startLonFB;
double wayPointLat = 6.9040322; //FAB - Malabe
double wayPointLon = 79.948803;
double wayPointLatTwo = 6.053519; //FAB - Malabe
double wayPointLonTwo = 80.220977;
double endLat = endLatFB; //MAS
double endLon = endLonFB;
LatLng start_latLng = new LatLng(startLat, startLon);
LatLng waypoint_latLng = new LatLng(wayPointLat, wayPointLon);
LatLng end_latLng = new LatLng(endLat, endLon);
// LatLng start_latLng = new LatLng(startLatFB, startLonFB);
// LatLng waypoint_latLng = new LatLng(wayPointLat, wayPointLon);
// LatLng end_latLng = new LatLng(endLatFB, endLonFB);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(start_latLng, 11));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(start_latLng,11f));
// start_latLng = startLatFB;
// Adding new item to the ArrayList
markerPoints.add(start_latLng);
markerPoints.add(end_latLng);
markerPoints.add(waypoint_latLng);
// Creating MarkerOptions
MarkerOptions options = new MarkerOptions();
MarkerOptions optionsTwo = new MarkerOptions();
MarkerOptions optionsThree = new MarkerOptions();
BitmapDescriptor icon = BitmapDescriptorFactory.fromResource(R.drawable.startlocation);
BitmapDescriptor icon2 = BitmapDescriptorFactory.fromResource(R.drawable.endlocation);
// Setting the position of the marker
options.position(start_latLng);
optionsTwo.position(end_latLng);
optionsThree.position(waypoint_latLng);
if (markerPoints.size() == 1) {
options.icon(icon);
} else if (markerPoints.size() == 2) {
options.icon(icon2);
}
// Add new marker to the Google Map Android API V2
mMap.addMarker(options);
mMap.addMarker(optionsTwo);
mMap.addMarker(optionsThree);
// Checks, whether start and end locations are captured
if (markerPoints.size() >= 3) {
LatLng origin = (LatLng) markerPoints.get(0);
LatLng dest = (LatLng) markerPoints.get(1);
LatLng waypointss = (LatLng) markerPoints.get(2);
Log.d("origin url", origin.toString());
Log.d("dest url", origin.toString());
Log.d("waypoint url", origin.toString());
// Getting URL to the Google Directions API
String url = getDirectionsUrl(origin, dest, waypointss);
DownloadTask downloadTask = new DownloadTask();
// Start downloading json data from Google Directions API
downloadTask.execute(url);
Log.d("DownloadTask url", url);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Try initializing new Arraylist of Points each time while traversing.
Here is a sample:
#Override
protected void onPostExecute(List<List<HashMap<String, String>>> result) {
ArrayList<LatLng> points = null;
PolylineOptions lineOptions = null;
// Traversing through all the routes
for(int i=0;i<result.size();i++){
points = new ArrayList<LatLng>(); //initialize here
lineOptions = new PolylineOptions();
// Fetching i-th route
List<HashMap<String, String>> path = result.get(i);
for (int j = 0; j < path.size(); j++) {
HashMap<String, String> point = path.get(j);
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
points.add(position);
}
lineOptions.addAll(points);
lineOptions.width(12);
lineOptions.color(Color.RED);
}
// Drawing polyline in the Google Map for the i-th route
mMap.addPolyline(lineOptions);
}
}
For detail implementation Go through This Link
I wanted to add some checkpoints(Marker) into Google map between the Source and destination as per available route in my Android App.
Check this Google Maps tutorial HERE.
On the step 4, you parse a JSON which contains the different routes. From each route you can get the points with Lat and Lng values.
public class PathToDestination {
private GoogleMap mMap;
private Context context;
private static final String API_KEY = "your key";
private String pathColor = "#05b1fb";//default blue color
private int pathWidth = 5;//default is 5
private Polyline line;
private PolylineOptions polylineOptions;
public PathToDestination(Context context, GoogleMap mMap) {
this.context = context;
this.mMap = mMap;
}
public void setPathColor(String pathColor) {
this.pathColor = pathColor;
}
public void setPathWidth(int pathWidth) {
this.pathWidth = pathWidth;
}
public void drawPathBetween(#MapManager.PathMode int mode, double sourcelat, double sourcelog, double destlat, double destlog) {
drawPathBetween(mode, sourcelat, sourcelog, destlat, destlog, null);
}
public void drawPathBetween(#MapManager.PathMode int mode, double sourcelat, double sourcelog, double destlat, double destlog, MapModel[] waypoints) {
String urlStr = makeURL(mode, sourcelat, sourcelog, destlat, destlog, waypoints);
new ConnectAsyncTask(urlStr).execute();
}
/*private String makeURL(double sourcelat, double sourcelog, double destlat, double destlog) {
return makeURL(sourcelat, sourcelog, destlat, destlog, );
}*/
private String makeURL(#MapManager.PathMode int mode, double sourcelat, double sourcelog, double destlat, double destlog, MapModel... waypoints) {
StringBuilder urlString = new StringBuilder();
urlString.append("https://maps.googleapis.com/maps/api/directions/json");
urlString.append("?origin=");// from
urlString.append(Double.toString(sourcelat));
urlString.append(",");
urlString.append(Double.toString(sourcelog));
if (waypoints != null && waypoints.length > 0) {
urlString.append("&waypoints=");// waypoints
for (int i = 0; i < waypoints.length; i++) {
MapModel coordinate = waypoints[i];
urlString.append(coordinate.getLatitude());
urlString.append(",");
urlString.append(coordinate.getLongitude());
if (i < waypoints.length - 1) {
urlString.append("|");
}
}
}
urlString.append("&destination=");// to
urlString.append(Double.toString(destlat));
urlString.append(",");
urlString.append(Double.toString(destlog));
urlString.append("&sensor=false");
urlString.append("&mode=" + mode);
urlString.append("&alternatives=true");
urlString.append("&key=" + API_KEY);
return urlString.toString();
}
private void drawPath(String result) {
try {
//Tranform the string into a json object
final JSONObject json = new JSONObject(result);
JSONArray routeArray = json.getJSONArray("routes");
JSONObject routes = routeArray.getJSONObject(0);
JSONObject overviewPolylines = routes.getJSONObject("overview_polyline");
String encodedString = overviewPolylines.getString("points");
List<LatLng> list = null;
if (polylineOptions == null) {
polylineOptions = new PolylineOptions()
.width(pathWidth)
.color(Color.parseColor(pathColor)) //Google maps blue color
.geodesic(true);
}
list = decodePoly(encodedString);
polylineOptions.addAll(list);
if (line == null) {
line = mMap.addPolyline(polylineOptions);
}
line.setPoints(list);
/*
for(int z = 0; z<list.size()-1;z++){
LatLng src= list.get(z);
LatLng dest= list.get(z+1);
Polyline line = mMap.addPolyline(new PolylineOptions()
.add(new LatLng(src.latitude, src.longitude), new LatLng(dest.latitude, dest.longitude))
.width(2)
.color(Color.BLUE).geodesic(true));
}
*/
} catch (JSONException e) {
e.printStackTrace();
}
}
public void drawPathFromEncodedPolyline(String encodedPolyline) {
// try {
//Tranform the string into a json object
// final JSONObject json = new JSONObject(result);
// JSONArray routeArray = json.getJSONArray("routes");
// JSONObject routes = routeArray.getJSONObject(0);
// JSONObject overviewPolylines = routes.getJSONObject("overview_polyline");
// String encodedString = overviewPolylines.getString("points");
List<LatLng> list = decodePoly(encodedPolyline);
Polyline line = mMap.addPolyline(new PolylineOptions()
.addAll(list)
.width(5)
.color(Color.parseColor("#05b1fb"))//Google maps blue color
.geodesic(true)
);
/*
for(int z = 0; z<list.size()-1;z++){
LatLng src= list.get(z);
LatLng dest= list.get(z+1);
Polyline line = mMap.addPolyline(new PolylineOptions()
.add(new LatLng(src.latitude, src.longitude), new LatLng(dest.latitude, dest.longitude))
.width(2)
.color(Color.BLUE).geodesic(true));
}
*/
// } catch (JSONException e) {
// e.printStackTrace();
// }
}
private List<LatLng> decodePoly(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;
}
private class ConnectAsyncTask extends AsyncTask<Void, Void, String> {
private ProgressDialog progressDialog;
String url;
ConnectAsyncTask(String urlPass) {
url = urlPass;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 &&
!((Activity) context).isDestroyed()) ||
!((Activity) context).isFinishing()) {
progressDialog = new ProgressDialog(context);
// progressDialog.setMessage("Fetching route, Please wait...");
// progressDialog.setIndeterminate(true);
// progressDialog.show();
}
}
#Override
protected String doInBackground(Void... params) {
HttpURLConnection conn = null;
StringBuilder jsonResults = new StringBuilder();
try {
URL url = new URL(this.url);
conn = (HttpURLConnection) url.openConnection();
InputStreamReader in = new InputStreamReader(conn.getInputStream());
// Load the results into a StringBuilder
int read;
char[] buff = new char[1024];
while ((read = in.read(buff)) != -1) {
jsonResults.append(buff, 0, read);
}
} catch (MalformedURLException e) {
return jsonResults.toString();
} catch (IOException e) {
return jsonResults.toString();
} finally {
if (conn != null) {
conn.disconnect();
}
}
return jsonResults.toString();
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (progressDialog != null) {
progressDialog.hide();
}
if (result != null) {
drawPath(result);
}
}
}
public void clearRoute() {
if (line != null) {
line.remove();
}
line = null;
polylineOptions = null;
}
}
Here MapModel is an interface
public interface MapModel {
double getLatitude();
double getLongitude();
}
If you want the list of LatLng you can easily get that from
drawPathFromEncodedPolyline(String encodedPolyline)
method.
You can look here for other map functions.
I have an app that find the shortest distance between my user to a polygon.
I want to convert the polygon to Geofence to check the distance between the user to the area to give mor accurate information to the user.
how can I do that?
this is the MapsActivity
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, LocationListener, MinimumDistanceTask.GetMinimumDistanceListener {
private GoogleMap mMap;
private LocationManager manager;
private double lat, lng;
private KmlLayer layer;
private LatLng latLngTest;
private boolean contains = false;
private ArrayList<LatLng> outerBoundary;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
manager = (LocationManager) getSystemService(LOCATION_SERVICE);
}
#Override
protected void onResume() {
super.onResume();
String provider = LocationManager.GPS_PROVIDER;
//take the user location every second
try {
manager.requestLocationUpdates(provider, 1000, 0, this);
}catch (SecurityException e){
}
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
}
#Override
public void onLocationChanged(Location location) {
//clear map before create new location
mMap.clear();
try {
//load the kml file
layer = new KmlLayer(mMap, R.raw.polygon_layer, this);
layer.addLayerToMap();
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
lat = location.getLatitude();
lng = location.getLongitude();
latLngTest = new LatLng(lat,lng);
// Add a marker in user location
LatLng userLocation = new LatLng(latLngTest.latitude, latLngTest.longitude);
mMap.addMarker(new MarkerOptions().position(userLocation).title("you are here"));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 15));
//check if the user in the polygon
boolean inside = ifUserInside();
if(inside){
Toast.makeText(MapsActivity.this, "you are in the polygon", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(MapsActivity.this, "you are outside the polygon", Toast.LENGTH_SHORT).show();
//create the string address for the url
String address = "";
for (int i = 0; i < outerBoundary.size(); i++) {
address += (outerBoundary.get(i).toString() + "|");
address = address.replace("lat/lng:", "");
address = address.replace(" ", "");
address = address.replace("(", "");
address = address.replace(")", "");
}
MinimumDistanceTask task = new MinimumDistanceTask(this);
task.execute("https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins="+latLngTest.latitude+ "," + latLngTest.longitude
+ "&destinations=" + address + "&mode=walking");
}
}
#Override
public void getMinimumDistance(int closeLocation) {
//check if you get results properly
if(closeLocation != -1) {
GetDirection direction = new GetDirection();
direction.execute("https://maps.googleapis.com/maps/api/directions/json?origin=" + latLngTest.latitude + "," + latLngTest.longitude
+ "&destination=" + outerBoundary.get(closeLocation).latitude + "+" + outerBoundary.get(closeLocation).longitude);
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
public boolean ifUserInside(){
if (layer.getContainers() != null) {
for (KmlContainer container : layer.getContainers()) {
if (container.getPlacemarks() != null) {
for (KmlPlacemark placemark : container.getPlacemarks()) {
contains = false;
if (placemark.getGeometry() instanceof KmlPolygon) {
KmlPolygon polygon = (KmlPolygon) placemark.getGeometry();
// Get the outer boundary and check if the test location lies inside
outerBoundary = polygon.getOuterBoundaryCoordinates();
contains = PolyUtil.containsLocation(latLngTest, outerBoundary, true);
if (contains) {
// Get the inner boundaries and check if the test location lies inside
ArrayList<ArrayList<LatLng>> innerBoundaries = polygon.getInnerBoundaryCoordinates();
if (innerBoundaries != null) {
for (ArrayList<LatLng> innerBoundary : innerBoundaries) {
// If the test location lies in a hole, the polygon doesn't contain the location
if (PolyUtil.containsLocation(latLngTest, innerBoundary, true)) {
contains = false;
}
}
}
}
}
}
}
}
}
return contains;
}
public class GetDirection extends AsyncTask<String , Void, String> {
HttpsURLConnection connection = null;
BufferedReader reader = null;
StringBuilder builder = new StringBuilder();
#Override
protected String doInBackground(String... params) {
String address = params[0];
try {
URL url = new URL(address);
connection = (HttpsURLConnection) url.openConnection();
if(connection.getResponseCode() != HttpURLConnection.HTTP_OK){
return "Error from server";
}
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = reader.readLine()) != null){
builder.append(line);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return builder.toString();
}
#Override
protected void onPostExecute(String s) {
//get the polyline string
String polygonPoints = "";
try {
JSONObject object = new JSONObject(s);
JSONArray array = object.getJSONArray("routes");
for (int i = 0; i < array.length(); i++) {
JSONObject arrObj1 = array.getJSONObject(i);
JSONObject points = arrObj1.getJSONObject("overview_polyline");
polygonPoints = points.getString("points");
}
//convert the string to polyline;
ArrayList<LatLng> a = new ArrayList<>(decodePolyPoints(polygonPoints));
//add polyline to the map
mMap.addPolyline(new PolylineOptions().addAll(a).width(10).color(Color.BLUE));
} catch (JSONException e) {
e.printStackTrace();
}
}
}
//the method that convert the string to polyline
public static ArrayList<LatLng> decodePolyPoints(String encodedPath){
int len = encodedPath.length();
final ArrayList<LatLng> path = new ArrayList<LatLng>();
int index = 0;
int lat = 0;
int lng = 0;
while (index < len) {
int result = 1;
int shift = 0;
int b;
do {
b = encodedPath.charAt(index++) - 63 - 1;
result += b << shift;
shift += 5;
} while (b >= 0x1f);
lat += (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
result = 1;
shift = 0;
do {
b = encodedPath.charAt(index++) - 63 - 1;
result += b << shift;
shift += 5;
} while (b >= 0x1f);
lng += (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
path.add(new LatLng(lat * 1e-5, lng * 1e-5));
}
return path;
}
}
This is my AsyncTask to get the minimum distance point
public class MinimumDistanceTask extends AsyncTask<String, Void, Integer>{
private int closeLocation;
// private String points;
private GetMinimumDistanceListener listener;
public MinimumDistanceTask(GetMinimumDistanceListener listener){
// this.points = points;
this.listener = listener;
}
#Override
protected Integer doInBackground(String... params) {
HttpsURLConnection connection = null;
BufferedReader reader = null;
StringBuilder builder = new StringBuilder();
int minimumDis = -1;
String address = params[0];
try {
URL url = new URL(address);
connection = (HttpsURLConnection) url.openConnection();
if(connection.getResponseCode() != HttpURLConnection.HTTP_OK){
return -1;
}
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = reader.readLine()) != null){
builder.append(line);
}
///get the json data
JSONObject jsonObject1 = new JSONObject(builder.toString());
JSONArray points = jsonObject1.getJSONArray("rows");
JSONObject jsonObject2 = points.getJSONObject(0);
JSONArray elements = jsonObject2.getJSONArray("elements");
for (int i = 0; i < elements.length(); i++) {
JSONObject jsonObject3 = elements.getJSONObject(i);
JSONObject distance = jsonObject3.getJSONObject("distance");
if( distance.getInt("value") < minimumDis || minimumDis == -1) {
minimumDis = distance.getInt("value");
closeLocation = i;
}
}
} catch (MalformedURLException | JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return closeLocation;
}
#Override
protected void onPostExecute(Integer closeLocation) {
listener.getMinimumDistance(closeLocation);
}
public interface GetMinimumDistanceListener{
void getMinimumDistance(int closeLocation);
}
}
thanks a lot :)
You can use a function like the following to calculate the nearest point from polygon defined by a List<LatLng> and a given LatLng.
It uses the PolyUtil.distanceToLine from the Google Maps Android API Utility Library to compute the distance between the test LatLng and every segment of the list, and a method based on the distanceToLine method from https://github.com/googlemaps/android-maps-utils/blob/master/library/src/com/google/maps/android/PolyUtil.java to compute the projection of a point on a segment.
private LatLng findNearestPoint(LatLng test, List<LatLng> target) {
double distance = -1;
LatLng minimumDistancePoint = test;
if (test == null || target == null) {
return minimumDistancePoint;
}
for (int i = 0; i < target.size(); i++) {
LatLng point = target.get(i);
int segmentPoint = i + 1;
if (segmentPoint >= target.size()) {
segmentPoint = 0;
}
double currentDistance = PolyUtil.distanceToLine(test, point, target.get(segmentPoint));
if (distance == -1 || currentDistance < distance) {
distance = currentDistance;
minimumDistancePoint = findNearestPoint(test, point, target.get(segmentPoint));
}
}
return minimumDistancePoint;
}
/**
* Based on `distanceToLine` method from
* https://github.com/googlemaps/android-maps-utils/blob/master/library/src/com/google/maps/android/PolyUtil.java
*/
private LatLng findNearestPoint(final LatLng p, final LatLng start, final LatLng end) {
if (start.equals(end)) {
return start;
}
final double s0lat = Math.toRadians(p.latitude);
final double s0lng = Math.toRadians(p.longitude);
final double s1lat = Math.toRadians(start.latitude);
final double s1lng = Math.toRadians(start.longitude);
final double s2lat = Math.toRadians(end.latitude);
final double s2lng = Math.toRadians(end.longitude);
double s2s1lat = s2lat - s1lat;
double s2s1lng = s2lng - s1lng;
final double u = ((s0lat - s1lat) * s2s1lat + (s0lng - s1lng) * s2s1lng)
/ (s2s1lat * s2s1lat + s2s1lng * s2s1lng);
if (u <= 0) {
return start;
}
if (u >= 1) {
return end;
}
return new LatLng(start.latitude + (u * (end.latitude - start.latitude)),
start.longitude + (u * (end.longitude - start.longitude)));
}
You can test it with the following code:
List<LatLng> points = new ArrayList<>();
points.add(new LatLng(2, 2));
points.add(new LatLng(4, 2));
points.add(new LatLng(4, 4));
points.add(new LatLng(2, 4));
points.add(new LatLng(2, 2));
LatLng testPoint = new LatLng(3, 0);
LatLng nearestPoint = findNearestPoint(testPoint, points);
Log.e("NEAREST POINT: ", "" + nearestPoint); // lat/lng: (3.0,2.0)
Log.e("DISTANCE: ", "" + SphericalUtil.computeDistanceBetween(testPoint, nearestPoint)); // 222085.35856591124
I have app which set multiple routes on the map.
The problem is when I put two points in the map, he get the suggested routes but with one extra straight line.
I found a solution. I just get the main tag for polyline - overview_polyline
In the code are the new changes :)
pic multiple routes - alternatives=true - I set just one road
pic - if I set alternatives=false in xml link, the straight line disappears.
In the xml everything is fine.
I looked in to the 2 xml files with alternatives=false and alternatives=true but there are identical.
link to XML file
Thanks in advance.
this code display the information:
//Polyline
private class GetRouteTask extends AsyncTask<String, Void, String> {
String response = "";
#Override
protected String doInBackground(String... urls) {
//Get All Route values
v2GetRouteDirection = new GMapV2Direction();
document = v2GetRouteDirection.getDocument(latLngFrom, latLngTo, GMapV2Direction.MODE_DRIVING);
response = "Success";
return response;
}
#Override
protected void onPostExecute(String result) {
if(document != null){
ArrayList<LatLng> directionPoint = v2GetRouteDirection.getDirection(document);
PolylineOptions rectLine = new PolylineOptions().width(3).color(Color.RED);
for (int i = 0; i < directionPoint.size(); i++) {
rectLine.add(directionPoint.get(i));
}
// Adding route on the map
map.addPolyline(rectLine);
}
}
}
this code get the tag information:
public class GMapV2Direction {
public GMapV2Direction(){}
public final static String MODE_DRIVING = "driving";
public final static String MODE_WALKING = "walking";
public static String error = null;
public Document getDocument(LatLng start, LatLng end, String mode) {
String url = "http://maps.googleapis.com/maps/api/directions/xml?"
+ "origin=" + start.latitude + "," + start.longitude
+ "&destination=" + end.latitude + "," + end.longitude
+ "&sensor=false&units=metric&mode=driving&alternatives=true";
////////////////
//Set TimeOuts
HttpParams httpParameters = new BasicHttpParams();
// Set the timeout in milliseconds until a connection is established.
// The default value is zero, that means the timeout is not used.
int timeoutConnection = 3000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT)
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = 5000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
try {
HttpClient httpClient = new DefaultHttpClient(httpParameters);
HttpContext localContext = new BasicHttpContext();
HttpGet httpGet = new HttpGet(url);
HttpResponse response = httpClient.execute(httpGet, localContext);
InputStream in = response.getEntity().getContent();
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(in);
return doc;
}
catch (ClientProtocolException e) {
error = "some";
e.printStackTrace();
} catch (IOException e) {
error = "some";
e.printStackTrace();
}
catch (Exception e) {
error = "some";
e.printStackTrace();
}
return null;
}
public ArrayList<LatLng> getDirection (Document doc) {
NodeList error = doc.getElementsByTagName("status");
int p;
Node error1 = null;
//взема последнич елемент на таг
for(p = 0;p<error.getLength();p++){
error1 = error.item(p);
}
if(p==p){
p--;
}
LatLng latLngZero = new LatLng(0.0, 0.0);
ArrayList<LatLng> list = new ArrayList<LatLng>();
list.add(latLngZero);
ArrayList<LatLng> listGeopoints = null;
if(error1.getFirstChild().getTextContent().equals("OK")) {
//new
NodeList routeTag,nl3;
listGeopoints = new ArrayList<LatLng>();
//get tag route
routeTag = doc.getElementsByTagName("route");
if (routeTag.getLength() > 0) {
//get first eelemnt of route
Element routeElement = (Element) routeTag.item(0);
//get tag overview_polyline
NodeList polylineList = routeElement.getElementsByTagName("overview_polyline");
Node node1 = polylineList.item(0);
nl3 = node1.getChildNodes();
Node latNode = nl3.item(getNodeIndex(nl3, "points"));
List<LatLng> arr = decodePoly(latNode.getTextContent());
for (int j = 0; j < arr.size(); j++) {
listGeopoints.add(new LatLng(arr.get(j).latitude, arr.get(j).longitude));
}
}
}
//////////////
else{
return list;
}
return listGeopoints;
}
private int getNodeIndex(NodeList nl, String nodename) {
for(int i = 0 ; i < nl.getLength() ; i++) {
if(nl.item(i).getNodeName().equals(nodename))
return i;
}
return -1;
}
private ArrayList<LatLng> decodePoly(String encoded) {
ArrayList<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 position = new LatLng((double) lat / 1E5, (double) lng / 1E5);
poly.add(position);
}
return poly;
}
}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
import com.google.android.gms.maps.model.LatLng;
public class DirectionsJSONParser {
public List<List<List<HashMap<String,String>>>> parse(JSONObject jObject){
List<List<HashMap<String, String>>> routes = new ArrayList<List<HashMap<String,String>>>() ;
List<List<List<HashMap<String,String>>>> routes1 = new ArrayList<List<List<HashMap<String,String>>>>() ;
JSONArray jRoutes = null;
JSONArray jLegs = null;
JSONArray jSteps = null;
try {
jRoutes = jObject.getJSONArray("routes");
/** Traversing all routes */
for(int i=0;i<jRoutes.length();i++){
jLegs = ( (JSONObject)jRoutes.get(i)).getJSONArray("legs");
List path = new ArrayList<HashMap<String, String>>();
List path1 = new ArrayList<ArrayList<HashMap<String,String>>>();
// Log.d("legs",jLegs.toString());
/** Traversing all legs */
for(int j=0;j<jLegs.length();j++){
HashMap<String, String> hm1 = new HashMap<String, String>();
jSteps = ( (JSONObject)jLegs.get(j)).getJSONArray("steps");
// Log.d("steps",jSteps.toString());
/** Traversing all steps */
for(int k=0;k<jSteps.length();k++){
String polyline = "";
polyline = (String)((JSONObject)((JSONObject)jSteps.get(k)).get("polyline")).get("points");
List<LatLng> list = decodePoly(polyline);
// Log.d("polyline",polyline.toString());
/** Traversing all points */
for(int l=0;l<list.size();l++){
HashMap<String, String> hm = new HashMap<String, String>();
hm.put("lat", Double.toString(((LatLng)list.get(l)).latitude) );
hm.put("lng", Double.toString(((LatLng)list.get(l)).longitude) );
path.add(hm);
// Log.d("lat", Double.toString(((LatLng)list.get(l)).latitude));
// Log.d("lng", Double.toString(((LatLng)list.get(l)).longitude));
}
}
path1.add(path);
}
routes1.add(path1);
}
} catch (JSONException e) {
e.printStackTrace();
}catch (Exception e){
}
return routes1;
}
/**
* Method to decode polyline points
* Courtesy : http://jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java
* */
private List<LatLng> decodePoly(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;
}
}
Faced similar problem and soled it by using addall() method for polylineoptions object to draw line on map directly using array list of latlng's.
Cannot confirm but trying this code might help
Polyline
private class GetRouteTask extends AsyncTask<String, Void, String> {
String response = "";
#Override
protected String doInBackground(String... urls) {
//Get All Route values
v2GetRouteDirection = new GMapV2Direction();
document = v2GetRouteDirection.getDocument(latLngFrom, latLngTo, GMapV2Direction.MODE_DRIVING);
response = "Success";
return response;
}
#Override
protected void onPostExecute(String result) {
if(document != null){
ArrayList<LatLng> directionPoint = v2GetRouteDirection.getDirection(document);
PolylineOptions rectLine = new PolylineOptions().width(3).color(Color.RED);
rectLine.addall(directionPoint);
// Adding route on the map
map.addPolyline(rectLine);
}
}
}
LatLng origin = new latlng(type your starting point latitude and longtitude);
LatLng dest = new latlng(type your ending point latitude and longtitude);
// Getting URL to the Google Directions API
String url = getDirectionsUrl(origin, dest);
DownloadTask downloadTask = new DownloadTask();
// Start downloading json data from Google Directions API
downloadTask.execute(url);
private String getDirectionsUrl(LatLng origin, LatLng dest) {
// Origin of route
String str_origin = "origin=" + origin.latitude + "," + origin.longitude;
// Destination of route
String str_dest = "destination=" + dest.latitude + "," + dest.longitude;
// Sensor enabled
String sensor = "sensor=false&alternatives=true&units=metric&mode=driving";
//&alternatives=true&units=metric&mode=driving
// Building the parameters to the web service
String parameters = str_origin + "&" + str_dest + "&" + sensor;
// Output format
String output = "json";
// Building the url to the web service
String url = "https://maps.googleapis.com/maps/api/directions/" + output + "?" + parameters;
return url;
}
/**
* A method to download json data from url
*/
private String downloadUrl(String strUrl) throws IOException {
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try {
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line);
}
data = sb.toString();
br.close();
} catch (Exception e) {
Log.d("Exception while downloading url", e.toString());
} finally {
iStream.close();
urlConnection.disconnect();
}
return data;
}
// Fetches data from url passed
private class DownloadTask extends AsyncTask<String, Void, String> {
// Downloading data in non-ui thread
#Override
protected String doInBackground(String... url) {
// For storing data from web service
String data = "";
try {
// Fetching the data from web service
data = downloadUrl(url[0]);
} catch (Exception e) {
Log.d("Background Task", e.toString());
}
return data;
}
// Executes in UI thread, after the execution of
// doInBackground()
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
ParserTask parserTask = new ParserTask();
// Invokes the thread for parsing the JSON data
parserTask.execute(result);
}
}
/**
* A class to parse the Google Places in JSON format
*/
private class ParserTask extends AsyncTask<String, Integer, List<List<List<HashMap<String, String>>>>> {
// Parsing the data in non-ui thread
#Override
protected List<List<List<HashMap<String, String>>>> doInBackground(String... jsonData) {
JSONObject jObject;
List<List<List<HashMap<String, String>>>> routes = null;
try {
jObject = new JSONObject(jsonData[0]);
DirectionsJSONParser parser = new DirectionsJSONParser();
// Starts parsing data
routes = parser.parse(jObject);
} catch (Exception e) {
e.printStackTrace();
}
return routes;
}
// Executes in UI thread, after the parsing process
#Override
protected void onPostExecute(List<List<List<HashMap<String, String>>>> result) {
ArrayList<LatLng> points = null;
PolylineOptions lineOptions = new PolylineOptions();
PolylineOptions lineOptions1 = null;
MarkerOptions markerOptions = new MarkerOptions();
String distance = "";
String duration = "";
Log.d("resultsize", result.size() + "");
int i = 0;
while (i < result.size()) {
// for(int i=0;i<result.size();i++){
//result.size()
//int g= i-1;
points = new ArrayList<LatLng>();
// lineOptions = new PolylineOptions();
// if(i==1){
// }else{
List<List<HashMap<String, String>>> path1 = result.get(i);
for (int s = 0; s < path1.size(); s++) {
Log.d("pathsize1", path1.size() + "");
// Fetching i-th route
List<HashMap<String, String>> path = path1.get(s);
Log.d("pathsize", path.size() + "");
// Fetching all the points in i-th route
for (int j = 0; j < path.size(); j++) {
lineOptions1 = new PolylineOptions();
HashMap<String, String> point = path.get(j);
// points = new ArrayList<LatLng>();
// if(j==0){ // Get distance from the list
// distance = (String)point.get("distance");
// continue;
// }else if(j==1){ // Get duration from the list
// duration = (String)point.get("duration");
// continue;
// }
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
// Log.d("latlng", position.toString());
points.add(position);
}
// lineOptions.addAll(points);
// lineOptions.width(5);
// lineOptions.color(Color.BLUE);
// map.addPolyline(lineOptions);
}
// }
if (i == 0) {
PolylineOptions line1 = new PolylineOptions();
line1.addAll(points);
line1.width(5);
line1.color(Color.RED);
map.addPolyline(line1);
} else if (i == 1) {
PolylineOptions line2 = new PolylineOptions();
line2.addAll(points);
line2.width(5);
line2.color(Color.BLUE);
map.addPolyline(line2);
} else if (i == 2) {
PolylineOptions line3 = new PolylineOptions();
line3.addAll(points);
line3.width(5);
line3.color(Color.GREEN);
map.addPolyline(line3);
}
// Adding all the points in the route to LineOptions
i++;
//
}
// Drawing polyline in the Google Map for the i-th route
// map.addPolyline(lineOptions);
}
}
Here is my code :
public class MyGoogleMapActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.googlemap);
GoogleMap map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
map.setMyLocationEnabled(true);
LatLng Paris= new LatLng(64.711696, 12.170481);
map.addMarker(new MarkerOptions().title("LolluSaba").position(Paris));
LatLng Cinema= new LatLng(34.711696, 2.170481);
map.addMarker(new MarkerOptions().title("Pseudo").position(Cinema));
}
}
And i like to draw a route from Paris to Cinema. How can I do it very simply ?
Assuming that you have the coordinates of the two points you want to draw, you can get the route from google using the following methods:
class GetDirection extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(MapaAnunciante.this);
dialog.setMessage("Drawing the route, please wait!");
dialog.setIndeterminate(false);
dialog.setCancelable(false);
dialog.show();
}
protected String doInBackground(String... args) {
String stringUrl = "http://maps.googleapis.com/maps/api/directions/json?origin=" + origin+ "&destination=" + destination+ "&sensor=false";
StringBuilder response = new StringBuilder();
try {
URL url = new URL(stringUrl);
HttpURLConnection httpconn = (HttpURLConnection) url
.openConnection();
if (httpconn.getResponseCode() == HttpURLConnection.HTTP_OK) {
BufferedReader input = new BufferedReader(
new InputStreamReader(httpconn.getInputStream()),
8192);
String strLine = null;
while ((strLine = input.readLine()) != null) {
response.append(strLine);
}
input.close();
}
String jsonOutput = response.toString();
JSONObject jsonObject = new JSONObject(jsonOutput);
// routesArray contains ALL routes
JSONArray routesArray = jsonObject.getJSONArray("routes");
// Grab the first route
JSONObject route = routesArray.getJSONObject(0);
JSONObject poly = route.getJSONObject("overview_polyline");
String polyline = poly.getString("points");
pontos = decodePoly(polyline);
} catch (Exception e) {
}
return null;
}
protected void onPostExecute(String file_url) {
for (int i = 0; i < pontos.size() - 1; i++) {
LatLng src = pontos.get(i);
LatLng dest = pontos.get(i + 1);
try{
//here is where it will draw the polyline in your map
Polyline line = map.addPolyline(new PolylineOptions()
.add(new LatLng(src.latitude, src.longitude),
new LatLng(dest.latitude, dest.longitude))
.width(2).color(Color.RED).geodesic(true));
}catch(NullPointerException e){
Log.e("Error", "NullPointerException onPostExecute: " + e.toString());
}catch (Exception e2) {
Log.e("Error", "Exception onPostExecute: " + e2.toString());
}
}
dialog.dismiss();
}
}
private List<LatLng> decodePoly(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;
}
Where origin and destination are two strings containing the lat and lng of the points, formatted like "-1.0,2.0":
String origin = "64.711696,12.170481";
String destination = "34.711696,2.170481";
To execute it, just call new GetDirection().execute();
Hope it helps!
As you have two points so send it through google json which provides to draw route
between two points. See this example.
Route direction between two location
You Need to use the Directions API in combination with the Android Maps util Lib
Get the Encoded Polyline String from the Directions Api.
Decode the encoded string using Maps Util Lib into a list of lat/lng's (https://developers.google.com/maps/documentation/android/utility/#poly-encoding)
Draw the Polyline on the map using the lat/lngs!
First a List of LatLng you need
List<LatLng> ls_pos=new ArrayList<>();
After that In OnMapReady
mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
#Override
public boolean onMarkerClick(final Marker marker) {
if (ls_pos.size() >= 2) {
mMap.addPolyline(newPolylineOptions().addAll(ls_pos).width(10).color(Color.RED).visible(true).clickable(true));
ls_pos.clear
That's Work for me.