I am using Mapbox (4.2.1) to draw a line from my position to a target position. I have the intention of using the straight line as an extremely basic navigation aid. As such I am re-drawing the guide line OnMyLocationChanged(). However it appears that as my location changes it will draw the line to my new location but MyLocationView (User icon) does not update in accordance (See image below).
They will eventually end up meeting again but it takes some time. It seems that the line is getting drawn inside the accuracy radius, however I would prefer if it could draw the line straight from the user icon.
Is there a simple way to draw a line between the user (The actual icon on the map) and a location which updates as the user moves?
My OnMyLocationChanged is:
MapboxMap.OnMyLocationChangeListener listner = new MapboxMap.OnMyLocationChangeListener(){
#Override
public void onMyLocationChange(final #Nullable Location locationChanged) {
//If we are not targeting anything or we are not tracking location
if(target == null || !map.isMyLocationEnabled()) return;
mapView.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(MapboxMap mapboxMap) {
//Log.i("LOC-MAPLINE", "Drawing from mapLoc call");
//Error if we don't have a location
if(!mapboxMap.isMyLocationEnabled() || locationChanged == null) return;
LatLng[] points = new LatLng[2];
final Location myLoc = locationChanged;
LatLng loc = new LatLng(myLoc.getLatitude(), myLoc.getLongitude());
LatLng dest = new LatLng(target.getLatitude(), target.getLongitude());
points[0] = loc;
points[1] = dest;
mapboxMap.removeAnnotations();
loadMarker(target);
PolylineOptions poly = new PolylineOptions()
.add(points)
.color(Color.parseColor("#3887be"))
.width(5);
line = mapboxMap.addPolyline(poly);
}
});
}
};
Any assistance is greatly appreciated, thank you!
EDIT (In regards to possible duplicate question - Google direction route from current location to known location)
I believe my question is different for a few reasons.
I am more concerned on getting the location of the user icon overlay rather than actual location (Accuracy issue)
I am not interested in getting turn for turn directions (Like those from a directions API)
I am using Mapbox rather than google maps (Not too sure but there could be some differences).
Nevertheless that question does not seem to answer my question
According to documentation you need only implement this method passing your currentLocation (origin) and destination
private void getRoute(Position origin, Position destination) throws ServicesException {
MapboxDirections client = new MapboxDirections.Builder()
.setOrigin(origin)
.setDestination(destination)
.setProfile(DirectionsCriteria.PROFILE_CYCLING)
.setAccessToken(MapboxAccountManager.getInstance().getAccessToken())
.build();
client.enqueueCall(new Callback<DirectionsResponse>() {
#Override
public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
// You can get the generic HTTP info about the response
Log.d(TAG, "Response code: " + response.code());
if (response.body() == null) {
Log.e(TAG, "No routes found, make sure you set the right user and access token.");
return;
} else if (response.body().getRoutes().size() < 1) {
Log.e(TAG, "No routes found");
return;
}
// Print some info about the route
currentRoute = response.body().getRoutes().get(0);
Log.d(TAG, "Distance: " + currentRoute.getDistance());
Toast.makeText(
DirectionsActivity.this,
"Route is " + currentRoute.getDistance() + " meters long.",
Toast.LENGTH_SHORT).show();
// Draw the route on the map
drawRoute(currentRoute);
}
#Override
public void onFailure(Call<DirectionsResponse> call, Throwable throwable) {
Log.e(TAG, "Error: " + throwable.getMessage());
Toast.makeText(DirectionsActivity.this, "Error: " + throwable.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
private void drawRoute(DirectionsRoute route) {
// Convert LineString coordinates into LatLng[]
LineString lineString = LineString.fromPolyline(route.getGeometry(), Constants.OSRM_PRECISION_V5);
List<Position> coordinates = lineString.getCoordinates();
LatLng[] points = new LatLng[coordinates.size()];
for (int i = 0; i < coordinates.size(); i++) {
points[i] = new LatLng(
coordinates.get(i).getLatitude(),
coordinates.get(i).getLongitude());
}
// Draw Points on MapView
map.addPolyline(new PolylineOptions()
.add(points)
.color(Color.parseColor("#009688"))
.width(5));
}
reference https://www.mapbox.com/android-sdk/examples/directions/
Related
I am using Google Map, now I am showing a polyline b/w my current location to my destination by using Google Direction API with moving marker animation.
Now if I change my path while driving then how can I update that path from my current location to the destination.
Here is my code
#Override
public void onDirectionSuccess(Direction direction, String rawBody) {
if (direction.isOK()) {
route = direction.getRouteList().get(0);
ArrayList<LatLng> directionPositionList = route.getLegList().get(0).getDirectionPoint();
mMap.addPolyline(DirectionConverter.createPolyline(this, directionPositionList, 8, Color.BLUE));
} else {
Toast.makeText(DriversActivity.this, direction.getStatus(), Toast.LENGTH_SHORT).show();
}
Here in OnDirectionSuccess method, m getting the direction. I don't want to call it again and again because the previous line is also there with a new one.
Is anyone can help me out???
please first add this function to activity
private void route(AbstractRouting.TravelMode travelMode, final LatLng end) {
this.end = end;
DataShahrManager dataShahrManager = DataShahrManager.getInstance(activity);
if (dataShahrManager.getMyLocation() != null) {
start = new LatLng(dataShahrManager.getMyLocation().getLatitude(),
dataShahrManager.getMyLocation().getLongitude());
if (end != null) {
mapsFragment.getProgressBar().setVisibility(View.VISIBLE);
Routing routing = new Routing.Builder()
.travelMode(travelMode)
.withListener(this)
.alternativeRoutes(false)
.waypoints(start, end)
.language("fa")
.key("your key")
.build();
routing.execute();
}
} else {
mapsFragment.getLocationProgressBar().setVisibility(View.VISIBLE);
mapsFragment.startLocationFinding();
mapsFragment.setUpMyLocationUsingMap();
if (activity != null) {
Toast.makeText(activity, R.string.finding_your_location, Toast.LENGTH_SHORT).show();
}
mapsFragment.setOnLocationFoundListener(() -> route(AbstractRouting.TravelMode.DRIVING, end));
}
}
so add this line to button
route(AbstractRouting.TravelMode.DRIVING, businessEntity.getLatLng());
I am using Google Directions API to get routes between two locations with Way Points.
Currently what I am doing is getting direction details between two locations using Direction API and showing the result in Google Maps integrated inside my application. It works well as expected. This is how I did it:
private DirectionsResult getDirectionsDetails(String origin,String destination,TravelMode mode) {
Log.i("testtt"," Origin "+origin+" Destination "+destination);
DateTime now = new DateTime();
try {
return DirectionsApi.newRequest(getGeoContext())
.mode(mode)
.origin(origin)
.waypoints(waypoints.toArray(new String[0]))
.destination(destination)
.departureTime(now)
.await();
} catch (InterruptedException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
} catch (com.google.maps.errors.ApiException e) {
e.printStackTrace();
return null;
}
}
#Override
public void onMapReady(GoogleMap googleMap) {
setupGoogleMapScreenSettings(googleMap);
DirectionsResult results = getDirectionsDetails(origin,destination,TravelMode.DRIVING);
if (results != null) {
addPolyline(results, googleMap);
positionCamera(results.routes[overview], googleMap);
addMarkersToMap(results, googleMap);
}
}
private void setupGoogleMapScreenSettings(GoogleMap mMap) {
mMap.setBuildingsEnabled(true);
mMap.setIndoorEnabled(true);
mMap.setTrafficEnabled(true);
UiSettings mUiSettings = mMap.getUiSettings();
mUiSettings.setZoomControlsEnabled(true);
mUiSettings.setCompassEnabled(true);
mUiSettings.setMyLocationButtonEnabled(true);
mUiSettings.setScrollGesturesEnabled(true);
mUiSettings.setZoomGesturesEnabled(true);
mUiSettings.setTiltGesturesEnabled(true);
mUiSettings.setRotateGesturesEnabled(true);
}
private void addMarkersToMap(DirectionsResult results, GoogleMap mMap) {
mMap.addMarker(new MarkerOptions().position(new LatLng(results.routes[overview].legs[overview].startLocation.lat,results.routes[overview].legs[overview].startLocation.lng)).title(results.routes[overview].legs[overview].startAddress));
mMap.addMarker(new MarkerOptions().position(new LatLng(results.routes[overview].legs[overview].endLocation.lat,results.routes[overview].legs[overview].endLocation.lng)).title(results.routes[overview].legs[overview].endAddress).snippet(getEndLocationTitle(results)));
}
private void positionCamera(DirectionsRoute route, GoogleMap mMap) {
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(route.legs[overview].startLocation.lat, route.legs[overview].startLocation.lng), 12));
}
private void addPolyline(DirectionsResult results, GoogleMap mMap) {
List<LatLng> decodedPath = PolyUtil.decode(results.routes[overview].overviewPolyline.getEncodedPath());
mMap.addPolyline(new PolylineOptions().addAll(decodedPath));
}
But what I want is I want to load this direction result in the external Google Maps app. What I am asking is is there any way to pass the DirectionsResult object to Google Maps application via Intent so that it will show the routes in the app.
Reason why I want this is to avoid integrating Google Maps API to the project as it is not completely free anymore.
Pricing details
As I can see in your code, that you are not performing any calculations on the DirectionsDetails given by DirectionsApi you can open the pass your location coordinates in google maps.
By default, Google maps always loads the best available route according to current traffic and time:
String geoUri = "http://maps.google.com/maps?q=loc:" + lat + "," + lng + " (" + mTitle + ")";
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(geoUri));
context.startActivity(intent);
If you want to add waypoints in between your source and destination you can have a look at this answer.
If you want, you can find the route through DirectionsApi and process the data for your internal analytics for eg. approx time to travel between his location and new location, distance etc.
while loading google map on device i am receiving below screen sometimes.it comes on second load as shown below. otherwise it comes perfectly as normal google map with route I am using SupportmapFragment and get googleMap object as.
supportMapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map_view_fragment);
below is code for displaying map in activity/fragment
public static void drawRouteIntoMap(final List<? extends MapHelper> position, final GoogleMap googleMap) {
/*List<MapHelper> position = new ArrayList<MapHelper>();
for (int i = lastPosition; i < maps.size(); i++) {
position.add(maps.get(i));
}*/
final LatLngBounds.Builder mapBounds = new LatLngBounds.Builder();
if (position.size() > 0 && Validator.isNotNull(googleMap)) {
googleMap.clear();
List<PolylineOptions> polylineOptionses = new ArrayList<PolylineOptions>();
PolylineOptions option = null;
Boolean lastPause = null;
for (MapHelper map : position) {
if (map.isPause()) {
if (Validator.isNull(lastPause) || !lastPause) {
option = new PolylineOptions().width(5).color(Color.rgb(255, 0, 155)).geodesic(true);
polylineOptionses.add(option);
}
mapBounds.include(new LatLng(map.getLatitude(),map.getLongitude()));
option.add(new LatLng(map.getLatitude(), map.getLongitude()));
} else {
if (Validator.isNull(lastPause) || lastPause) {
option = new PolylineOptions().width(5).color(Color.rgb(0, 179, 253)).geodesic(true);
polylineOptionses.add(option);
}
mapBounds.include(new LatLng(map.getLatitude(),map.getLongitude()));
option.add(new LatLng(map.getLatitude(), map.getLongitude()));
}
lastPause = map.isPause();
}
for (PolylineOptions options : polylineOptionses) {
googleMap.addPolyline(options);
}
if(Validator.isNotNull(option)){
//List<LatLng> points = option.getPoints();
googleMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
#Override
public void onMapLoaded() {
LatLng startPoint = new LatLng(position.get(0).getLatitude(), position.get(0).getLongitude());
googleMap.addMarker(new MarkerOptions().position(startPoint).title("start").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)));
mapBounds.include(startPoint);
LatLng endPoint = new LatLng(position.get(position.size() - 1).getLatitude(), position.get(position.size() - 1).getLongitude());
mapBounds.include(endPoint);
googleMap.addMarker(new MarkerOptions().position(endPoint).title("finish").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
googleMap.setPadding(15, 205, 10, 110);
googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(mapBounds.build(), 0));
//googleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(mapBounds.build(), 10));
googleMap.moveCamera(CameraUpdateFactory.zoomOut());
}
});
}
}
}
supportMapFragment.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap googleMap) {
if (Validator.isNotNull(googleMap)) {
googleMap.setMyLocationEnabled(false);
googleMap.clear();
googleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng latLng) {
if (activity.preferences.isSaveScreen()) {
facebook.setChecked(false);
twitter.setChecked(false);
activity.replaceFragment(new FullMapFragment(), null);
}
if (!activity.preferences.isSaveScreen()) {
activity.preferences.setHistoryScreen(true);
activity.replaceFragment(new FullMapFragment(), null);
}
}
});
if (gps) {
nonGpsSummary.setVisibility(View.GONE);
List<HistoryMap> historyMaps = new ArrayList<HistoryMap>();
if (Validator.isNotNull(activity.preferences.getUserHistory().getHistoryMaps())) {
historyMaps.addAll(Arrays.asList(activity.preferences.getUserHistory().getHistoryMaps()));
}
if (historyMaps.size() > 0) {
if (Validator.isNotNull(googleMap)) {
drawRouteIntoMap(historyMaps, googleMap);
}
} else {
mapFrame.setVisibility(View.GONE);
}
} else {
gpsSummary.setVisibility(View.GONE);
}
}
}
});
this question is in relation with zoom over specific route google map.
by using that i get proper route with mapbounds but i m not getting why this screen is displaying.
i am not receiving cordinates 0.0 i debug that,api key is also proper.
You are calling moveCamera twice. The first one tries to move the camera but the second one doesn't wait for the first one to end and performs the zoom out.
This may not happen all the times and may behave differently on different devices.
The best option is to set a padding on your CameraUpdateFactory.newLatLngBounds(mapBounds.build(), 0) instead of 0
This problem occurs when your coordinates are not properly set. Make sure the coordinates that you are using is pointing in the land to get the maps correctly. Another possible reason is your API key is not working, try to generate new API key for this project.
For more information, check these related SO questions.
Android google maps return error and blue screen
Blue screen in Android Google Maps
previously I use GmapV2 from Android: How to draw route directions google maps API V2 from current location to destination. But now it's not work I got error about that class. How to fix that class?
This code will draw the line from origin to destination.
#Override
public void onDirectionSuccess(Direction direction, String rawBody) {
Log.d("Status", "Success");
Log.d("Direction", "" + direction);
mMap.addMarker(new MarkerOptions().position(origin));
mMap.addMarker(new MarkerOptions().position(destination));
if (waypoints != null){
for (int i = 0; i < waypoints.size(); i++){
mMap.addMarker(new MarkerOptions().position(waypoints.get(i)));
}
}
ArrayList<LatLng> directionPositionList = direction.getRouteList().get(0).getLegList().get(0).getDirectionPoint();
mMap.addPolyline(DirectionConverter.createPolyline(this, directionPositionList, 5, Color.BLUE));
Log.d("Status", "Success 2");
showRoute.setVisibility(View.GONE);
}
I have a set of points in a text file that I want to plot on a map (API v2) and draw a line through. Each of the points is a <Lat, Lng> and there are a total of 7253 such points in the text file. The code is as follows:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_my_route_mock);
//Step 0. Get google map instance.
map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
if(map == null) {
Toast.makeText(getApplicationContext(), "Map is not available.", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "Map is available.", Toast.LENGTH_LONG).show();
}
//Step 0.a. Load a type of map.
map.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
//Step 0.b. Load your current location on the map.
map.setMyLocationEnabled(true);
if(po == null) {
po = new PolylineOptions();
}
//Toast.makeText(getApplicationContext(), "Location lat = " + loc.getLatitude() + " and longitude = " + loc.getLongitude(), Toast.LENGTH_LONG).show();
//Step 1. Set GPS to service provider.
locMgr = (LocationManager) getSystemService(LOCATION_SERVICE);
mocLocProvider = locMgr.GPS_PROVIDER;
locMgr.addTestProvider(mocLocProvider, false, false, true, false, true, false, false, 0, 5);
locMgr.setTestProviderEnabled(mocLocProvider, true);
//locMgr.requestLocationUpdates(mocLocProvider, 0, 0, locLstnr);
//Step 2. Open file for reading from.
try {
is = getAssets().open("locationLogs.txt");
br = new BufferedReader(new InputStreamReader(is));
String line = null;
try {
line = br.readLine();
while(line != null) {
//while((line = br.readLine()) != null) {
//there is still a line in the file. parse for gps coordinates etc.
Location l = new Location(LocationManager.GPS_PROVIDER);
String[] details = line.split(","); //the array will contain date, time, lat, long, speed, altitude and accuracy.
l.setTime(System.currentTimeMillis());
l.setLatitude(Double.parseDouble(details[2]));
l.setLongitude(Double.parseDouble(details[3]));
l.setSpeed((float) Double.parseDouble(details[4]));
l.setAltitude(Double.parseDouble(details[5]));
l.setAccuracy((float) Double.parseDouble(details[6]));
//Toast.makeText(getApplicationContext(), l.getLatitude() + "," + l.getLongitude() + "," + l.getSpeed() + "," + l.getAltitude() + "," + l.getAccuracy() + "\n", Toast.LENGTH_SHORT).show();
locMgr.setTestProviderLocation(mocLocProvider, l);
po.add(new LatLng(l.getLatitude(), l.getLongitude()));
Log.v(this.toString(), "Number of po objects = " + po.getPoints().size());
//pl = map.addPolyline(po);
//Log.v(this.toString(), "number of polyline objects added = " + pl.getPoints().size());
line = br.readLine();
}
} catch(FileNotFoundException e) {
Log.v(this.toString(), "File not found.");
}
} catch (IOException e) {
// TODO Auto-generated catch block
Log.v(this.toString(), "Cannot open file for reading from.");
}
}
After reading about 1300 points, the application collapses with an OutOfMemory exception. Though there are a whole host of threads dealing with memory leakage on Google Maps API v2, closer analysis with MAT reveals that the line: pl = map.addPolyline(po) is the culprit, hogging most of the memory. This turns out to be true, since after that line is commented out, the memory footprint of the above code is very small ~8MB for about 7k points read.
My question(s):
1. Is there anything wrong with the way Polylines object is being used to draw on the map? Once for every update?
2. If so, how can a line be drawn such that it does not take up too much memory? With Canvas and the like or drawing a line only after a certain number of points (say, 10 or so)?
3. Some developers who have used Maps API v2 in their application can maybe shed some light on the proper way to do this?
Call pl = map.addPolyline(po); after the loop to create one polyline and not to try to create 7000 polylines each one "one point longer" than the one before.