private void setCurrentLocationMarker(LatLng currLatLng) {
if (currLatLng == null) {
Toast.makeText(getActivity(), "Check Internet Connection", Toast.LENGTH_SHORT).show();
return;
}
mMap.moveCamera(CameraUpdateFactory.newLatLng(currLatLng));
mMap.animateCamera(CameraUpdateFactory.zoomBy(R.integer.camera_zoom_value));
setMarkerAtCentre(mMap.getCameraPosition().target);
}
private void setMarkerAtCentre(LatLng cameraCentre){
if(cameraCentre == null) return;
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(cameraCentre);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker());
markerOptions.title("Your Position");
sourceMarker = mMap.addMarker(markerOptions);
}
Above two are the functions for setting the marker to desired latitude and longitude and placing the camera focusing the location.
Everything is working fine.
But the problem which I face here is with the zoom
mMap.animateCamera(CameraUpdateFactory.zoomBy(R.integer.camera_zoom_value));
I may place any value for the zoom.
<integer name="camera_zoom_value">2</integer>
But the zoom which I get always is the maximum one i.e. the largest possible zoom, which is kinda issue here.
Can anyone help me out? Thanks in advance.
your are passing the resource integer directly without using getResources().getInteger() so the value passed is some long integer > 20 leading to maximum zoom. Fix that and it will work.
Related
This is how i calculate the Distance between my list.
my code is below
public void calc(){
for(int i = 0; i < mSearchResultModelsToGetAppointments.size(); i++){
Location newLocation = new Location("");
newLocation.setLatitude(gpsTracker.getLatitude());
newLocation.setLongitude(gpsTracker.getLongitude());
if(String.valueOf(gpsTracker.getLatitude()).equalsIgnoreCase("0.0") || String.valueOf(gpsTracker.getLongitude()).equalsIgnoreCase("0.0")) {
} else{
Location oldLocation = new Location("");
oldLocation.setLatitude(mSearchResultModelUnderProcess.getLatitude());
oldLocation.setLongitude(mSearchResultModelUnderProcess.getLongitude());
float distanceInMeters = newLocation.distanceTo(oldLocation)/1000;
if(distanceInMeters < 2820){
getAdapter().notifyDataSetChanged();
getAdapter().removeItem(i);
getAdapter().notifyDataSetChanged();
}
}
}
}
This is how i display the location now.
If you do not want use any external library, I would suggest following way.
Create your own custom Location Class with attributes lat and lng, and additionally attribute called distance which measures from your current location till the point. here you can find how to find distance between 2 points
This class should implement Comparable interface and override its compare function. Inside this function, you can create your own sorting logic based on distance
here you can find how to use comparable interface, Let me know if you have still problem
Happy coding
In the map below I have three markers, the red one is the users current position while the green ones are the clickable markers.
Clicking the bottom one is not a problem. But clicking the one the user is close to is a different matter as the position marker is in the way. So for that one the user usually has to click 2 - 8 times before the green one is touched.
Is there a way to define that some markers are not clickable so they dont trigger the onMarkerClickListener?
I am aware that I can change the z-index and put the position marker below but it wont be nice for the user if he can't see his own position when close to another marker.
Another solution can think of but dont like is to intercept the click for the user marker and then go through a list of the other markers and find possible matches and trigger a click myself. I'd prefer an existing solution.
So what I have ended up doing is adding the object the marker represents to its tag. Then in onMarkerClickListener I check the marker type by the tag object. Like so (kotlin):
map.setOnMarkerClickListener { marker ->
val mapEvent: MapEvent?
mapEvent =
if (marker.tag is MapEvent) {
marker.tag as MapEvent?
} else {
val clickedMarker = getClickedMarker(from = map)
if (clickedMarker != null)
clickedMarker.tag as MapEvent?
else
return#setOnMarkerClickListener false
}
markerClicked(this#MainActivity, mapEvent)
true
}
If the object is of type MapEvent I call markerClicked() if the clicked marker is not of type MapEvent I go through a list of all markers to see if the clicked marker is inside the radius of any of the MapEvent markers. If so I use that marker and call markerClicked().
This is how I sort through the list of markers:
fun getClickedMarker(from: GoogleMap): Marker? {
if (!::userMarker.isInitialized)
return null
var clickWidth = ContextCompat.getDrawable(App.context, R.drawable.ic_map_permanent)!!.intrinsicWidth
clickWidth += (clickWidth / 3)
val g0 = from.projection.fromScreenLocation(Point(0, 0))
val g1 = from.projection.fromScreenLocation(Point(clickWidth, clickWidth))
val latRadius = (g1.latitude - g0.latitude) / 2
val lonRadius = (g1.longitude - g0.longitude) / 2
return try {
eventMarkers.single {
it.position!!.latitude - latRadius > userMarker.position.latitude && // west
it.position!!.latitude + latRadius < userMarker.position.latitude && // east
it.position!!.longitude + lonRadius > userMarker.position.longitude && // north
it.position!!.longitude - lonRadius < userMarker.position.longitude // south
}
} catch (e: Exception) {
null
}
}
Please comment if anything is unclear. I hope this might help anyone else!
In my Android application i need to get the traveled road with car and i check it with google android directions API and GPS.
But the problem is that some times the GPS location is not precise and i can get an error of 10Km for some lecture and that means that in a total travel of 150km my "distance traveled" can be 250km and it's wrong!
Yesterday i test it in highway and the problem is that when the marker is located out from highway, the calculation of distance traveled from my current position and the last marker located by road is very wrong (in this case out of the highway).
There is some best way for getting traveled distance with car using the phone?
Maybe some better code for getting more precise GPS position?
Here is my code:
private void getUserLocation() {
Log.d(TAG, "getUserLocation()");
checkLocationPermission();
mFusedLocationClient.getLastLocation()
.addOnSuccessListener(getActivity(), new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
// Got last known location. In some rare situations this can be null.
if (location != null) {
// Logic to handle location object
String stringStartLat, stringStartLng;
double lat = location.getLatitude();
double lng = location.getLongitude();
//Start position of device
if (travelInfo.getStartLat() == 0 && travelInfo.getStartLng() == 0) {
travelInfo.setStartLat(lat);
travelInfo.setStartLng(lng);
//Set lastcoordinates equals to start
travelInfo.setLastLat(lat);
travelInfo.setLastLng(lng);
}
//Current position of device
travelInfo.setCurrentLat(lat);
travelInfo.setCurrentLng(lng);
stringStartLat = Double.toString(travelInfo.getStartLat());
stringStartLng = Double.toString(travelInfo.getStartLng());
//Set the TextView in the fragment with start coordinates
Log.d(TAG,"LatitudeStart: " + stringStartLat);
Log.d(TAG,"LongitudeStart: " + stringStartLng);
if (startMarker == null) {
//Add the user location to the map with a marker
LatLng userLoction = new LatLng(travelInfo.getStartLat(), travelInfo.getStartLng());
startMarker = googleMap.addMarker(new MarkerOptions()
.position(userLoction)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE))
.title("Start Position")
.snippet("Show the start position of user"));
// For zooming automatically to the location of the marker
CameraPosition cameraPosition = new CameraPosition.Builder().target(userLoction).zoom(9).build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
} else {
LatLng currentLocation = new LatLng(travelInfo.getCurrentLat(), travelInfo.getCurrentLng());
currentPositionMarker = googleMap.addMarker(new MarkerOptions()
.position(currentLocation)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_YELLOW))
.title("Current Position")
.snippet("Show the current position of user during travel"));
// For zooming automatically to the location of the marker
CameraPosition cameraPosition = new CameraPosition.Builder().target(currentLocation).zoom(11).build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}
if (travelInfo.getEndLat() != 0 && travelInfo.getEndLng() != 0) {
Log.i(TAG, "Dentro if userlocation");
//Get total distance of travel
getTotalDistanceTime(travelInfo);
//Get the percurred distance from last known coordinates
getPercurredDistance(travelInfo);
}
}
}
});
}
And getpercurredDistance use google direction API with this url
String url = "https://maps.googleapis.com/maps/api/directions/json?origin=" + obj.getLastLat() + "," + obj.getLastLng() + "&destination=" + obj.getCurrentLat() + "," + obj.getCurrentLng() + "&mode=driving&key=AI*******************I";
For getting distance traveled from last marker and current position marker.
But some times it put the localized position too far from real position... how avoid this?
EDIT
The method that i use is good for my work? mFusedLocationClient.getLastLocation()
There is no possibilities to get more precise GPS position from GPS sensor of android device, but you can filter "wrong" points this ways:
1) for each travel point get several values of Lat and Lng, discard the minimum and maximum and average the remaining ones;
2) log timestamps of each travel point and compare it for two neighboring points: speed (distance between that two points divided by time interval of that points) grater than max. car speed (e.g. 250 km/h) that means the second point is wrong (if first point is good of course).
3) use Google Maps Roads API to find best-fit road geometry for a given set of GPS coordinates.
Also take a look at this question.
For real-time location purposes, location updates allow you to request location updates at different intervals. See the android developer location documentation. The function you want is FusedLocationProviderClient.requestLocationUpdates.
There is no reason GPS (or any other widely used location technology) should ever give you 10km error for a single location estimate. If you are getting this, there is a large mismatch between when you the location estimate was made and when you are requesting it.
Im getting list of planes from web api with their locations and infos. Im calling this web api every few seconds and drawing the map markers (planes) to map.
When I call my method addPlanesToMap(), to add/update markers on map, map freezes for short period of time. If im movin the map at the same time the markers get added/updated there is some lag. This happens in devices like Nexus 5. There is around 200 - 300 markers in map.
Is there something how I can improve my code, do something completely differently?
HashMap<String, MarkerContainer> mMarkerHashMap = new HashMap <String, MarkerContainer>();
public void addPlanesToMap(List <? extends RealtimePlane > planes) {
View planeMarkerView = getActivity().getLayoutInflater().inflate(R.layout.map_marker_plane, null);
TextView markerShortCodeText = (TextView) planeMarkerView.findViewById(R.id.MapMarkerText);
ImageView markerArrow = (ImageView) planeMarkerView.findViewById(R.id.MapMarkerArrow);
for (RealtimePlane plane: planes) {
MarkerContainer markerContainer = mMarkerHashMap.get(plane.getPlaneId());
// Do not process, if not updated
if (markerContainer != null && markerContainer.getPlane().getRecordedAtTime().equals(plane.getRecordedAtTime())) {
continue;
}
markerShortCodeText.setText(plane.getPlaneCode());
markerShortCodeText.setBackgroundResource(getMapMarkerDrawableBg(plane.getType()));
markerArrow.setRotation((float) plane.getBearing());
markerArrow.setVisibility(View.VISIBLE);
// Add new plane marker to map
if (markerContainer == null) {
Marker m = mMap.addMarker(new MarkerOptions()
.position(plane.getLocation())
.flat(true)
.anchor(0.5f, 0.5f)
.title(plane.getLineCode())
.icon(BitmapDescriptorFactory.fromBitmap(loadBitmapFromView(getActivity(), planeMarkerView))));
mMarkerHashMap.put(plane.getPlaneId(), new MarkerContainer(m, plane));
}
// Marker already set, update
else {
markerContainer.getMarker().setIcon(BitmapDescriptorFactory.fromBitmap(loadBitmapFromView(getActivity(), planeMarkerView)));
markerContainer.getMarker().setPosition(plane.getLocation());
markerContainer.setPlane(plane);
}
}
}
Is there something how I can improve my code, do something completely differently
yes, do not plot every single marker and only plot what is in the visible area. you can also do marker clustering.
Plotting 2-300 markers every few seconds is not really a good idea to begin with
Trying to routing via osmbonus pack here, everything works almost fine, but there is a problem which is I can not see the polyline drawn as the route on my map.
I'm sure it has een generated since (mRoadOverlay.getNumberOfPoints()) returns 41
And I'm following the OSMNavigator Sample https://code.google.com/p/osmbonuspack/source/browse/trunk/OSMNavigator/src/com/osmnavigator/MapActivity.java
void updateUIWithRoad(Road road){
mRoadNodeMarkers.getItems().clear();
TextView textView = (TextView)findViewById(R.id.tv_main_routeInfo);
textView.setText("");
List<Overlay> mapOverlays = map.getOverlays();
if (mRoadOverlay != null){
Log.d("Polylinenopoin",String.valueOf(mRoadOverlay.getNumberOfPoints()));
mapOverlays.remove(mRoadOverlay);
mRoadOverlay = null;
Log.d("POLYLINE","1");
}
if (road == null){
return;}
if (road.mStatus == Road.STATUS_TECHNICAL_ISSUE)
Toast.makeText(map.getContext(), "Technical issue when getting the route", Toast.LENGTH_SHORT).show();
else if (road.mStatus > Road.STATUS_TECHNICAL_ISSUE) //functional issues
Toast.makeText(map.getContext(), "No possible route here", Toast.LENGTH_SHORT).show();
mRoadOverlay = RoadManager.buildRoadOverlay(road, Main.this);
String routeDesc = road.getLengthDurationText(-1);
mRoadOverlay.setTitle("route" + " - " + routeDesc);
String det = String.valueOf(mRoadOverlay.getColor()) + "- " + String.valueOf(mRoadOverlay.getWidth());
Log.d("Polydet",det);
map.getOverlays().add(mRoadOverlay);
//we insert the road overlay at the "bottom", just above the MapEventsOverlay,
//to avoid covering the other overlays.
putRoadNodes(road);
map.invalidate();
//Set route info in the text view:
textView.setText(routeDesc);
}
Also I need to say that I can see road Nodes on the map, so it's safe to say that road is correct
For future reference:
I found the reason,
the reason was that to enlarge the font size of the maps I used this custom XYTileSource:
map.setTileSource(new XYTileSource("Google Terrian",
ResourceProxy.string.bing, 10, 17, 512, ".jpg", new String[] {
"http://otile1.mqcdn.com/tiles/1.0.0/map/",
"http://otile2.mqcdn.com/tiles/1.0.0/map/",
"http://otile3.mqcdn.com/tiles/1.0.0/map/",
"http://otile4.mqcdn.com/tiles/1.0.0/map/"}));
in which I had changed the aTileSizePixel to 512, while my tiles were in fact 256x256 ... this helped me to show tiles bigger and hence bigger font size, the latitude and longitude were alright as I could set points by myself on the map in exact location, also the route Nodes were alright, the route Polyline itself however was not, I guess it had been loaded in a different location which was not in the view I had checked.