HereMaps api getdirections invalid operation error on android - android

I am trying to get directions between two point in heremaps. But in routeManagerListener, I get an error that is INVALID_OPERATION. please help.
This is my listener.
private RouteManager.Listener routeManagerListener = new RouteManager.Listener() {
#Override
public void onCalculateRouteFinished(RouteManager.Error error, List<RouteResult> list) {
if (error == RouteManager.Error.NONE &&
list.get(0).getRoute() != null) {
// create a map route object and place it on the map
mapRoute = new MapRoute(list.get(0).getRoute());
map.addMapObject(mapRoute);
// Get the bounding box containing the route and zoom in
GeoBoundingBox gbb = list.get(0).getRoute().getBoundingBox();
map.zoomTo(gbb, Map.Animation.NONE,
Map.MOVE_PRESERVE_ORIENTATION);
textViewResult.setText(
String.format("Route calculated with %d maneuvers.",
list.get(0).getRoute().getManeuvers().size()));
}else{
textViewResult.setText(
String.format("Route calculation failed: %s",
error.toString()));
}
}
#Override
public void onProgress(int i) {
textViewResult.setText(
String.format("... %d percent done ...", i));
}
};
and this is getDirections method.
public void getDirections(View view) {
// 1. clear previous results
textViewResult.setText("");
if (map != null && mapRoute != null) {
map.removeMapObject(mapRoute);
mapRoute = null;
}
// 2. Initialize RouteManager
RouteManager routeManager = new RouteManager();
// 3. Select routing options via RoutingMode
RoutePlan routePlan = new RoutePlan();
RouteOptions routeOptions = new RouteOptions();
routeOptions.setTransportMode(RouteOptions.TransportMode.CAR);
routeOptions.setRouteType(RouteOptions.Type.FASTEST);
routePlan.setRouteOptions(routeOptions);
// 4. Select Waypoints for your routes
// START: Nokia, Burnaby
routePlan.addWaypoint(new GeoCoordinate(49.1966286, -123.0053635));
// END: Airport, YVR
routePlan.addWaypoint(new GeoCoordinate(49.1947289, -123.1762924));
// 5. Retrieve Routing information via RouteManagerListener
RouteManager.Error error =
routeManager.calculateRoute(routePlan, routeManagerListener);
if (error != RouteManager.Error.NONE) {
Toast.makeText(getApplicationContext(),
"Route calculation failed with: " + error.toString(),
Toast.LENGTH_SHORT)
.show();
}
}
and how ı call this method:
bgetDirection.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getDirections(view);
}
});

Related

Wait for response from Retrofit 2 asynchronous call

in my Android inside an activity I have an asynchronous call to a google maps API inside a method see the code below :
public void reverseGeocode(String lat, String lng) {
String geocodeApiUrl = getUrl(lat, lng);
GoogleService googleService = GoogleServiceBuilder.buildService(GoogleService.class);
Call<Address> geocodeRequest = googleService.geocodeAddress(geocodeApiUrl);
geocodeRequest.enqueue(new Callback<Address>() {
#Override
public void onResponse(Call<Address> call, Response<Address> response) {
if (response.errorBody() == null) {
if (response.body().getResults().length > 0) {
if (response.body().getResults()[0].getFormatted_address() != null) {
dropOffAddress = response.body().getResults()[0].getFormatted_address();
}
}
} else {
Toast.makeText(AdressPicker.this, "An error has occured", Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<Address> call, Throwable t) {
Toast.makeText(AdressPicker.this, "An error has occured", Toast.LENGTH_LONG).show();
}
});
}
this method is called inside the Google map marker 's onMarkerDragEnd callback function , see code below :
#Override
public void onMarkerDragEnd(Marker marker) {
double lat = marker.getPosition().latitude;
double lng = marker.getPosition().longitude;
reverseGeocode(String.valueOf(lat), String.valueOf(lng));
marker.setSnippet(dropOffAddress);
marker.showInfoWindow();
editor.putString("dropOffAddress", dropOffAddress);
editor.putString("lat", String.valueOf(lat));
editor.putString("lng", String.valueOf(lng));
editor.apply();
}
The problem here is the first time when I move the marker the reverseGeocode method is called but it is not awaited and the onMarkerDragEnd continue its execution and puts null inside the value of the dropOffAddress variable which is intended to be displayed inside the snippet of the marker.
My question here is HOW to WAIT for the reverseGeocode method'is response inside onMarkerDragEnd before continuing executing ?
Thank you.
the only thing you. need is marker, just pass it as a parameter in your retrofit api call something like this.
public void reverseGeocode(String lat, String lng, Marker marker) {
String geocodeApiUrl = getUrl(lat, lng);
GoogleService googleService = GoogleServiceBuilder.buildService(GoogleService.class);
Call<Address> geocodeRequest = googleService.geocodeAddress(geocodeApiUrl);
geocodeRequest.enqueue(new Callback<Address>() {
#Override
public void onResponse(Call<Address> call, Response<Address> response) {
if (response.errorBody() == null) {
if (response.body().getResults().length > 0) {
if (response.body().getResults()[0].getFormatted_address() != null) {
dropOffAddress = response.body().getResults()[0].getFormatted_address();
applyGeoCode(marker)
}
}
} else {
Toast.makeText(AdressPicker.this, "An error has occured", Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<Address> call, Throwable t) {
Toast.makeText(AdressPicker.this, "An error has occured", Toast.LENGTH_LONG).show();
}
});
}
now from here call a method passing the marker
public void applyGeoCode(Marker marker){
double lat = marker.getPosition().latitude;
double lng = marker.getPosition().longitude;
marker.setSnippet(dropOffAddress);
marker.showInfoWindow();
editor.putString("dropOffAddress", dropOffAddress);
editor.putString("lat", String.valueOf(lat));
editor.putString("lng", String.valueOf(lng));
editor.apply();
}
and call like this
#Override
public void onMarkerDragEnd(Marker marker) {
reverseGeocode(String.valueOf(lat), String.valueOf(lng), marker);
}
You can use CountDownLatch from the java.utils.Concurrent class.
Here is an example:
public class DoSomething {
private Address dropoffAddr;
private CountDownLatch dropoffAddrLatch = new CountDownLatch(1);
public void getAddressCallback(Address addr) {
dropoffAddr = addr;
dropoffAddrLatch.countDown();
}
#Override
public void onMarkerDragEnd(Marker marker) {
//your stuff
reverseGeocode(...); //you should call getAddressCallback once you have everything
dropOffAddrLatch.await(); //this will wait until getAddressCallBack has returned,
// you can call dropoffAddrLatch.countDown() wherever you want.
//finish your stuff
}
}

Adding coordinate in Mapbox Android

I'm working with mapbox android, i'm trying to add multiple waypoints between origin and destination.but after adding one waypoint when it's adding another one this gives the exception " Too many coordinate the s; maximum number of coordinates is 3."
I just want to add multiple waypoint between two point and draw route over those line in mapbox android.
[pastbin link] : https://paste.ubuntu.com/p/PKMQzFyzVb/
My Route Draw Function -->
{
private void getRouteWithWaypoint(Point origin, Point destination, List<Point> wayPoints) {
assert Mapbox.getAccessToken() != null;
NavigationRoute.Builder builder = NavigationRoute.builder(getActivity())
.accessToken(Mapbox.getAccessToken())
.origin(origin)
.destination(destination);
if (wayPoints != null) {
for (Point point : wayPoints) {
builder.addWaypoint(point);
}
}
builder.build().getRoute(new Callback<DirectionsResponse>() {
#Override
public void onResponse(#NonNull Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
Log.e(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().routes().size() < 1) {
Log.e(TAG, "No routes found");
return;
}
currentRoute = response.body().routes().get(0);
if (navigationMapRoute != null) {
navigationMapRoute.removeRoute();
} else {
navigationMapRoute = new NavigationMapRoute(null, mapView, map, R.style.NavigationMapRoute);
}
navigationMapRoute.addRoute(currentRoute);
}
#SuppressLint("TimberArgCount")
#Override
public void onFailure(Call<DirectionsResponse> call, Throwable t) {
Timber.e(t, "Error: %s");
}
});
}}
Draw root on Mapbox map, copied the below code from Mapbox documentation.
private void getRoute(Point origin, Point destination) {
NavigationRoute.builder(this)
.accessToken(Mapbox.getAccessToken())
.origin(origin)
.destination(destination)
.build()
.getRoute(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().routes().size() < 1) {
Log.e(TAG, "No routes found");
return;
}
currentRoute = response.body().routes().get(0);
// Draw the route on the map
if (navigationMapRoute != null) {
navigationMapRoute.removeRoute();
} else {
navigationMapRoute = new NavigationMapRoute(null, mapView, mapboxMap, R.style.NavigationMapRoute);
}
navigationMapRoute.addRoute(currentRoute);
}
#Override
public void onFailure(Call<DirectionsResponse> call, Throwable throwable) {
Log.e(TAG, "Error: " + throwable.getMessage());
}
});
}
for more detail follow the link
https://www.mapbox.com/help/android-navigation-sdk/#calculate-and-draw-route
The default profile for requesting routes is DirectionsCriteria.ProfileCriteria.PROFILE_DRIVING_TRAFFIC
This profile allows only 1 waypoint between the origin and the destination. If you want to use more than 1 waypoint, just use PROFILE_DRIVING instead (this allows up to 25 waypoints I think).
Like this:
NavigationRoute.Builder builder = NavigationRoute.builder(getActivity())
.accessToken(Mapbox.getAccessToken())
.origin(origin)
.destination(destination)
.profile(DirectionsCriteria.ProfileCriteria.PROFILE_DRIVING);
if (wayPoints != null) {
for (Point point : wayPoints) {
builder.addWaypoint(point);
}
}

Custom Follow Me Mission DJI Android SDK

I am trying to create a FollowMeMission using the DJI Phantom 4 by providing custom coordinates, similar to this post Custom coordinates on Follow me Mission DJI Mobile SDK for android
My current code looks like this:
private double lat = 48.5561726;
private double lng = 12.1138481;
private float initHeight = 10f;
private LocationCoordinate2D location;
if (getFollowMeMissionOperator().getCurrentState().toString().equals(FollowMeMissionState.READY_TO_EXECUTE.toString())){
getFollowMeMissionOperator().updateFollowingTarget(new LocationCoordinate2D(lat + 0.0001d, lng), new CommonCallbacks.CompletionCallback() {
#Override
public void onResult(DJIError djiError) {
setResultToToast("Mission updateFollowingTarget: " + (djiError == null ? "Successfully" : djiError.getDescription()));
}
});
//Toast.makeText(getApplicationContext(), "updateFollowingTarget...", Toast.LENGTH_SHORT).show();
Log.println(Log.INFO,"FOLLOW", "Before");
try{
Thread.sleep(2500);
}catch (InterruptedException e){
setResultToToast("InterruptedException!" + e.getMessage());
}
getFollowMeMissionOperator().startMission(FollowMeMission.getInstance().initUserData(lat + 0.0001d , lng, initHeight), new CommonCallbacks.CompletionCallback() {
#Override
public void onResult(DJIError djiError) {
setResultToToast("Mission Start: " + (djiError == null ? "Successfully" : djiError.getDescription()));
}});
}
else{
Toast.makeText(getApplicationContext(), getFollowMeMissionOperator().getCurrentState().toString(), Toast.LENGTH_SHORT).show();
}
I even added a 2.5 sec sleep before calling startMission() as advised in this topic http://forum.dev.dji.com/thread-33716-1-1.html
What happens is, i invoke FollowMe() and after 2.5 sec i get the message "Mission Start: Successfull", but without any callback from updateFollowingTarget(). Then nothing happens, the drone stays where it is.
What am i doing wrong? Is the way i use updateFollowingTarget() and startMission() even right?
The causes on this issue are:
1. We need use timer to updateFollowingTarget in a given frequency.
2. The moving object (following target) need provide its dynamic location.
Please refer to below code to refine it for your case:
private float initHeight = 10f;
private LocationCoordinate2D movingObjectLocation;
private AtomicBoolean isRunning = new AtomicBoolean(false);
private Subscription timmerSubcription;
private Observable<Long> timer =Observable.timer(100, TimeUnit.MILLISECONDS).observeOn(Schedulers.computation()).repeat();
private void followMeStart(){
if (getFollowMeMissionOperator().getCurrentState().toString().equals(FollowMeMissionState.READY_TO_EXECUTE.toString())){
//ToDo: You need init or get the location of your moving object which will be followed by the aircraft.
getFollowMeMissionOperator().startMission(FollowMeMission.getInstance().initUserData(movingObjectLocation.getLatitude() , movingObjectLocation.getLongitude(), initHeight), new CommonCallbacks.CompletionCallback() {
#Override
public void onResult(DJIError djiError) {
setResultToToast("Mission Start: " + (djiError == null ? "Successfully" : djiError.getDescription()));
}});
if (!isRunning.get()) {
isRunning.set(true);
timmerSubcription = timer.subscribe(new Action1<Long>() {
#Override
public void call(Long aLong) {
getFollowMeMissionOperator().updateFollowingTarget(new LocationCoordinate2D(movingObjectLocation.getLatitude(),
movingObjectLocation.getLongitude()),
new CommonCallbacks.CompletionCallback() {
#Override
public void onResult(DJIError error) {
isRunning.set(false);
}
});
}
});
}
} else{
Toast.makeText(getApplicationContext(), getFollowMeMissionOperator().getCurrentState().toString(), Toast.LENGTH_SHORT).show();
}
}

Not able to draw complete path on mapbox, it is only connecting origin and destination

I want to draw a complete route on Mapbox from origin to destination using .geojson file.
Please find below code.
private void drawMapMatched(Position[] coordinates) {
try {
MapboxMapMatching client = new MapboxMapMatching.Builder()
.setAccessToken(Mapbox.getAccessToken())
.setSteps(true)
.setProfile(MapMatchingCriteria.PROFILE_DRIVING)
.setCoordinates(coordinates)
.build();
client.enqueueCall(new Callback<MapMatchingResponse>() {
#Override
public void onResponse(Call<MapMatchingResponse> call, Response<MapMatchingResponse> response) {
List<LatLng> mapMatchedPoints = new ArrayList<>();
if (response.code() == 200) {
String geometry = response.body().getMatchings().get(0).getGeometry();
List<Position> positions = PolylineUtils.decode(geometry, Constants.PRECISION_6);
if (positions == null) {
return;
}
for (int i = 0; i < positions.size(); i++) {
mapMatchedPoints.add(new LatLng(
positions.get(i).getLatitude(),
positions.get(i).getLongitude()));
}
if (mapMatchedRoute != null) {
mapboxMap.removeAnnotation(mapMatchedRoute);
}
mapMatchedRoute = mapboxMap.addPolyline(new PolylineOptions()
.color(Color.GREEN)
.alpha(0.65f)
.width(4));
for (int i = 0; i < mapMatchedPoints.size(); i++) {
mapMatchedRoute.addPoint(mapMatchedPoints.get(i));
}
Position origin = Position.fromCoordinates(mapMatchedPoints.get(0).getLongitude(), mapMatchedPoints.get(0).getLatitude());
Position destination = Position.fromCoordinates(mapMatchedPoints.get(mapMatchedPoints.size() - 1).getLongitude(), mapMatchedPoints.get(mapMatchedPoints.size() - 1).getLatitude());
getRoute(origin, destination);
} else {
Log.e(TAG, "Too many coordinates, profile not found, invalid input, or no match.");
}
}
#Override
public void onFailure(Call<MapMatchingResponse> call, Throwable throwable) {
Log.e(TAG, "MapboxMapMatching error: " + throwable.getMessage());
}
});
} catch (ServicesException servicesException) {
servicesException.printStackTrace();
}
locationLayerPlugin = new LocationLayerPlugin(mapView, mapboxMap, null); locationLayerPlugin.setLocationLayerEnabled(LocationLayerMode.NAVIGATION);
}
private void getRoute(final Position origin, final Position destination) {
ArrayList<Position> positions = new ArrayList<>();
positions.add(origin);
positions.add(destination);
MapboxDirections client = new MapboxDirections.Builder()
.setAccessToken(Mapbox.getAccessToken())
.setOrigin(origin)
.setDestination(destination)
.setAlternatives(true)
.setProfile(DirectionsCriteria.PROFILE_DRIVING)
.setSteps(true)
.setOverview(DirectionsCriteria.OVERVIEW_FULL)
.setBearings(new double[]{60, 45}, new double[]{45, 45})
.setAnnotation(DirectionsCriteria.ANNOTATION_DISTANCE, DirectionsCriteria.ANNOTATION_DURATION)
.build();
client.enqueueCall(new Callback<DirectionsResponse>() {
#Override
public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
Log.d(TAG, "API call URL: " + call.request().url().toString());
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;
}
// Print some info about the route
route = response.body().getRoutes().get(0);
//showMessage(String.format(Locale.US, "Route is %.1f meters long.", currentRoute.getDistance()));
// Draw the route on the map
drawRoute(route, origin, destination);
}
#Override
public void onFailure(Call<MapMatchingResponse> call, Throwable throwable) {
}
});
} catch (ServicesException servicesException) {
servicesException.printStackTrace();
}
locationLayerPlugin = new LocationLayerPlugin(mapView, mapboxMap, null);
locationLayerPlugin.setLocationLayerEnabled(LocationLayerMode.NAVIGATION);
}`
Route is getting draw but from origin to destination.
For example, if complete route is like, A-B-C-D-E, so I want to draw route which connects A-B-C-D-E but I am able to connect directly A-E.
Please guide.
Thanks in advance.

how to get list of points from kml layer android

i'm trying to get the coordinates of my kml layer in my android app, and i just cant seem to find how to do it.
i have this kml layer:
KmlLayer layer = new KmlLayer(mMap, R.raw.allowedarea, getApplicationContext());
and i'm trying to get the Latitude and Longtitude list of his boundries points.
ArrayList<LatLnt> latlitArray = layer.soemthing();
could find anything, please guys help.
Try this solution
try {
KmlLayer layer = new KmlLayer(googleMap, R.raw.zone, this);
layer.addLayerToMap();
Iterable<KmlContainer> containers = layer.getContainers();
accessContainers(containers);
} catch (XmlPullParserException | IOException e) {
e.printStackTrace();
}
public void accessContainers(Iterable<KmlContainer> containers) {
for (KmlContainer container : containers) {
if (container != null) {
if (container.hasContainers()) {
accessContainers(container.getContainers());
} else {
if (container.hasPlacemarks()) {
accessPlacemarks(container.getPlacemarks());
}
}
}
}
}
public void accessPlacemarks(Iterable<KmlPlacemark> placemarks) {
for (KmlPlacemark placemark : placemarks) {
if (placemark != null) {
KmlGeometry geometry = placemark.getGeometry();
if (geometry instanceof KmlPolygon) {
KmlPolygon polygon = (KmlPolygon) geometry;
mLatLngList.addAll(polygon.getOuterBoundaryCoordinates());
}
}
}
}
This will recursively access every placemark geometry inside the container. I'm not aware if the object obtained can actually be an instance of any other class or collection besides List and LatLng.
public void accessContainers(Iterable<KmlContainer> containers) {
for(KmlContainer c : containers) {
if(c.hasPlacemarks()) {
for(KmlPlacemark p : c.getPlacemarks()) {
KmlGeometry g = p.getGeometry();
Object object = g.getGeometryObject();
if(object instanceof LatLng) {
LatLng latlng = (LatLng)object;
//Do more stuff with the point
}
if(object instanceof List<?>) {
List<LatLng> list = (List<LatLng>)object;
//Do more stuff with the list of points
}
Log.d(TAG, g.getGeometryType() + ":" + object.toString());
}
}
if(c.hasContainers()) {
accessContainers(c.getContainers());
}
}
}

Categories

Resources