A colleague of mine is currently working on implementing turn by turn directions into an app that is being developed for the company we are working in. I have been tasked with trying to assist him but neither of us have been able to make any progress.
He is using Mapbox to create the map. I have never used mapbox before so I am not much help.
He has code implemented that should give us turn by turn directions but it does not seem to be doing anything whatsoever.
Sorry if I am bringing up old questions or am not stating my situation clearly but this is the best I can explain myself. We have done much searching but nothing we found seems to help.
Here is the code that he has tried using that is supposed to implement turn by turn directions.
private void getRoute(Waypoint origin, Waypoint destination) throws ServicesException {
MapboxDirections client = new MapboxDirections.Builder()
.setOrigin(origin)
.setDestination(destination)
.setProfile(DirectionsCriteria.PROFILE_DRIVING)
.setSteps(true)
// .setOverview(DirectionsCriteria.OVERVIEW_FULL)
.setInstructions(DirectionsCriteria.INSTRUCTIONS_TEXT)
.setAccessToken("pk.eyJ1IjoibnRyY3N2ZyIsImEiOiJCUmc4OHhjIn0.shHWdNg3Q32QUHJ1nOCs3A")
.build();
client.enqueue(new retrofit.Callback<DirectionsResponse>() {
#Override
public void onResponse(Response<DirectionsResponse> response, Retrofit retrofit) {
// 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;
}
}
#Override
public void onFailure(Throwable t) {
Log.e(TAG, "Error: " + t.getMessage());
Toast.makeText(MainActivity.this, "Error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
}
public void onResponse(Response<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;
}
drawRoute(currentRoute);
}
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());
}
Polyline polyline = mMapboxMap.addPolyline(new PolylineOptions()
.add(points)
.color(Color.RED)
.width(5));
directionsOn = true;
}
Any help would be very much appreciated.
Thanks in advance.
I'd highly recommend changing from Directions v4 to v5 found in Mapbox Java. Once you make the switch, you can work off this example found on our website. Make sure you are also passing in coordinates in the correct order, longitude is given first followed by latitude.
Dear friend mapbox provides detailed document with sample code snippets as well.
I have build a working app for my requirement by following mapbox turn by turn navigation documents.
please follow the link and let me know if you face any issues.
Link : https://www.mapbox.com/android-docs/navigation/overview/navigation-ui/
Here you can use NavigationView component to customise the mapbox turn by turn features.
Related
I am developing an android app where a customer requests a worker for pickuplocation, so i am using google direction library to show routes between the customer and worker but direction API keeps throwing error saying that you must use an API key to make requests to google cloud platform, already i have created a project in google cloud console and generated my key.
Here is what i have done;
First of all i started my project without a billing account, then in the process of my project i was required to create a billing account in order to make direction request so i linked my project what
What i did;
i added my API key to manifest
i have already enabled places API and direction API
in the direction part i am using google direction library, this one
i added it to app build-gradle
compile 'com.github.jd-alexander:library:1.1.0'
and here is a sample of code in my activity for direction request since i am using the above library i dont know whether it is because i created the project then billing account, what might be the problem?
Even places API does not function properly
private void getRouteToMarker(LatLng customerpickuplocation) {
Routing routing = new Routing.Builder()
.travelMode(AbstractRouting.TravelMode.DRIVING)
.withListener(this)
.alternativeRoutes(false)
.waypoints(new LatLng(lat, lng), customerpickuplocation)
.build();
routing.execute();
}
#Override
public void onRoutingFailure(RouteException e) {
if (e != null) {
Toast.makeText(this, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "Something went wrong, Try again", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onRoutingSuccess(ArrayList<Route> route, int shortestRouteIndex) {
if (polylines.size() > 0) {
for (Polyline poly : polylines) {
poly.remove();
}
}
polylines = new ArrayList<>();
//add route(s) to the map.
for (int i = 0; i < route.size(); i++) {
//In case of more than 5 alternative routes
int colorIndex = i % COLORS.length;
PolylineOptions polyOptions = new PolylineOptions();
polyOptions.color(getResources().getColor(COLORS[colorIndex]));
polyOptions.width(10 + i * 3);
polyOptions.addAll(route.get(i).getPoints());
Polyline polyline = mMap.addPolyline(polyOptions);
polylines.add(polyline);
Toast.makeText(getApplicationContext(), "Route " + (i + 1) + ": distance - " + route.get(i).getDistanceValue() + ": duration - " + route.get(i).getDurationValue(), Toast.LENGTH_SHORT).show();
}
}
i have come up with a solution but not a good security measure, by adding key to getRouteToMarker() method
private void getRouteToMarker(LatLng customerpickuplocation) {
Routing routing = new Routing.Builder()
.travelMode(AbstractRouting.TravelMode.DRIVING)
.withListener(this)
.alternativeRoutes(false)
.waypoints(new LatLng(lat, lng), customerpickuplocation)
.key("your api key")
.build();
routing.execute();
}
I installed the HERE test product on my tablet (it's an old Android 5.1 tablet without GPS or Cellular data, just Wifi) and it worked well to (approximately) give my position using Wifi.
So I am attempting to program the same in my app.
Downloaded the HERE API, got a freemium license for my app name, input the lines in my manifest:
<meta-data
android:name="com.here.android.maps.appid"
android:value="itkC4uIay69MTXXXXXXX" />
<meta-data
android:name="com.here.android.maps.apptoken"
android:value="NdT8laoCmRysyh8XXXXXXX" />
Included the HERE-sdk in my build, and my Code compiles just fine.
I have code in my MainActivity.onCreate() [EDIT I have added in code to initialize the map engine as recommended by HERE support below]:
MapEngine.getInstance().init(this, new OnEngineInitListener() {
#Override
public void onEngineInitializationCompleted(Error error) {
if (error == Error.NONE) {
Logger.i(Tags.POSITION, "correctly started map engine");
PositioningManager pm = PositioningManager.getInstance();
PositioningManager.LocationStatus ls = pm.getLocationStatus(PositioningManager.LocationMethod.GPS_NETWORK);
if (ls == PositioningManager.LocationStatus.AVAILABLE) {
Logger.i(Tags.POSITION, "Positioning is available");
} else {
Logger.w(Tags.POSITION, "Positioning not available right now " + ls.toString());
}
pm.start(PositioningManager.LocationMethod.GPS_NETWORK);
} else {
Logger.i(Tags.POSITION, "Problem setting up map engine: " + error);
}
}
});
Then I have code running once per minute on a timer to check my current position:
GeoPosition pos = PositioningManager.getInstance().getPosition();
if (pos == null) {
Log.w("Positioning", "GeoPosition is Null");
} else {
GeoCoordinate coord = pos.getCoordinate();
Logger.i("Positioning", "Location: Latitude = " + coord.getLatitude() + ", Longitude = " + coord.getLongitude());
Logger.i("Positioning", "Accuracy = " + pos.getLatitudeAccuracy() + ", " + pos.getLongitudeAccuracy());
}
When I run I get logs like this:
2019-01-27 11:49:31.960 30112-30112/com.company.app I/: [main] INFO Positioning: correctly started map engine
2019-01-27 11:49:31.961 30112-30112/com.company.app W: [main] WARN Positioning: Positioning not available right now OUT_OF_SERVICE
Then, once per minute
2019-01-27 11:50:30.850 30112-30343/com.company.app W/: [Timer-2] WARN Positioning: GeoPosition is Null
In "Settings" on the tablet "Location" is turned "On" though it says "No apps have requested Location recently"
The logs contain no Errors or warnings, all permissions are requested in the Manifest
[EDIT] The worst thing is my simple test app (mentioned in my comment below), now works after I added in the initializaion of the MapEngine. To answer HERE's question, I really am not interested in using mapping just now, I only want to pull a current Longitude and Latitude to aid in finding my tablet if lost.
Anyone have a clue what I am doing wrong?
I have a few questions to ask, the answer on which will help us to understand what is going wrong.
Do you want to show a map or just using PositioningManager?
If using PositionManager only, do you initialize MapEngine initially?
If you don't use a Map, you have to do something like this since PositionManager doesn't initialize MapEngine itself.
ApplicationContext context = new ApplicationContext(getApplicationContext());
MapEngine.getInstance().init(context, new OnEngineInitListener() {
#Override
public void onEngineInitializationCompleted(OnEngineInitListener.Error error) {
if (error == OnEngineInitListener.Error.NONE) {
} else {
}
}
});
Update: There is another test application on github that might be quite useful, no map using but position manager being used. Hope this helps!
https://github.com/heremaps/here-android-sdk-examples/tree/master/speed-limit-watcher
I'm trying to save a GeoPolygon into my Parse server using an android app but I keep getting an:
error 111: this is not a valid polygon
this is my code:
//create the parse object
ParseObject obj = new ParseObject("SomeClass");
List<ParseGeoPoint> geoPoints = new ArrayList<ParseGeoPoint>();
geoPoints.add(new ParseGeoPoint(1.468074, 110.429638));
geoPoints.add(new ParseGeoPoint(1.468075, 110.429287));
geoPoints.add(new ParseGeoPoint(1.467376, 110.429681));
geoPoints.add(new ParseGeoPoint(1.467373, 110.429283));
ParsePolygon geoPolygon = new ParsePolygon(geoPoints);
obj.put("Boundaries", geoPolygon);
obj.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Toast.makeText(getContext(), "Geo Polygon save complete.", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getContext(), "Geo Polygon save failed. error: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
I followed the Docs for geopolygons here:
http://docs.parseplatform.org/android/guide/#parsepolygon
and somehow, even when I copy pasted the code provided in the docs, it doesnt work.
Any suggestions/ solutions are most welcomed.
I believe not many people may see this but I'll post my solution to this anyway.
The issue was solved after I updated the version of my Parse Server. I didn't note which version I updated the Parse Server from but my current Parse Server is now v2.7.1 .
Previous/ older version of Parse Server does not support geo-Polygons.
I am writing an Android App using Xamarin which uses Xamarin.GooglePlayServices.Maps Nuget Package. I need to get to a particular place on the map using the name of the place. For this purpose I loaded Xamarin.GooglePlayServices.Places. I am able to pass a partial place name to the GetAutocompletePredictionsAsync as so:
var autocompletePredictions = await
PlacesClass.GeoDataApi.GetAutocompletePredictionsAsync(
Adapter.googleApiClient, constraint.ToString(),
Adapter.bounds, Adapter.autoCompleteFilter);
The result I get back is basically a collection of IAutocompletePrediction. The only item in this object that has to do with location is the PlaceId. I cannot find any way to use this on the Google Maps API. I tried seeing if I could get any more information by calling the GetPlaceById:
var place = PlacesClass.GeoDataApi.GetPlaceById(googleApiClient, item.PlaceId);
But I didn't see any location information at all in that result. Does anyone know how to get LatLng information from the Google Places API?
Update: I used information from several responses to get the answer:
Task.Run(async () =>
{
PlaceBuffer places = await PlacesClass.GeoDataApi.GetPlaceByIdAsync(googleApiClient, item.PlaceId);
if (places.Status.IsSuccess)
{
foreach (var place in places)
try
{
//IPlace place = (IPlace)places.Get(0);
MarkOnMap(place.NameFormatted.ToString(), place.AddressFormatted.ToString(), place.LatLng);
UpdateCameraPosition(place.LatLng);
}
catch (Exception ex)
{
Log.Error("WhatNow", ex.ToString());
}
}
places.Dispose();
});
The odd thing was when I enumerated the places in the foreach, the place was an IPlace type. However
IPlace place = (IPlace)places.Get(0);
Did not cast to an IPlace. Who knows? I just hope that Dispose() releases the buffer as recommended in the Docs. Xamarin is always just a little different from Java.
Thanks to everyone who helped.
I have used this, you can try this code.
I am using autoCompleteTextView.
dropLocationEt.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final PlaceAutoCompleteAdapter.PlaceAutocomplete item = mAdapter.getItem(position);
final String placeId = String.valueOf(item.placeId);
Log.i(TAG, "Autocomplete item selected: " + item.description);
/*
Issue a request to the Places Geo Data API to retrieve a Place object with additional
details about the place.
*/
PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi
.getPlaceById(googleApiClient, placeId);
placeResult.setResultCallback(new ResultCallback<PlaceBuffer>() {
#Override
public void onResult(PlaceBuffer places) {
if (!places.getStatus().isSuccess()) {
// Request did not complete successfully
Log.e(TAG, "Place query did not complete. Error: " + places.getStatus().toString());
places.release();
return;
}
// Get the Place object from the buffer.
final Place place = places.get(0);
latLngDrop = place.getLatLng();
StaticMethods.hideKeyboard(getActivity());
dropLocationEt.setSelection(0);
}
});
}
});
From the latlngDrop, you can retrieve the lat and lng, eg: latlngDrop.getLatitude, latlngDrop.getLongitude
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/