I am creating an app and i am drawing a route from current marker to nearby markers. when i tap on nearby marker it created a route, and when i again tap on another marker previous route still show. so i want to remove the previous route and draw a new route from current marker to nearby marker. Please help me using my source code....
mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker arg0) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
//for direction Route
if(CurrentMarker != null) {
LatLng origin = CurrentMarker.getPosition();
LatLng dest = marker.getPosition();
String url = getDirectionsUrl(origin, dest);
DownloadPar downloadPar = new DownloadPar();
// Start downloading json data from Google Directions API
downloadPar.execute(url);
}
View myContentsView = getLayoutInflater().inflate(R.layout.details, null);
TextView tvTitle = ((TextView)myContentsView.findViewById(R.id.title));
tvTitle.setText(marker.getTitle());
TextView tvSnippet = ((TextView)myContentsView.findViewById(R.id.snippet));
tvSnippet.setText(marker.getSnippet());
return myContentsView;
}
});
Please help me...
Thanks
Declare a variable:
private Polyline polyline;
Then in your method when you initially add the Polyline to the Map:
polyline = mMap.addPolyline(lineOptions);
Then when you want to update the Polyline I believe you can use:
polyline.setPoints(newPoints);
Otherwise, remove the polyline by calling polyline.setMap(null) and create a new one like you have done above.
For more information regarding Polyline, see the documentation
protected void onPostExecute(List>> result) {
ArrayList points = null;
PolylineOptions lineOptions = null;
// MarkerOptions markerOptions = new MarkerOptions();
//markerOptions.position(latLng);
// markerOptions.title("Find Location");
// markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
// FindMarker = mMap.addMarker(markerOptions);
// Traversing through all the routes
for (int i = 0; i < result.size(); i++) {
points = new ArrayList<LatLng>();
lineOptions = new PolylineOptions();
// Fetching i-th route
List<HashMap<String, String>> path = result.get(i);
// Fetching all the points in i-th route
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);
}
// Adding all the points in the route to LineOptions
lineOptions.addAll(points);
lineOptions.width(8);
lineOptions.color(Color.GRAY);
}
// Drawing polyline in the Google Map for the i-th route
mMap.addPolyline(lineOptions);
}
}
Related
I am using the HERE Maps Lite SDK for Android as a library in my project.
I want to show MapView, and add overlays of all shelters I have in my database, in their specific coordinates.
The map works well, but the shown coordinates are not accurate. I tried to geocode the coordinates in lat-long website, and they are correct, but in the map they are shown right to their real location.
My code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shelters_map);
mapView = findViewById(R.id.mapview);
mapView.onCreate(savedInstanceState);
ActivityCompat.requestPermissions(SheltersMapActivity.this, new String[] {
Manifest.permission.ACCESS_FINE_LOCATION}, 123);
if (ContextCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
Toast.makeText(getApplicationContext(), "אנא אפשר גישה לשירותי מיקום", Toast.LENGTH_SHORT).show();
ActivityCompat.requestPermissions(this,
new String[]{ACCESS_FINE_LOCATION},
1);
} else // premission is granted
{
GPStracker g = new GPStracker(getApplicationContext());
userLocation = g.getLocation();
}
loadMapScene();
addSheltersOverlay();
// loadMapScene();
}
private void loadMapScene() {
// Load a scene from the SDK to render the map with a map style.
mapView.getMapScene().loadScene(MapStyle.NORMAL_DAY, new MapScene.LoadSceneCallback() {
#Override
public void onLoadScene(#Nullable MapScene.ErrorCode errorCode) {
if (errorCode == null) {
mapView.getCamera().setTarget(new GeoCoordinates(userLocation.getLatitude(),
userLocation.getLongitude()));
mapView.getCamera().setZoomLevel(15);
} else {
Log.d("data1", "onLoadScene failed: " + errorCode.toString());
}
}
});
}
private void addSheltersOverlay() {
db = new DatabaseHandler(this);
ArrayList<Shelter> places = this.db.getAllPlaces();
Shelter userLocationPlace = new Shelter("המיקום שלך", "", userLocation, null, 0, "");
places.add(userLocationPlace);
int size = places.size();
for(int i = 0; i < size; i++) {
TextView textView = new TextView(this);
textView.setTextColor(Color.parseColor("#FFFFFF"));
textView.setText(places.get(i).getName());
LinearLayout linearLayout = new LinearLayout(this);
if (places.get(i) instanceof Basement)
linearLayout.setBackgroundColor(Color.BLACK);
else if (places.get(i) instanceof Stairs)
linearLayout.setBackgroundColor(Color.GREEN);
else
linearLayout.setBackgroundColor(Color.BLUE);
linearLayout.setPadding(10, 10, 10, 10);
linearLayout.addView(textView);
GeoCoordinates geoCoordinates = new GeoCoordinates(places.get(i).getLocation().getLatitude(),
places.get(i).getLocation().getLongitude());
MapOverlay<LinearLayout> mapOverlay = new MapOverlay<>(linearLayout, geoCoordinates);
mapView.addMapOverlay(mapOverlay);
}
}
The shown map:
.
I can see the streets names in the shown map itself, and I see that it is not the accurate point.
Anybody help?
From the code it looks correct, but I cannot see the location vs. the expected location. By default, MapOverlays are drawn centered on the coordinates. You can set an anchor point to move the overlay in relation to the coordinates. This could help if there is always an offset between the coordinates in your database and the location on the map.
Maybe, can you try to render a small MapCircle item onto the map at the expected location? Then you can more easily see where that location lies on the map. You can compare the results with https://www.latlong.net/.
I have 3 points of which i want a polyline to be drawn but a polyline isn't visible.
First and foremost , the 3 markers are available on the map , so i tried to join them with a polyline and it refused, and to me the code seems fine, but a polyline is not visible , How can i improve my code.
Below is my code:
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
setUpClusterer(mMap);
}
//clustered map
private void setUpClusterer(GoogleMap mMap) {
// Position the map.
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(-23.684, 133.903), 4));
// Initialize the manager with the context and the map.
// (Activity extends context, so we can pass 'this' in the constructor.)
mClusterManager = new ClusterManager<MyItem>(this, mMap);
// Point the map's listeners at the listeners implemented by the cluster
// manager.
mMap.setOnCameraIdleListener(mClusterManager);
mMap.setOnMarkerClickListener(mClusterManager);
// Add cluster items (markers) to the cluster manager.
addItems(mMap);
}
private void addItems(GoogleMap mMap) {
// Set some lat/lng coordinates to start with.
double lat = 51.5145160;
double lng = -0.1270060;
HashMap<Double,Double> hm = new HashMap<>();
/* new LatLng(-34.747, 145.592),
new LatLng(-34.364, 147.891),
new LatLng(-33.501, 150.217),*/
hm.put(-34.747,145.592);
hm.put(-34.364,147.891);
hm.put(-33.501,150.217);
// Add ten cluster items in close proximity, for purposes of this example.
for(Map.Entry m:hm.entrySet()){
System.out.println(m.getKey()+" "+m.getValue());
MyItem offsetItem = new MyItem(Double.parseDouble(m.getKey().toString()),Double.parseDouble(m.getValue().toString()));
mClusterManager.addItem(offsetItem);
Polyline polyline = mMap.addPolyline(new PolylineOptions()
.clickable(true)
.add(
new LatLng(Double.parseDouble(m.getKey().toString()), Double.parseDouble(m.getValue().toString()))
));
stylePolyline(polyline);
}
}
You are creating one Polyline for each point. You need to create some kind of iterable (an ArrayList for example), add the LatLngs to it and then add all the points to a new Polyline:
List<LatLngs> latLngs = new ArrayList<LatLng>();
for(Map.Entry m:hm.entrySet()){
MyItem offsetItem = new MyItem(Double.parseDouble(m.getKey().toString()),Double.parseDouble(m.getValue().toString()));
mClusterManager.addItem(offsetItem);
latLngs.add(new LatLng(Double.parseDouble(m.getKey().toString()), Double.parseDouble(m.getValue().toString())));
}
Polyline polyline = mMap.addPolyline(new PolylineOptions()
.clickable(true)
.addAll(latLngs));
stylePolyline(polyline);
When I click somewhere on map, app draw polyline between current location and destination (click). I want that destination marker is clicking by himself all the time (every few seconds), so on user movement new polylines are drawing (updating the last one).
I tried with handler and bunch of the things and didn't find solution.
Any answer would be highly appreciated.
private ArrayList<LatLng> mClickedPoints;
/** Setting onclick listener for the map */
mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng point) {
/**
* Clearing map if user clicks on map more then one time.
* Reseting View widgets and arrays, adding points of interests
*/
if (mClickedPoints.size() > 1) {
mMap.clear();
mClickedPoints.clear();
mClickedPoints = new ArrayList<>();
}
/** Adding current location to the ArrayList */
mClickedPoints.add(start);
Log.i("current location", start.toString());
MarkerOptions options = new MarkerOptions();
options.position(start);
/** Destination click */
mClickedPoints.add(point);
/** Setting the position of the marker */
options.position(point);
/** Checks if start and end locations are captured */
if (mClickedPoints.size() >= 2) {
orig = mClickedPoints.get(0);
dest = mClickedPoints.get(1);
}
mMap.addMarker(options);
request_directions_and_get_response();
}
});
onLocationChanged() override:
#Override
public void onLocationChanged(Location location) {
mLastLocation = location;
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
/** Setting current location marker */
start = new LatLng(location.getLatitude(),location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(start);
markerOptions.title("Current Location");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
mCurrLocationMarker = mMap.addMarker(markerOptions);
}
In order to use the clicked points ArrayList as you have it now, you'll need to remove the previous origin, then add the current origin to the start of the ArrayList, and then get re-calculated directions based on the new current location.
Something like this:
#Override
public void onLocationChanged(Location location) {
mLastLocation = location;
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
/** Setting current location marker */
start = new LatLng(location.getLatitude(),location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(start);
markerOptions.title("Current Location");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
mCurrLocationMarker = mMap.addMarker(markerOptions);
//If there is a previous route drawn:
if (mClickedPoints.size() >= 2) {
//remove the old origin:
mClickedPoints.remove(0);
//add the new one at the 0th position:
mClickedPoints.add(0, start);
//set orig and dest for directions:
orig = mClickedPoints.get(0);
dest = mClickedPoints.get(1);
//get updated directions:
request_directions_and_get_response();
}
}
I've got a Google Map with Polygons, I've got everything to work except this last part which is detect if a Marker is already inside a Polygon.The current situation is when I touch a Polygon it will add the Marker"which is correct" but if I touch the Polygon in a different spot it will remove the Marker and add a new one. What I want to happen is if a Marker is already within those points don't add a new one. My code is below any help would be appreciate.
public void onMapClick(LatLng point) {
for (int j = 0; j < arrPolygons.size(); j++) {
if (isPointInPolygon(point, arrPolygons.get(j).getPoints())) {
if (marker != null) {
marker.remove();
marker = null;
Log.v("Marker", "Removing Marker");
}else{
marker = googleMap.addMarker(new MarkerOptions()
.position(point)
.title("test")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
Log.v("Marker", "ADDing Marker");
}
}
}
Any help would be appreciated.
The easiest way to do this would be using the Google Maps Android API Utility Library, which contains the PolyUtil class.
First import the library by adding the current version to your build.gradle, currently 0.3.4
for example:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.1.1'
compile 'com.google.android.gms:play-services-maps:7.3.0'
compile 'com.google.maps.android:android-maps-utils:0.3.4'
}
For this simple example we'll assume the Map Activity class definition and member variables look like this, and only one Polygon defined in polygonList:
import com.google.maps.android.PolyUtil;
//other imports.....
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mMap;
private Marker marker;
List<LatLng> polygonList = new ArrayList<LatLng>();
//.............
You would then set up your GoogleMap.OnMapClickListener like this in order to only add one Marker inside the Polygon.:
mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng point) {
if (PolyUtil.containsLocation(point, polygonList, false)) {
if (marker == null) {
//only add Marker if there is not one already inside the Polygon
marker = mMap.addMarker(new MarkerOptions()
.position(point)
.title("test")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
Log.v("Marker", "ADDing Marker");
}
}
}
});
Multiple Polygons, Multiple Markers Solution:
In order to make it work with multiple Ploygons, you could use a POJO to store Polygon/Marker pairs:
public class PolyMarkerObject{
Polygon polygon;
Marker marker;
}
Then define a new member variable polyMarkerList:
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mMap;
List<PolyMarkerObject> polyMarkerList = new ArrayList<>();
//.............
Add each Polygon to the list when drawing it:
List<LatLng> newPolygon = new ArrayList<>();
//set up the points in the Polygon.......
Polygon p = mMap.addPolygon(new PolygonOptions()
.addAll(newPolygon)
.strokeColor(Color.RED)
.fillColor(Color.BLUE));
PolyMarkerObject newPolyMarkerObj = new PolyMarkerObject();
newPolyMarkerObj.polygon = p;
polyMarkerList.add(newPolyMarkerObj);
Then cycle through the list on each Map click to see whether the current Ploygon already has a Marker. If it does not have a Marker already, then remove any Marker already placed in a different Polygon, and create one in the current Polygon:
mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng point) {
for (PolyMarkerObject pmObj : polyMarkerList) {
//only add Marker if there is not one already inside the Polygon
if (PolyUtil.containsLocation(point, pmObj.polygon.getPoints(), false)) {
if (pmObj.marker == null) {
//Add Marker to current Polygon
Marker newMarker = mMap.addMarker(new MarkerOptions()
.position(point)
.title("test")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
pmObj.marker = newMarker;
Log.v("Marker", "ADDing Marker");
break;
}
}
}
}
});
Multiple Polygons, One Marker Solution:
In this case, you just need one Marker reference, and a list of Polygons:
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mMap;
Marker marker;
List<Polygon> polyList = new ArrayList<>();
//................
Add the Polygon to the list when it's added to the Map:
List<LatLng> newPolygon = new ArrayList<>();
//set up the points in the Polygon.......
Polygon p = mMap.addPolygon(new PolygonOptions()
.addAll(newPolygon)
.strokeColor(Color.RED)
.fillColor(Color.BLUE));
polyList.add(p);
Then, in the Map click listener, you have two cases, one for if the Marker reference is null (no Marker added yet), and one for if the Marker is in a different Polygon. If the Marker is in the current Polygon already, it will not be moved.
mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng point) {
for (Polygon pObj : polyList) {
//find Polygon user tapped inside of
if (PolyUtil.containsLocation(point, pObj.getPoints(), false)) {
//first case, no Marker
if (marker == null) {
//Add Marker to current Polygon
marker = mMap.addMarker(new MarkerOptions()
.position(point)
.title("test")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
Log.v("Marker", "ADDing first Marker");
break;
}
else if (!PolyUtil.containsLocation(marker.getPosition(), pObj.getPoints(), false)) {
//Marker exists already in a different Polygon
//remove Marker from previous Polygon
marker.remove();
//Add Marker to current Polygon
marker = mMap.addMarker(new MarkerOptions()
.position(point)
.title("test")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
Log.v("Marker", "Moving Marker to new Polygon");
break;
}
}
}
}
});
I'm creating a map of some cities in Sweden and would like some functionality added to it. I would like to display the city name and the distance in kilometers of the city closest to the center of the map, where I have placed a crosshairs through an ImageView in my layout XML file. Is there a proper way of accomplishing this?
This is the code I'm currently using to create my map and place my city markers:
public class MyMap extends Activity implements OnMapReadyCallback
{
public final Context context = this;
private String fileString = "";
private String coordsFileName = "coords";
private GoogleMap myMap = null;
private LatLngBounds bounds = null;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_map);
// Gets the map fragment from the xml file
MapFragment mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
// Load strings from file
fileString = ReadFromFile(coordsFileName);
}
#Override
public void onMapReady(GoogleMap map)
{
myMap = map;
List<Marker> markers = new ArrayList<Marker>();
String[] locations = fileString.split(";");
for (String location : locations)
{
try
{
String[] cityLatLng = location.split(":|,");
String cityName = cityLatLng[0];
Double lat = Double.parseDouble(cityLatLng[1]);
Double lng = Double.parseDouble(cityLatLng[2]);
LatLng cityPos = new LatLng(lat, lng);
// Create marker
Marker marker = myMap.addMarker(new MarkerOptions()
.position(cityPos)
.title(cityName));
// Add new marker to array of markers
markers.add(marker);
}
catch(Exception e)
{
System.out.println("Error 3: " + e.getMessage());
}
}
// Move the camera to show all markers
LatLngBounds.Builder builder = new LatLngBounds.Builder();
for (Marker marker : markers)
{
builder.include(marker.getPosition());
}
bounds = builder.build();
myMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback()
{
#Override
public void onMapLoaded()
{
// Pixel offset from edge of map
int padding = 30;
// Move the camera
myMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, padding));
}
});
}
}
And this is my layout xml file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<fragment
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.google.android.gms.maps.MapFragment"/>
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_action_locate"
android:layout_gravity="center_vertical"
android:layout_centerInParent="true"
android:contentDescription="#string/crosshairs"/>
</RelativeLayout>
One of the probable solution is to first find the center coordinates of the map by using
map.getCenter();
This will return the latlang object. Then you can compare the distance of the center with each of the position markers (that represents cities) using the Google Distance Matrix API, find out the min by using a minDist() method and return the coordinates of marker at minimum distance (which is the name of the city)
Hope that would help!!!
I actually managed to solve it using Location objects and GoogleMap.setOnCameraChangeListener() to recalculate each time the user navigates the map. Below is the code I managed to put together to achieve this.
myMap.setOnCameraChangeListener(new OnCameraChangeListener()
{
#SuppressLint("DefaultLocale") #Override
public void onCameraChange(CameraPosition position)
{
// Get the latlng of the map center
LatLng mapCenter = myMap.getCameraPosition().target;
// Create a centerlocation based on the map's latlng
Location centerLocation = new Location("CenterLocation");
centerLocation.setLatitude(mapCenter.latitude);
centerLocation.setLongitude(mapCenter.longitude);
// Location for storage of the city closest to the map
Location closestCity = new Location("ClosestCity");
float distance = 0;
for (City city : cities)
{
Location cityLocation = new Location(city.getCityName());
cityLocation.setLatitude(city.getLatitude());
cityLocation.setLongitude(city.getLongitude());
float currentCityDistance = cityLocation.distanceTo(centerLocation);
if(distance == 0)
{
distance = currentCityDistance;
closestCity = cityLocation;
}
if(currentCityDistance < distance)
{
distance = currentCityDistance;
closestCity = cityLocation;
}
}
// Convert from meters to kilometers
float distanceKm = distance / 1000;
String kilometersString = String.format("%.2f", distanceKm);
// Present a toast with information
Toast.makeText(getBaseContext(), "Distance to " + closestCity.getProvider() + ": " + kilometersString + " km", Toast.LENGTH_SHORT).show();
}
});