After trying all the previous answers on StackOverflow I am posting this answer.
I am showing live location of a driver and a path from that location to a specific destination. What i want is to remove the old polyline soon the live location of driver changes but it's not hapening and it's increasing number of polylines.
Here is the code where i am removing the polyline but it's not working.
private void drawRouteOnMap(GoogleMap map, List<LatLng> positions) {
PolylineOptions options = new PolylineOptions().width(12).color(Color.GREEN).geodesic(true);
options.addAll(positions);
if (polyline != null) {
polyline.remove();
Log.e("Old Poly", "Removed");
}
Log.e("Poly", "Added");
polyline = mMap.addPolyline(options);
}
Try like this.
// decleare it globally
List<Polyline> polylines = new ArrayList<Polyline>();
private void drawRouteOnMap(GoogleMap map, List<LatLng> positions) {
PolylineOptions options = new PolylineOptions().width(12).color(Color.GREEN).geodesic(true);
for(Polyline polyline: polylines){
polyline.remove();
}
polylines.clear();
for(LatLng latlng: positions){
options.add(latlng);
polylines.add(mMap.addPolyline(options);
}
}
I have solved it myself. It is because that function was being called from another call due to which polyline instance was null. Solved it by saving polyline in SharedPrefrence and retrieving that value again on next call.
Related
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.
i am creating a user tracker project , and what i want to do is to draw the user path on the map , the method that i used it's Polyline and this is the code
public void drawOnMap(ArrayList<LatLng> directionPoints) {
PolylineOptions rectLine = new PolylineOptions().width(5).color(Color.GREEN).geodesic(false);
rectLine.addAll(directionPoints);
mMap.addPolyline(rectLine);
}
but after about 500 polyline the map going to laggy and after 1900 the app crash
so is there is better solution
i found a solution and this is the right code
private Polyline polyline;
public void drawOnMap(ArrayList<LatLng> directionPoints) {
if(polyline == null)
{
PolylineOptions rectLine = new PolylineOptions().width(5).color(Color.GREEN).geodesic(false);
rectLine.addAll(directionPoints);
polyline = mMap.addPolyline(rectLine);
}else{
polyline.setPoints(directionPoints);
}
}
I'm trying to draw a polyline from what the Google Directions Api returns, the api has this field, overview_polyline, I'm assuming that this field contains the entire polyline so I was thinking why not draw the polyline from there, this is what I have in my JSON, from Google:
{
geocoded_waypoints: [
{},
{}
],
routes: [
{
bounds: {},
copyrights: "Dados do mapa ©2017 Google, Inst. Geogr. Nacional",
legs: [],
overview_polyline: {
points: "cxwnFtdct#dAQlAf#fAf#|Aq#l#]pCcFhCjA|LfJlAT~#IpDi#jAb#f#HXi#t#kBhBeBx#Qz#z#dClHzFpW`H|RvTpj#`AxAdBdAnAXhB?fBk#rAcAnG_HhCgAjAKrATbA`Al#lBHnAc#rFgBhIkCxMBfIlBvHnBtCnB|AnEdCrJxFj#fB#h#OhAgCtHGfCl#jAlA\jE]tDBzBb#tLxFtK~E`d#hShIzEtDhDxDrEfDpFlFjNvDtRdDjThF`TzH`QhEhG|EvFhL`JpJtE|LpEdOpFjOzGlPfJlHzE~NjLfQvPfP|RtHrKxDjGfI|NdHbOvGjPfCbHpCtIvJh_#vG|[|CtNvFvSvE~MfI|QzLbTfNxQbKlKrRzP|NnNvNlQjIzMnLfV`T|h#nDbHhIdMxFjH~JrMnEfHzIrQfHvOtEjI|MnQfNzP`FzI~EnLrKp[nDlHvErHzL~MbRbM`EjCjFxEtRnX|D~EjIhI~WrRxGlGdFnG`JjNxHzKfTxVfKfRfMbRlErHtBlFxIjYvHnPpBtFxF~WpCjHjGhJfDzClF~CnDlArDl#pC\vHXvX[lOaB|GcBdFqBxQwJbDmAxE_ApJ_#jEXtItBrQ~EbQbDlUfBpMfA|IxCbF`DhGlGnJjKtJrF`SpFbRnDdUxAbGrAlEjBnFpDtNnMfGlE~[lTbRdQjTpUxH`GjHfEnGlC`O|DrUxEnEzAfFrBnSpIjPnDxSlAf\lAl~#hDzRrAjOpBvKrBrQtEv^pM``#rPrR|JxSdMlGnGfGtH~HxFdFlBtGfApGp#bG|AnHxD|FzFrH`L~FvH|HrFrFtBtFjA~Mt#pHR|FhA`IfDpEbDzFxGrHrKhEtErF`EnS`MzMvItSdUfF~DtE~B|SrInEnBzDtCxN`QpQfVtQ~Yjn#~fAnK`RvLlRzEjF|GlFrc#vUfRjKfIvGxDhEjIxKdN~T`L~MrFvE~LhIlp#fb#xCtBzFtFbEzFbDrGhH`TfF|JnGfHzEdD|UdIpTdHtKtFj]nUrEzC~[pTfLfG|EbB~KfCnTvDpmAxSzs#~LhOfDzOdFfOxGdY`O`k#zYnVzMlK|HrFjFbXj[rCbCvDfB|FfBbD^xRBlb#nBrIdArJvDfD|B|FzFvFzHnCbIDrCk#dA_A_#q#mHz#sAvAJ^f#r#n#x#UR_#fBGjET`S~#ro#pCpXpAfFp#dEhCnGtE#HXl#n#H^W|ASpShAbZxAtPp#~SjAzGZKdDStBd#x#dC#nEVz#HtAp#b#\OZ|AbBxDnFJf#"
},
summary: "A1",
warnings: [ ],
waypoint_order: [ ]
}
],
status: "OK"
}
How do I draw with that value?
This help me,you can use it..
Firstly create a google server key from google developer account
GoogleDirection.withServerKey(getResources().getString(R.string.SERVER_KEY))
.from(SourceLatlng)
.to(DestinationLatlng)
.execute(new DirectionCallback() {
#Override
public void onDirectionSuccess(Direction direction, String message) {
if (direction.isOK()) {
routeSucess2(direction, message,SourceLatlng,DestinationLatlng);
} else {
//selectedRawLine = ERROR;
}
}
#Override
public void onDirectionFailure(Throwable t) {
t.printStackTrace();
}
});
then draw a route using google direction
private void routeSucess2(Direction direction, String message,LatLng sourceLatlng,LatLng DestinationLng) {
for (Route route : direction.getRouteList()) {
PolylineOptions polyoptions = new PolylineOptions();
polyoptions.color(getResources().getColor(R.color.primary__dark));
polyoptions.width(5);
polyoptions.addAll(route.getOverviewPolyline().getPointList());
poly = googleMap.addPolyline(polyoptions);
poly.setClickable(true);
}
LatLngBounds.Builder latLngBuilder = new LatLngBounds.Builder();
if(sourceLatlng!=null)
latLngBuilder.include(sourceLatlng);
if(DestinationLng!=null)
latLngBuilder.include(DestinationLng);
try {
LatLngBounds bounds = latLngBuilder.build();
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds,
UiHelper.dpToPixel(getActivity(), 135));
googleMap.animateCamera(cu);
} catch (Exception e) {
e.printStackTrace();
}
}
This would help you.
#alb First you should parse lat,long from JSON. You can see this link:
https://developers.google.com/maps/documentation/directions/
Then you have to get lat, long values & put them in List<>.
After that you can use below code for draw polyline on map:
PolylineOptions options = new PolylineOptions().width(5).color(Color.BLUE).geodesic(true);
for (int z = 0; z < list.size(); z++) {
LatLng point = list.get(z);
options.add(point);
}
line = myMap.addPolyline(options);
I already have replied on similar question on below link
How to buffer a polyline in Android or draw a polygon around a polyline?
It will resolve your Issue probably
The polyline which we will draw on the map is not similar to the polyline of google's map application.It is giving a nice 3d feel,can we draw the polyline similar to that polyline?.Is it possible to draw using 9-patch images?.Anyone please help?.
Hello this would help you, it helped me.
Firstly make the google api server key from Google developer account then add a dependency for google direction.
compile 'com.akexorcist:googledirectionlibrary:1.0.4'
then it check that feasible and shortest route between LatLongs.
use this code to check route is available or not.
GoogleDirection.withServerKey(getResources().getString(R.string.SERVER_KEY))
.from(SourceLatlng)
.to(DestinationLatlng)
.execute(new DirectionCallback() {
#Override
public void onDirectionSuccess(Direction direction, String message) {
if (direction.isOK()) {
DrawRoute(direction, message,SourceLatlng,DestinationLatlng);
} else {
//selectedRawLine = ERROR;
}
}
#Override
public void onDirectionFailure(Throwable t) {
t.printStackTrace();
}
});
Using this we can find that route is feasible or not
private void DrawRoute(Direction direction, String message,LatLng sourceLatlng,LatLng DestinationLng) {
for (Route route : direction.getRouteList()) {
PolylineOptions polyoptions = new PolylineOptions();
polyoptions.color(getResources().getColor(R.color.blackcolor));
polyoptions.width(5);
polyoptions.addAll(route.getOverviewPolyline().getPointList());
poly = googleMap.addPolyline(polyoptions);
poly.setClickable(true);
}
LatLngBounds.Builder latLngBuilder = new LatLngBounds.Builder();
if(sourceLatlng!=null)
latLngBuilder.include(sourceLatlng);
if(DestinationLng!=null)
latLngBuilder.include(DestinationLng);
try {
LatLngBounds bounds = latLngBuilder.build();
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds,
UiHelper.dpToPixel(getActivity(), 135));
googleMap.animateCamera(cu);
} catch (Exception e) {
e.printStackTrace();
}
}
Using this code we make polyline between two latLongs ...
I am building an android app in which i have to do tracking of a user from one date/time to another and deploy makers using polylines one by one?
In response from a server i am receiving multiple lat/langs in a list. Now i want to deploy them one by one like a video is being played i know how to add markers i just want to control there deployment.E.g Marker A is deployed after 2 secs marker B should be deployed and joining with marker A with a poly-line and so do markers C,D. etc. How should i be able to achieve that. Timer, Threads? Any help or references,algos, would be great although i have searched such examples i couldn't find it yet.
Thanks in advance
You can use Handler to perform this task.
I am posting an example for you, I have not run it but I hope It will run successfully:
private final Handler mHandler = new Handler(Looper.getMainLooper());
private List<LatLng> mLatLngs;
private PutMarkerRunnable mRunnable;
private int mNoOfMarkersPlaced = -1;
private void showMarkers(List<LatLng> latLngs) {
mLatLngs = latLngs;
mHandler.post(mRunnable);
}
private class PutMarkerRunnable implements Runnable {
#Override
public void run() {
// write code to add marker
map.addMarker();
mNoOfMarkersPlaced++;
if (mNoOfMarkersPlaced != mLatLngs.size()) {
// scheduling next marker to be placed after 3 seconds
mHandler.postDelayed(mRunnable, 3000);
}
}
}
Ok thanks community.. But i have been finally able to do this through. Mark it correct because this really worked for me!
First we animate our camera using..
CameraPosition cameraPosition =
new CameraPosition.Builder()
.target(new LatLng(0,0))
.bearing(45)
.tilt(90)
.zoom(googleMap.getCameraPosition().zoom)
.build();
googleMap.animateCamera(
CameraUpdateFactory.newCameraPosition(cameraPosition),
ANIMATE_SPEEED_TURN,
new CancelableCallback() {
#Override
public void onFinish() {
}
#Override
public void onCancel() {
}
}
);/**
*
* Callback that highlights the current marker and keeps animating to the next marker, providing a "next marker" is still available.
* If we've reached the end-marker the animation stops.
*
*/
CancelableCallback simpleAnimationCancelableCallback =
new CancelableCallback(){
#Override
public void onCancel() {
}
#Override
public void onFinish() {
if(++currentPt < markers.size()){
CameraPosition cameraPosition =
new CameraPosition.Builder()
.target(targetLatLng)
.tilt(currentPt<markers.size()-1 ? 90 : 0)
//.bearing((float)heading)
.zoom(googleMap.getCameraPosition().zoom)
.build();
googleMap.animateCamera(
CameraUpdateFactory.newCameraPosition(cameraPosition),
3000,
simpleAnimationCancelableCallback);
highLightMarker(currentPt);
}
}
};
A bearing can be calculated between 2 android.location.Location objects. As we’re working with com.google.android.gms.maps.model.LatLng objects here, we first need to convert them into Location objects.
private Location convertLatLngToLocation(LatLng latLng) {
Location location = new Location("someLoc");
location.setLatitude(latLng.latitude);
location.setLongitude(latLng.longitude);
return location;
}
Once we have 2 Location objects, we can calculate the bearing between the 2. This is what we need to put on the Camera when transitioning to the target (the endLocation).
private float bearingBetweenLatLngs(LatLng beginLatLng,LatLng endLatLng) {
Location beginLocation = convertLatLngToLocation(beginLatLng);
Location endLocation = convertLatLngToLocation(endLatLng);
return beginLocation.bearingTo(endLocation);
}
We’ll use that number to calculate the coordinates of the intermediate point. Once we have those coordinates, we set our tracking marker to that new position.
long elapsed = SystemClock.uptimeMillis() - start;
double t = interpolator.getInterpolation((float)elapsed/ANIMATE_SPEEED);
double lat = t * endLatLng.latitude + (1-t) * beginLatLng.latitude;
double lng = t * endLatLng.longitude + (1-t) * beginLatLng.longitude;
LatLng intermediatePosition = new LatLng(lat, lng);
trackingMarker.setPosition(intermediatePosition);
We’ll also update our polyline with the new marker position, creating a trailing effect on the polyline.
private void updatePolyLine(LatLng latLng) {
List<LatLng> points = polyLine.getPoints();
points.add(latLng);
polyLine.setPoints(points);
}