Google Map v2: "Android" extracting waypoint from json after passing string array - android

The code below takes 2 address point and show it on the map, however i wanted to edit it by adding "waypoint" on the application. My question is, how can i extract the waypoint information from the json like how start and end information extracted below.
public class DirectionJsonParser {
private static final String DIRECTION_URL_API = "https://maps.googleapis.com/maps/api/directions/json?";
private static final String GOOGLE_API_KEY = "key";
private DirectionJsonListener listener;
private String origin;
private String destination;
public DirectionJsonParser(DirectionJsonListener listener, String origin, String destination) {
this.listener = listener;
this.origin = origin;
this.destination = destination;
}
public void execute() throws UnsupportedEncodingException {
listener.onDirectionFinderStart();
new DownloadRawData().execute(createUrl());
}
private String createUrl() throws UnsupportedEncodingException {
String urlOrigin = URLEncoder.encode(origin, "utf-8");
String urlDestination = URLEncoder.encode(destination, "utf-8");
return DIRECTION_URL_API + "origin=" + urlOrigin + "&destination=" + urlDestination + "&key=" + GOOGLE_API_KEY;
}
private class DownloadRawData extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
String link = params[0];
try {
URL url = new URL(link);
InputStream is = url.openConnection().getInputStream();
StringBuffer buffer = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
return buffer.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String res) {
try {
parseJSon(res);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
private void parseJSon(String data) throws JSONException {
if (data == null)
return;
List<Route> routes = new ArrayList<Route>();
JSONObject jsonData = new JSONObject(data);
JSONArray jsonRoutes = jsonData.getJSONArray("routes");
for (int i = 0; i < jsonRoutes.length(); i++) {
JSONObject jsonRoute = jsonRoutes.getJSONObject(i);
Route route = new Route();
JSONObject overview_polylineJson = jsonRoute.getJSONObject("overview_polyline");
JSONArray jsonLegs = jsonRoute.getJSONArray("legs");
JSONObject jsonLeg = jsonLegs.getJSONObject(0);
JSONObject jsonDistance = jsonLeg.getJSONObject("distance");
JSONObject jsonDuration = jsonLeg.getJSONObject("duration");
JSONObject jsonEndLocation = jsonLeg.getJSONObject("end_location");
JSONObject jsonStartLocation = jsonLeg.getJSONObject("start_location");
route.distance = new Distance(jsonDistance.getString("text"), jsonDistance.getInt("value"));
route.duration = new Duration(jsonDuration.getString("text"), jsonDuration.getInt("value"));
route.endAddress = jsonLeg.getString("end_address");
route.startAddress = jsonLeg.getString("start_address");
route.startLocation = new LatLng(jsonStartLocation.getDouble("lat"), jsonStartLocation.getDouble("lng"));
route.endLocation = new LatLng(jsonEndLocation.getDouble("lat"), jsonEndLocation.getDouble("lng"));
route.points = decodePolyLine(overview_polylineJson.getString("points"));
routes.add(route);
}
listener.onDirectionFinderSuccess(routes);
}
private List<LatLng> decodePolyLine(final String poly) {
int len = poly.length();
int index = 0;
List<LatLng> decoded = new ArrayList<LatLng>();
int lat = 0;
int lng = 0;
while (index < len) {
int b;
int shift = 0;
int result = 0;
do {
b = poly.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 = poly.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
decoded.add(new LatLng(
lat / 100000d, lng / 100000d
));
}
return decoded;
}
}

To convert JSON to String, you can use the JSONStringer. Implements toString() and toString(). Most application developers should use those methods directly and disregard this API.
JSONObject object = ...
String json = object.toString();
Each stringer may be used to encode a single top level value. Instances of this class are not thread safe. Although this class is nonfinal, it was not designed for inheritance and should not be subclassed. In particular, self-use by overrideable methods is not specified.
Stringers only encode well-formed JSON strings. In particular:
The stringer must have exactly one top-level array or object.
Lexical scopes must be balanced: every call to array() must have a matching call to 'endArray()' and every call to object() must have a matching call to endObject().
Arrays may not contain keys (property names).
Objects must alternate keys (property names) and values.
Values are inserted with either literal value calls, or by nesting arrays or objects.
Calls that would result in a malformed JSON string will fail with a JSONException. Some implementations of the API support at most 20 levels of nesting. Attempts to create more than 20 levels of nesting may fail with a JSONException.

Related

Android GoogleMap show route to cover all locations?

I marked 10 locations using Google Maps addMarker() and is that possible to show route for reach all locations, the shortest route to cover all locations. If we click on one location it shows a route to reach there but I need connected route not only for one at a time.
You can use Google Maps Directions API with up to 23 waypoints (excluding the origin and destination) (its enough for your 10 marker places) with optimize:true (from Official Docs Optimize your waypoints section):
you may pass optimize:true as the first argument within the waypoints
parameter to allow the Directions service to optimize the provided
route by rearranging the waypoints in a more efficient order.
Something like that request:
https://maps.googleapis.com/maps/api/directions/json?origin=kilimanoor,in&destination=delhi,in&waypoints=optimize:true|via:12.972614,77.619728|via:17.381196,78.491409|via:21.150758,79.090297&key=YOUR_API_KEY
And than you should parse JSON response and, for example, draw route polyline based on it (you need data from overview_polyline tag for that). You can use code like this:
private String buildDirectionsUrl(List<LatLng> trackPoints) {
if (trackPoints.size() < 2) {
return null;
}
final LatLng origin = trackPoints.get(0);
final LatLng dest = trackPoints.get(trackPoints.size() - 1);
StringBuilder url = new StringBuilder();
url.append("https://maps.googleapis.com/maps/api/directions/json?");
url.append(String.format("origin=%8.5f,%8.5f", origin.latitude, origin.longitude));
url.append(String.format("&destination=%8.5f,%8.5f", dest.latitude, dest.longitude));
// add waypoints, if they exists
if (trackPoints.size() > 2) {
url.append("&waypoints=optimize:true|");
LatLng wayPoint;
for (int ixWaypoint = 1; ixWaypoint < trackPoints.size() - 2; ixWaypoint++) {
wayPoint = trackPoints.get(ixWaypoint);
url.append(String.format("%8.5f,%8.5f|", wayPoint.latitude, wayPoint.longitude));
}
url.delete(url.length() - 1, url.length());
}
url.append(String.format("&key=%s", getResources().getString(R.string.google_maps_key)));
return url.toString();
}
private class GetDirectionPointsAsyncTask extends AsyncTask<List<LatLng>, Void, List<LatLng>> {
protected void onPreExecute() {
super.onPreExecute();
}
protected List<LatLng> doInBackground(List<LatLng>... params) {
List<LatLng> routePoints = new ArrayList<>();
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(buildDirectionsUrl(params[0]));
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();
int responseCode = connection.getResponseCode();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder jsonStringBuilder = new StringBuilder();
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line+"\n");
jsonStringBuilder.append(line);
jsonStringBuilder.append("\n");
}
JSONObject jsonRoot = new JSONObject(jsonStringBuilder.toString());
JSONArray jsonRoutes = jsonRoot.getJSONArray("routes");
if (jsonRoutes.length() < 1) {
return null;
}
JSONObject jsonRoute = jsonRoutes.getJSONObject(0);
JSONObject overviewPolyline = jsonRoute.getJSONObject("overview_polyline");
String overviewPolylineEncodedPoints = overviewPolyline.getString("points");
routePoints = decodePoly(overviewPolylineEncodedPoints);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return routePoints;
}
#Override
protected void onPostExecute(List<LatLng> result) {
super.onPostExecute(result);
PolylineOptions polyLineOptions = new PolylineOptions();
polyLineOptions.addAll(result);
polyLineOptions.width(5);
polyLineOptions.color(Color.RED);
mGoogleMap.addPolyline(polyLineOptions);
LatLngBounds.Builder builder = new LatLngBounds.Builder();
builder.include(result.get(0));
builder.include(result.get(result.size()-1));
LatLngBounds bounds = builder.build();
mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 10));
}
}
//
// 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<>();
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;
}
Also see this tutorial.

why onMapready is executing before executing the called task

I have a code in which i call function(getData) before map fragment so that function is executed from that i call showList function but this is executed only after the OnMapready function. I actually don't know the reason behind it. The system first said that more work is done in main thread so skipped 49 frames to clear this i executed Showlist even as async task but the map function is called before ShowList(). Anyone say me the reason behind it. I know some logic is there but don't know what it is?
my code
public class GetCo extends FragmentActivity implements OnMapReadyCallback {
String path1la, path1lo, path2la, path2lo;
double dsla, dslo, ddla, ddlo, dp1la, dp1lo, dp2la, dp2lo;
private GoogleMap mMap;
public String myJSON;
private static final String TAG_RESULT = "RESULT";
private static final String TAG_ID = "id";
private static final String TAG_NAME = "Taskname";
private static final String TAG_KILOMETER = "Kilometer";
private static final String TAG_TIMING = "Timing";
private static final String TAG_SOLA = "SourceLa";
private static final String TAG_SOLO = "SourceLo";
private static final String TAG_DLA = "DestinationLa";
private static final String TAG_DLO = "DestinationLo";
private static final String TAG_P1LA = "Path1La";
private static final String TAG_P1LO = "Path1Lo";
private static final String TAG_P2LA = "Path2La";
private static final String TAG_P2LO = "Path2Lo";
JSONArray array = null;
String id, name, kmeter, time, sla, slo, p1la, p1lo, p2la, p2lo, dla, dlo;
TableLayout tl;
TableRow tr;
int c, vt;
TextView tn, kms, tm;
Button map;
String result=null;
String task;
#Override
public void onCreate(Bundle savedInstanceState) {
Intent in = getIntent();
task = in.getExtras().getString("task");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
getData();
// 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);
}
public void getData() {
class GetDataJSON extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
DefaultHttpClient httpclient = new DefaultHttpClient(new BasicHttpParams());
Uri.Builder builder = new Uri.Builder();
builder.scheme("http")
.authority("www.futuroitsolutions.in")
.appendPath("php_android_api")
.appendPath("datare.php")
.appendQueryParameter("Taskname", task);
String myUrl = builder.build().toString();
Log.d("String",task);
Log.d("url",myUrl);
HttpGet httpget = new HttpGet(myUrl);
// Depends on your web service
httpget.setHeader("Content-type", "application/json");
InputStream inputStream = null;
try {
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
inputStream = entity.getContent();
// json is UTF-8 by default
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
result = sb.toString();
} catch (Exception e) {
// Oops
} finally {
try {
if (inputStream != null) inputStream.close();
} catch (Exception squish) {
}
}
return result;
}
#Override
protected void onPostExecute(String result) {
myJSON=result;
Log.d("jsooon",myJSON);
ShowList(myJSON);
}
}
GetDataJSON g = new GetDataJSON();
g.execute();
}
public void ShowList(String json) {
final String vi = json;
{
class GetData extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
try {
JSONObject j = null;
j = new JSONObject(vi);
// String notes = j.getString("result");
array = j.getJSONArray("result");
for (int i = 0; i < array.length(); i++) {
JSONObject c = array.getJSONObject(i);
id = c.getString(TAG_ID);
name = c.getString(TAG_NAME);
kmeter = c.getString(TAG_KILOMETER);
time = c.getString(TAG_TIMING);
sla = c.getString(TAG_SOLA);
slo = c.getString(TAG_SOLO);
p1la = c.getString(TAG_P1LA);
p1lo = c.getString(TAG_P1LO);
p2la = c.getString(TAG_P2LA);
p2lo = c.getString(TAG_P2LO);
dla = c.getString(TAG_DLA);
dlo = c.getString(TAG_DLO);
vt = array.length();
String v = String.valueOf(c);
String x = String.valueOf(vt);
Log.d("tagggggg", v);
Log.d("tag", name);
Log.d("tag", kmeter);
Log.d("tag", time);
Log.d("tag", x);
Log.d("lat", sla);
Log.d("log", slo);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
}
}
GetData g = new GetData();
g.execute();
}
}
public void onMapReady(GoogleMap googleMap) {
Log.d("start","first");
mMap = googleMap;
// dsla = Double.parseDouble(sla);
try {
// sla = URLEncoder.encode(sla, "UTF-8");
Log.d("inmap", sla);
dsla = Double.parseDouble(sla);
// slo = URLEncoder.encode(slo, "UTF-8");
dslo = Double.parseDouble(slo);
//path1la = URLEncoder.encode(path1la, "UTF-8");
dp1la = Double.parseDouble(path1la);
// path1lo = URLEncoder.encode(path1lo, "UTF-8");
dp1lo = Double.parseDouble(path1lo);
// path2la = URLEncoder.encode(path2la, "UTF-8");
dp2la = Double.parseDouble(path2la);
// path2lo = URLEncoder.encode(path2lo, "UTF-8");
dp2lo = Double.parseDouble(path2lo);
// dla = URLEncoder.encode(dla, "UTF-8");
ddla = Double.parseDouble(dla);
// dlo = URLEncoder.encode(dlo, "UTF-8");
ddlo = Double.parseDouble(dlo);
} catch (Exception e) {
}
String url1 = getMapsApiDirectionsUrl(dsla,dslo,dp1la,dp1lo,ddla,ddlo);
new connectAsyncTask(url1).execute();
// Getting JSON from URL
// Add a marker in Sydney and move the camera
LatLng kakkanad = new LatLng(10.007243, 76.354628);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(kakkanad, 18));
// mMap.addMarker(new MarkerOptions()
// .position(kakkanad)
// .title("Marker in kakkanad"));
//mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(Source, 18));
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
mMap.setMyLocationEnabled(true);
}
public String getMapsApiDirectionsUrl(double dsla,double dslo,double dp1la,double dp2lo,double ddla,double ddlo) {
//Log.d("in func",sla);
String c=String.valueOf(dsla);
Log.d("in func",c);
final LatLng source = new LatLng(dsla, dslo);
final LatLng path1 = new LatLng(dp1la, dp2lo);
final LatLng path2 = new LatLng(dp2la, dp2lo);
final LatLng dest = new LatLng(ddla, ddlo);
String origin = "", waypoints = "", destination = "";
try {
origin = "origin=" + URLEncoder.encode(String.valueOf(source.latitude), "UTF-8") + "," + URLEncoder.encode(String.valueOf(source.longitude), "UTF-8");
waypoints = "waypoints=" + URLEncoder.encode(String.valueOf(path1.latitude), "UTF-8") + "," + URLEncoder.encode(String.valueOf(path1.longitude), "UTF-8");
destination = "destination=" + URLEncoder.encode(String.valueOf(dest.latitude), "UTF-8") + "," + URLEncoder.encode(String.valueOf(dest.longitude), "UTF-8");
} catch (UnsupportedEncodingException e) {
}
String way = "", sour = "", desty = "";
try {
way = URLEncoder.encode(waypoints, "UTF-8");
desty = URLEncoder.encode(destination, "UTF-8");
sour = URLEncoder.encode(origin, "UTF-8");
} catch (UnsupportedEncodingException e) {
}
String key = "key=AIzaSyDOidVs6_dHl0cjEJ0-OhMfUY0oNFf1SOE";
String params = origin + "&" + destination + "&" + waypoints + "&" + key;
String output = "json";
// https://maps.googleapis.com/maps/api/directions/json?origin=Boston,MA&destination=Concord,MA&waypoints=Charlestown,MA|Lexington,MA&key=YOUR_API_KEY
// String url1="https://maps.googleapis.com/maps/api/directions/json?origin=edapally,kerala&destination=ernakulam,kerala&waypoints=optimize:true|palarivattom,kerala|vytilla,kerala&key=AIzaSyDOidVs6_dHl0cjEJ0-OhMfUY0oNFf1SOE";
String url = "https://maps.googleapis.com/maps/api/directions/"
+ output + "?" + params;
Log.d("taqg", url);
return url;
}
public void drawPath(String result) {
if (result != null) {
mMap.clear();
}
int height = 100;
int width = 100;
BitmapDrawable bitmapdraw = (BitmapDrawable) getResources().getDrawable(R.drawable.source);
Bitmap b = bitmapdraw.getBitmap();
Bitmap ssource = Bitmap.createScaledBitmap(b, width, height, false);
BitmapDrawable bitmapdraw1 = (BitmapDrawable) getResources().getDrawable(R.drawable.way);
Bitmap b1 = bitmapdraw1.getBitmap();
Bitmap sway = Bitmap.createScaledBitmap(
b1, width, height, false);
BitmapDrawable bitmapdraw2 = (BitmapDrawable) getResources().getDrawable(R.drawable.dest);
Bitmap b2 = bitmapdraw2.getBitmap();
Bitmap sdest = Bitmap.createScaledBitmap(b2, width, height, false);
LatLng Source = new LatLng(dsla, dslo);
mMap.addMarker(new MarkerOptions()
.position(Source)
.title("Source")
.icon(BitmapDescriptorFactory.fromBitmap(ssource)));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(Source, 18));
LatLng path1 = new LatLng(dp1la, dp1lo);
mMap.addMarker(new MarkerOptions()
.position(path1)
.title("path")
.icon(BitmapDescriptorFactory.fromBitmap(sway)));
LatLng path2 = new LatLng(dp2la, dp2lo);
mMap.addMarker(new MarkerOptions()
.position(path2)
.title("path")
.icon(BitmapDescriptorFactory.fromBitmap(sway)));
LatLng dest = new LatLng(ddla, ddlo);
mMap.addMarker(new MarkerOptions()
.position(dest)
.title("Destination")
.icon(BitmapDescriptorFactory.fromBitmap(sdest)));
try {
// Tranform the string into a json object
final JSONObject json = new JSONObject(result);
Log.d("array", result);
JSONArray routeArray = json.getJSONArray("routes");
int i = routeArray.length();
String x = String.valueOf(i);
Log.d("length", x);
JSONObject routes = routeArray.getJSONObject(0);
JSONObject overviewPolylines = routes
.getJSONObject("overview_polyline");
String encodedString = overviewPolylines.getString("points");
List<LatLng> list = decodePoly(encodedString);
Polyline line = mMap.addPolyline(new PolylineOptions()
.addAll(list)
.width(12)
.color(Color.parseColor("#FF0000"))//Google maps blue color
.geodesic(true)
);
/* for (int z = 0; z < list.size() - 1; z++) {
LatLng src = list.get(z);
LatLng desti = list.get(z + 1);
Polyline line = mMap.addPolyline(new PolylineOptions()
.add(new LatLng(src.latitude, src.longitude),
new LatLng(path1.latitude,path1.longitude),
new LatLng(path2.latitude,path2.longitude),
new LatLng(desti.latitude, desti.longitude))
.width(5).color(Color.BLUE).geodesic(true));
}
*/
} catch (Exception 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() {
// TODO Auto-generated method stub
super.onPreExecute();
progressDialog = new ProgressDialog(GetCo.this);
progressDialog.setMessage("Fetching route, Please wait...");
progressDialog.setIndeterminate(true);
progressDialog.show();
}
#Override
protected String doInBackground(Void... params) {
JSONParser jParser = new JSONParser();
String json = jParser.getJSONFromUrl(url);
Log.d("jsonnnnnnnnnnnnnnn", json);
return json;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
progressDialog.hide();
if (result != null) {
Log.d("jsonppp", result);
drawPath(result);
}
}
}
}

Efficiently drawing large distances of Polylines on Google Maps

I am currently trying to draw routes between 2 destinations utilizing requested JSON data from Google's Directions API. The version I currently have works well with destinations within around 150 miles. Yet when I try drawing poly lines across a state the application crashes. Below is the snippet of my Async task.
public class FetchRouteStepsFromService extends AsyncTask<Void,Void,StringBuilder> {
private LocalBroadcastManager manager;
private String currentAddress;
private String destinationAddress;
public FetchRouteStepsFromService(String currentAddress, String destinationAddress, Context context){
this.currentAddress = currentAddress;
this.destinationAddress = destinationAddress;
manager = LocalBroadcastManager.getInstance(context);
}
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;
}
#Override
protected void onPostExecute(StringBuilder result) {
super.onPostExecute(result);
try{
JSONObject jsonObj = new JSONObject(result.toString());
JSONArray routesJSONArray = jsonObj.getJSONArray("routes");
JSONObject beforeLegsJSONObject = routesJSONArray.getJSONObject(0);
JSONArray legsJSONArray = beforeLegsJSONObject.getJSONArray("legs");
JSONObject beforeStepsJSONObject = legsJSONArray.getJSONObject(0);
JSONArray stepsJSONArray = beforeStepsJSONObject.getJSONArray("steps");
List<LatLng> test = new ArrayList<>();
ArrayList<PolylineOptions> options = new ArrayList<>();
map.clear();
for(int i = 0; i < stepsJSONArray.length(); i++){
JSONObject object = stepsJSONArray.getJSONObject(i);
JSONObject polyLineObject = object.getJSONObject("polyline");
String encodedPoly = polyLineObject.getString("points");//Holds the code for the polyline (String)
test = decodePoly(encodedPoly);
//Todo: Maybe create a separate asynctask to add latlngs on separate thread?
for(int j = 0; j < test.size();j++){
PolylineOptions options1;
if(j != test.size() -1) {
LatLng startLocation = test.get(j);
LatLng nextLocation = test.get(j + 1);
options1 = new PolylineOptions().add(startLocation, nextLocation).width(5).color(Color.GREEN).geodesic(true);
map.addPolyline(options1);
}else{
LatLng startLocation = test.get(j);
LatLng nextLocation = test.get(j);
options1 = new PolylineOptions().add(startLocation, nextLocation).width(5).color(Color.GREEN).geodesic(true);
map.addPolyline(options1);
}
}
}
dialog.dismiss();
updateUI();
}catch (Exception e){
e.printStackTrace();
}
}
#Override
protected StringBuilder doInBackground(Void... params) {
try{
StringBuilder jsonResults = new StringBuilder();
String googleMapUrl = "https://maps.googleapis.com/maps/api/directions/json?" +
"origin="+currentAddress+"&" +
"destination="+destinationAddress+"&key=MY_KEY";
URL url = new URL(googleMapUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
InputStreamReader in = new InputStreamReader(conn.getInputStream());
int read;
char[] buff = new char[3000];
while((read = in.read(buff,0,3000)) != -1 ){
jsonResults.append(buff,0,read);
}
return jsonResults;
}catch (Exception e){
Log.d("PlanTrip","doInBackgroud exception");
e.printStackTrace();
}
return null;
}
}
This is a local class within my Fragment which holds the Google Map. I previously have tried to make this AsyncTask its own class. This class would broadcast an intent consisting of PolyLineOptions which would be received by the fragment's BroadcastReceiver. Although this did not work either. Any resources, advice, or feedback would be greatly appreciated.
EDIT 1: Logcat during large request

Android - How to remove straight line from multiple routes on Google Maps API v2

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

Android google maps API 2 got JSONException: Index 0 out of range [0..0)

im working with google maps API to route between some points (asking google apis for those road paths)..
in majority process working good but sometime got a JSONException: Index 0 out of range [0..0) while trying getJSONObject(0) on JSONArray("routes") cousing my app loss some road path;
im using real device with WiFi connection when testing this app, I think this it not the problem..
here some of my stuff..
on Asynctask
protected void onProgressUpdate(String... progress) {
super.onProgressUpdate();
if (progress != null)
drawPath(progress[0],color);
}
#Override
protected String doInBackground(Void... params) {
for (int i = 0; i < route_.size() - 1; i++) {
String url = jsonParser.makeURL(route_.get(i).latitude,
route_.get(i).longitude, route_.get(i + 1).latitude,
route_.get(i + 1).longitude);
//Log.i(TAG, i +" Asynctask : " + url);
JSONParser jParser = new JSONParser();
String json = jParser.getJSONFromUrl(url);
publishProgress(json);
}
return "";
}
URL maker
public String makeURL(double sourcelat, double sourcelog, double destlat,
double destlog) {
StringBuilder urlString = new StringBuilder();
urlString.append("http://maps.googleapis.com/maps/api/directions/json");
urlString.append("?origin=");// from
urlString.append(Double.toString(sourcelat));
urlString.append(",");
urlString.append(Double.toString(sourcelog));
urlString.append("&destination=");// to
urlString.append(Double.toString(destlat));
urlString.append(",");
urlString.append(Double.toString(destlog));
urlString.append("&sensor=false&mode=driving&alternatives=false"); //Log.d(TAG, urlString.toString());
return urlString.toString();
}
getting JSON form URL
public String getJSONFromUrl(String url) {
// Making HTTP request
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
json = sb.toString();
is.close();
} catch (Exception e) {
Log.e(TAG, "Buffer Error converting result " + e.toString());
}
return json;
}
public 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(((lat / 1E5)), ((lng / 1E5)));
poly.add(p);
}
return poly;
}
Drawing path
public void drawPath(String result , int color) {
try {
final JSONObject json = new JSONObject(result);
calcuDistTime(json);
JSONArray routeArray = json.getJSONArray("routes");Log.d(TAG, "JSON Len " + routeArray.length());
JSONObject routes;
routes = routeArray.getJSONObject(0); <<< HERE THE PROBLEM org.json.JSONException: Index 0 out of range [0..0)
JSONObject overviewPolylines = routes
.getJSONObject("overview_polyline");
String encodedString = overviewPolylines.getString("points");
List<LatLng> list = jsonParser.decodePoly(encodedString);
for (int z = 0; z < list.size() - 1; z++) {
LatLng src = list.get(z);
LatLng dest = list.get(z + 1);
map.addPolyline(new PolylineOptions()
.add(new LatLng(src.latitude, src.longitude),
new LatLng(dest.latitude, dest.longitude))
.width(8).color(color).geodesic(true));
// Log.d(TAG, z + "DRAW POLYLINE : " + list.get(z).toString());
}
} catch (JSONException e) {
Log.w(TAG, e.toString());
}
}
failed when routeArray.getJSONObject(0) got JSONException: Index 0 out of range [0..0) cousing my app loss some paths like above..
please help me which one I must change :(
thanks,
My Best Regards..
EDIT : after printing my JSONObject the problem is {"status":"OVER_QUERY_LIMIT","routes":[]}..this is why my problem like randomly .so sad :(..
how to solve that?
any tricks?.

Categories

Resources