I'm trying to set routes directions in my app using google API v2 but I'm getting this error that I can't find what is causing the problem
D/Exception while reading url﹕ java.io.FileNotFoundException: https://maps.googleapis.com/maps/api/directions/json?waypoints=optimize:true|-23.3246,-51.1489|-23.3206,-51.1459|-23.2975,-51.2007&sensor=false
And when I copy and paste that link on Chrome I get the following:
"error_message" : "Invalid request. Missing the 'origin' parameter.",
This is my map Class:
public class MapaViagem extends FragmentActivity {
private GoogleMap googleMap;
private String IdViagem;
private List<EnderecoModel> mEnderecoModel = new ArrayList<EnderecoModel>();
private ArrayList<LatLng> coordList = new ArrayList<LatLng>();
private ProgressDialog dialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
setContentView(R.layout.maps);
// Loading map
initilizeMap();
// Changing map type
googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
// googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
// googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
// googleMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
// googleMap.setMapType(GoogleMap.MAP_TYPE_NONE);
// Showing / hiding your current location
googleMap.setMyLocationEnabled(true);
// Enable / Disable zooming controls
googleMap.getUiSettings().setZoomControlsEnabled(true);
// Enable / Disable my location button
googleMap.getUiSettings().setMyLocationButtonEnabled(true);
// Enable / Disable Compass icon
googleMap.getUiSettings().setCompassEnabled(true);
// Enable / Disable Rotate gesture
googleMap.getUiSettings().setRotateGesturesEnabled(true);
// Enable / Disable zooming functionality
googleMap.getUiSettings().setZoomGesturesEnabled(true);
try {
Bundle parametros = getIntent().getExtras();
IdViagem = parametros.getString("id_viagem");
Repositorio mRepositorio = new Repositorio(this);
String waypoints = "waypoints=optimize:true";
String coordenadas = "";
mEnderecoModel = mRepositorio.getListaEnderecosDaViagem(Integer.valueOf(IdViagem));
for (int j = 0; j < mEnderecoModel.size(); j++) {
float latitude = Float.parseFloat(mEnderecoModel.get(j).getLatitude());
float longitude = Float.parseFloat(mEnderecoModel.get(j).getLongitude());
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude, longitude), 10));
coordenadas += "|" + latitude + "," + longitude;
coordList.add(new LatLng(latitude, longitude));
// Creating MarkerOptions
MarkerOptions options = new MarkerOptions();
// Setting the position of the marker
options.position(new LatLng(latitude, longitude));
if (j == mEnderecoModel.size() - 1) {
options.icon(BitmapDescriptorFactory.fromBitmap(writeTextOnDrawable(R.drawable.vermelho, String.valueOf(mEnderecoModel.size()))));
} else {
options.icon(BitmapDescriptorFactory.fromBitmap(writeTextOnDrawable(R.drawable.verde, String.valueOf(j + 1))));
}
// Add new marker to the Google Map Android API V2
googleMap.addMarker(options);
}
String sensor = "sensor=false";
String params = waypoints + coordenadas + "&" + sensor;
String url = "https://maps.googleapis.com/maps/api/directions/json?" + params;
ReadTask downloadTask = new ReadTask();
downloadTask.execute(url);
} catch (Exception e) {
e.printStackTrace();
}
}
private class ReadTask extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(MapaViagem.this);
// setup your dialog here
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.setTitle("Traçando Rotas");
dialog.setMessage("Aguarde...");
dialog.setCancelable(false);
dialog.show();
}
#Override
protected String doInBackground(String... url) {
String data = "";
try {
HttpConnection http = new HttpConnection();
data = http.readUrl(url[0]);
} catch (Exception e) {
e.printStackTrace();
}
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
new ParserTask().execute(result);
}
}
private class ParserTask extends
AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {
#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]);
PathJSONParser parser = new PathJSONParser();
routes = parser.parse(jObject);
} catch (Exception e) {
e.printStackTrace();
}
return routes;
}
#Override
protected void onPostExecute(List<List<HashMap<String, String>>> routes) {
ArrayList<LatLng> points = null;
PolylineOptions polyLineOptions = null;
if(routes != null){
for (int i = 0; i < routes.size(); i++) {
points = new ArrayList<LatLng>();
polyLineOptions = new PolylineOptions();
List<HashMap<String, String>> path = routes.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);
}
polyLineOptions.addAll(points);
polyLineOptions.width(4);
polyLineOptions.color(Color.BLUE);
}
googleMap.addPolyline(polyLineOptions);
}
if (dialog.isShowing()) {
dialog.dismiss();
}
}
}
private Bitmap writeTextOnDrawable(int drawableId, String text) {
Bitmap bm = BitmapFactory.decodeResource(getResources(), drawableId)
.copy(Bitmap.Config.ARGB_8888, true);
Typeface tf = Typeface.create("Helvetica", Typeface.BOLD);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
paint.setTypeface(tf);
paint.setTextAlign(Paint.Align.CENTER);
paint.setTextSize(convertToPixels(MapaViagem.this, 11));
Rect textRect = new Rect();
paint.getTextBounds(text, 0, text.length(), textRect);
Canvas canvas = new Canvas(bm);
//If the text is bigger than the canvas , reduce the font size
if (textRect.width() >= (canvas.getWidth() - 4)) //the padding on either sides is considered as 4, so as to appropriately fit in the text
paint.setTextSize(convertToPixels(MapaViagem.this, 7)); //Scaling needs to be used for different dpi's
//Calculate the positions
int xPos = (canvas.getWidth() / 2) - 1; //-2 is for regulating the x position offset
//"- ((paint.descent() + paint.ascent()) / 2)" is the distance from the baseline to the center.
int yPos = (int) ((canvas.getHeight() / 2) - ((paint.descent() + paint.ascent()) / 8f));
canvas.drawText(text, xPos, yPos, paint);
return bm;
}
public static int convertToPixels(Context context, int nDP) {
final float conversionScale = context.getResources().getDisplayMetrics().density;
return (int) ((nDP * conversionScale) + 0.5f);
}
private void initilizeMap() {
if (googleMap == null) {
googleMap = ((MapFragment) getFragmentManager().findFragmentById(
R.id.map)).getMap();
// check if map is created successfully or not
if (googleMap == null) {
Toast.makeText(getApplicationContext(),
"Não foi possível carregar o mapa", Toast.LENGTH_SHORT)
.show();
}
}
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#Override
public void onBackPressed() {
super.onBackPressed();
overridePendingTransition(R.anim.animation_back, R.anim.animation_back_leave);
finish();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_mapa, menu);
return super.onCreateOptionsMenu(menu);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
super.onBackPressed();
overridePendingTransition(R.anim.animation_back, R.anim.animation_back_leave);
finish();
return true;
case R.id.menu_atualizar_mapa:
/* dispara os repositorios a sincronizar */
new Sincronizar(MapaViagem.this, MapaViagem.this).execute(0);
}
return true;
}
#Override
protected void onResume() {
super.onResume();
initilizeMap();
}
}
The url which is being generated in the code : "https://maps.googleapis.com/maps/api/directions/json?waypoints=optimize:true|-23.3246,-51.1489|-23.3206,-51.1459|-23.2975,-51.2007&sensor=false"
is WRONG.
Your URL should be like this : "https://maps.googleapis.com/maps/api/directions/json?origin=-23.3246,-51.1489&destination=-23.2975,-51.2007&%20waypoints=optimize:true|-23.3246,-51.1489|-23.3206,-51.1459|-23.2975,-51.2007&sensor=false"
Here's the code to generate the url :
private String getMapsApiDirectionsUrl(LatLng Office, LatLng home) {
String waypoints = "waypoints=optimize:true|"
+ Office.latitude + "," + Office.longitude
+ "|" + "|" + home.latitude + ","
+ home.longitude;
String OriDest = "origin="+Office.latitude+","+Office.longitude+"&destination="+home.latitude+","+home.longitude;
String sensor = "sensor=false";
String params = OriDest+"&%20"+waypoints + "&" + sensor;
String output = "json";
String url = "https://maps.googleapis.com/maps/api/directions/"
+ output + "?" + params;
return url;
}
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 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
Using Map Api V2 I have drawn a route on the map. Now i wish to save this route in my database.
So I need to get the lat/lng of points on the route say after each 100 meters which i will save as a polygon. How can i do it in Google Map V2 in android.
i am stuck on it from last 10 days but not getting a solution.
any help will be appriciable :)
public class NavigationActivity extends FragmentActivity {
public static final String TAG_SLAT = "sourcelat";
public static final String TAG_SLONG = "sourcelong";
public static final String TAG_DLAT = "destinationlat";
public static final String TAG_DLONG = "destinationg";
private static LatLng Source = null;
private static LatLng Destination = null;
private GoogleMap map;
private SupportMapFragment fragment;
private LatLngBounds latlngBounds;
private Button bNavigation;
private Polyline newPolyline;
private Marker smarker;
private Marker dmarker;
Geocoder geocoder;
private boolean isTraveling = false;
private int width, height;
private String sourcelat;
private String sourcelong;
private String destinationg;
private String destinationlat;
double slat;
double slong;
double dlat;
double dlong;
double d;
double tempDistance;
String distance;
ConnectionDetector cd;
Boolean isConnectingToInternet = false;
String ts;
LatLng latLng;
GPSTracker gps;
List<Address> addresses;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!isGooglePlayServicesAvailable()) {
finish();
}
setContentView(R.layout.activity_navigation);
cd = new ConnectionDetector(getApplicationContext());
isConnectingToInternet = cd.isConnectingToInternet();
if (isConnectingToInternet) {
Intent in = getIntent();
sourcelat = in.getStringExtra(TAG_SLAT);
destinationlat = in.getStringExtra(TAG_DLAT);
destinationg = in.getStringExtra(TAG_DLONG);
sourcelong = in.getStringExtra(TAG_SLONG);
slat = Double.parseDouble(sourcelat);
slong = Double.parseDouble(sourcelong);
dlat = Double.parseDouble(destinationlat);
dlong = Double.parseDouble(destinationg);
Source = new LatLng(slat, slong);
Destination = new LatLng(dlat, dlong);
getSreenDimanstions();
fragment = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map));
map = fragment.getMap();
map.setMyLocationEnabled(true);
map.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
map.setTrafficEnabled(true);
ImageButton cureent_location = (ImageButton) findViewById(R.id.clocation);
cureent_location.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onLocationChanged();
}
});
if (!isTraveling) {
isTraveling = true;
findDirections(Source.latitude, Source.longitude, Destination.latitude, Destination.longitude, GMapV2Direction.MODE_DRIVING);
} else {
isTraveling = false;
}
}else {
AlertUtils.showAlertDialog(NavigationActivity.this, "No Internet Detected", "Please check your internet connection.", false);
}
}
public double calculateDistance(double fromLatitude,double fromLongitude,double toLatitude,double toLongitude)
{
float results[] = new float[1];
try {
Location.distanceBetween(fromLatitude, fromLongitude, toLatitude, toLongitude, results);
} catch (Exception e) {
if (e != null)
e.printStackTrace();
}
if (Source.equals(Destination)){
distance="0";
}
else {
int dist = (int) results[0];
if (dist <= 0)
return 0D;
DecimalFormat decimalFormat = new DecimalFormat("#.##");
results[0] /= 1000D;
distance = decimalFormat.format(results[0]);
double d = Double.parseDouble(distance);
double speed = 40;
double time = d / speed;
ts = manual(time);
Log.v("fdf", String.valueOf(ts));
}
return d;
}
private static String manual(double eta) {
int hour = (int) eta;
eta = (eta - hour) * 60;
int minutes = (int) eta;
eta = (eta - minutes) * 60;
int seconds = (int) eta;
eta = (eta - seconds) * 1000;
int ms = (int) eta;
//Log.d("ffgfh", String.valueOf(eta));
return String.format("%dHr %dMin ", hour, minutes);
}
#Override
protected void onResume() {
super.onResume();
latlngBounds = createLatLngBoundsObject(Source, Destination);
map.moveCamera(CameraUpdateFactory.newLatLngBounds(latlngBounds, width, height, 100));
}
public void handleGetDirectionsResult(ArrayList<LatLng> directionPoints) {
PolylineOptions rectLine = new PolylineOptions().width(5).color(Color.RED);
//MarkerOptions marker = new MarkerOptions().position(Source).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
MarkerOptions marker1 = new MarkerOptions().position(Destination).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
for(int i = 0 ; i < directionPoints.size() ; i++)
{
rectLine.add(directionPoints.get(i));
}
if (newPolyline != null)
{
newPolyline.remove();
}
newPolyline = map.addPolyline(rectLine);
//smarker = map.addMarker(marker);
dmarker = map.addMarker(marker1);
if (isTraveling) {
latlngBounds = createLatLngBoundsObject(Source, Destination);
map.animateCamera(CameraUpdateFactory.newLatLngBounds(latlngBounds, width, height, 100));
Dialog dialog_help = new Dialog(this);
dialog_help .requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog_help.setContentView(R.layout.title_multi_selectitems_dialog);
calculateDistance(slat, slong, dlat, dlong);
TextView dis = (TextView) dialog_help.findViewById(R.id.distance);
dis.setText("Distance " + distance + "Km ");
TextView tim = (TextView) dialog_help.findViewById(R.id.time);
tim.setText("Time " + ts);
dialog_help.setCancelable(true);
dialog_help.setTitle("Distance & Time" );
dialog_help.setCanceledOnTouchOutside(true);
dialog_help.show();
dialog_help.getWindow().setGravity(Gravity.CENTER);
dialog_help.getWindow().setBackgroundDrawable(new ColorDrawable(Color.LTGRAY));
dialog_help.getWindow().setLayout(RadioGroup.LayoutParams.WRAP_CONTENT, RadioGroup.LayoutParams.WRAP_CONTENT);
}
else {
map.animateCamera(CameraUpdateFactory.newLatLngBounds(latlngBounds, width, height, 100));
}
}
private void getSreenDimanstions()
{
Display display = getWindowManager().getDefaultDisplay();
width = display.getWidth();
height = display.getHeight();
}
private LatLngBounds createLatLngBoundsObject(LatLng firstLocation, LatLng secondLocation)
{
if (firstLocation != null && secondLocation != null)
{
LatLngBounds.Builder builder = new LatLngBounds.Builder();
builder.include(firstLocation).include(secondLocation);
return builder.build();
}
return null;
}
public void findDirections(double fromPositionDoubleLat, double fromPositionDoubleLong, double toPositionDoubleLat, double toPositionDoubleLong, String mode)
{
Map<String, String> map = new HashMap<String, String>();
map.put(GetDirectionsAsyncTask.USER_CURRENT_LAT, String.valueOf(fromPositionDoubleLat));
map.put(GetDirectionsAsyncTask.USER_CURRENT_LONG, String.valueOf(fromPositionDoubleLong));
map.put(GetDirectionsAsyncTask.DESTINATION_LAT, String.valueOf(toPositionDoubleLat));
map.put(GetDirectionsAsyncTask.DESTINATION_LONG, String.valueOf(toPositionDoubleLong));
map.put(GetDirectionsAsyncTask.DIRECTIONS_MODE, mode);
GetDirectionsAsyncTask asyncTask = new GetDirectionsAsyncTask(this);
try {
asyncTask.execute(map);
}catch (Exception e){
Toast.makeText(getBaseContext(), "Something went Wrong", Toast.LENGTH_SHORT).show();
}
}
public void onLocationChanged( ){
TextView cl = (TextView) findViewById(R.id.latlongLocation);
cd = new ConnectionDetector(getApplicationContext());
isConnectingToInternet = cd.isConnectingToInternet();
if (isConnectingToInternet) {
gps = new GPSTracker(NavigationActivity.this);
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();
latLng = new LatLng(latitude, longitude);
geocoder = new Geocoder(this, Locale.getDefault());
try {
addresses = geocoder.getFromLocation(latitude, longitude, 1);
} catch (IOException e) {
e.printStackTrace();
}
String address = addresses.get(0).getAddressLine(0);
String prmises = addresses.get(0).getAddressLine(1);
String city = addresses.get(0).getAddressLine(2);
String country = addresses.get(0).getAddressLine(3);
cl.setText(address + " " + prmises + " " + city + " " + country);
}else {
AlertUtils.showAlertDialog(NavigationActivity.this, "No Internet Detected", "Please check your internet connection.", false);
}
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
return false;
}
}
}
You can try it with this map application: http://maps.cloudmade.com/.
At first you create your route with waypoints. Click on the button "Get directions" (upper left corner) and create your route (clicking on the map). After that you can export (there is a button on the upper right corner) your route (include waypoints) to a gpx-or a json-file. You can load both files to a GIS.
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;
}
}
I'm trying to implement a cluster marker on my map, and it is behaving a little strange, first, it shows me the cluster marker with the right number of markers, but when I zoom out to join other markers it generates another cluster marker which I don't know where it is coming from and why it is showing on the map, I`ll add some image to explain it better:
Here is the image with zoom in, as you can see, I have a cluster marker with 8 points and another one alone, so when I zoom out it should give me one clusterMarker with 9 points, but look what happens when I zoom out:
What that cluster marker with 7 points is doing there?
here is my code:
public class MapaViagem extends FragmentActivity implements ClusterManager.OnClusterClickListener<MyItem>, ClusterManager.OnClusterItemClickListener<MyItem> {
private GoogleMap googleMap;
private String rm_IdViagem;
private List<ClienteModel> mClienteModel = new ArrayList<ClienteModel>();
private List<EnderecoModel> mEnderecoModel = new ArrayList<EnderecoModel>();
private ArrayList<LatLng> coordList = new ArrayList<LatLng>();
private ArrayList<String> nomes = new ArrayList<String>();
private ViagemModel mViagemModel = new ViagemModel();
private ClusterManager<MyItem> mClusterManager;
private ProgressDialog dialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.maps);
try {
Bundle parametros = getIntent().getExtras();
rm_IdViagem = parametros.getString("id_viagem");
Repositorio ca = new Repositorio(this);
mViagemModel = ca.getViagemPorId(Integer.valueOf(rm_IdViagem));
Repositorio cl = new Repositorio(this);
mClienteModel = cl.getClientesViagem(Integer.valueOf(rm_IdViagem));
String waypoints = "waypoints=optimize:true";
String coordenadas = "";
if(mClienteModel != null) {
for (int i = 0; i < mClienteModel.size(); i++) {
Repositorio mRepositorio = new Repositorio(this);
mEnderecoModel = mRepositorio.getListaEnderecosDoCliente(Integer.valueOf(mClienteModel.get(i).getClientes_id()));
for (int j = 0; j < mEnderecoModel.size(); j++) {
// Loading map
initilizeMap();
// Changing map type
googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
// googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
// googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
// googleMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
// googleMap.setMapType(GoogleMap.MAP_TYPE_NONE);
// Showing / hiding your current location
googleMap.setMyLocationEnabled(true);
// Enable / Disable zooming controls
googleMap.getUiSettings().setZoomControlsEnabled(true);
// Enable / Disable my location button
googleMap.getUiSettings().setMyLocationButtonEnabled(true);
// Enable / Disable Compass icon
googleMap.getUiSettings().setCompassEnabled(true);
// Enable / Disable Rotate gesture
googleMap.getUiSettings().setRotateGesturesEnabled(true);
// Enable / Disable zooming functionality
googleMap.getUiSettings().setZoomGesturesEnabled(true);
float latitude = Float.parseFloat(mEnderecoModel.get(j).getLatitude());
float longitude = Float.parseFloat(mEnderecoModel.get(j).getLongitude());
coordenadas += "|" + latitude + "," + longitude;
nomes.add(mClienteModel.get(i).getNome());
coordList.add(new LatLng(latitude, longitude));
mClusterManager = new ClusterManager<MyItem>(MapaViagem.this, googleMap);
mClusterManager.setRenderer(new MyClusterRenderer(MapaViagem.this, googleMap, mClusterManager));
addItems(coordList, nomes);
googleMap.setOnCameraChangeListener(mClusterManager);
googleMap.setOnMarkerClickListener(mClusterManager);
mClusterManager.setOnClusterClickListener(this);
mClusterManager.setOnClusterItemClickListener(this);
mClusterManager.cluster();
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude, longitude), 5));
}
}
String sensor = "sensor=false";
String params = waypoints + coordenadas + "&" + sensor;
String output = "json";
String url = "https://maps.googleapis.com/maps/api/directions/" + output + "?" + params;
ReadTask downloadTask = new ReadTask();
downloadTask.execute(url);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public class MyClusterRenderer extends DefaultClusterRenderer<MyItem> {
public MyClusterRenderer(Context context, GoogleMap map,
ClusterManager<MyItem> clusterManager) {
super(context, map, clusterManager);
}
#Override
protected void onBeforeClusterItemRendered(MyItem item, MarkerOptions markerOptions) {
super.onBeforeClusterItemRendered(item, markerOptions);
markerOptions.title(String.valueOf(item.getName()));
}
#Override
protected void onClusterItemRendered(MyItem clusterItem, Marker marker) {
super.onClusterItemRendered(clusterItem, marker);
//here you have access to the marker itself
}
#Override
protected boolean shouldRenderAsCluster(Cluster<MyItem> cluster) {
return cluster.getSize() > 1;
}
}
}
There seems to be an issue in this code:
coordenadas += "|" + latitude + "," + longitude; nomes.add(mClienteModel.get(i).getNome());
coordList.add(new LatLng(latitude, longitude));
mClusterManager = new ClusterManager<MyItem>(MapaViagem.this, googleMap);
mClusterManager.setRenderer(new MyClusterRenderer(MapaViagem.this, googleMap, mClusterManager));
addItems(coordList, nomes);
You should be adding these two things in there:
getMap().setOnCameraChangeListener(mClusterManager);
and
private void addItems() {
// Set some lat/lng coordinates to start with.
double lat = 51.5145160;
double lng = -0.1270060;
// Add ten cluster items in close proximity, for purposes of this example.
for (int i = 0; i < 10; i++) {
double offset = i / 60d;
lat = lat + offset;
lng = lng + offset;
MyItem offsetItem = new MyItem(lat, lng);
mClusterManager.addItem(offsetItem);
}
Here's an example from the documentation: https://developers.google.com/maps/documentation/android/utility/marker-clustering#simple