I'm using the Roads Google API passing a list of positions and I want to paint lines in the most probable road driven by a car by these points.
Something is going wrong because some points are not being crossed by the lines and the lines are not using only roads, some of them pass through edifices or the sea with straight lines. I added markers to show the problem.
Is something wrong in the code?
Some sample code to get this error:
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mGoogleMap;
private MapFragment mapFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mapFragment = (MapFragment) getFragmentManager()
.findFragmentById(R.id.map_fragment);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
List<LatLng> sourcePoints = new ArrayList<>();
sourcePoints.add(new LatLng(39.4321055669415, -0.343169529033198));
sourcePoints.add(new LatLng(39.4279737815806, -0.334743742804801));
sourcePoints.add(new LatLng(39.4235262880062, -0.341102620562518));
sourcePoints.add(new LatLng(39.4216973481355, -0.340624944612178));
sourcePoints.add(new LatLng(39.4194951574233, -0.335974058847626));
sourcePoints.add(new LatLng(39.4216760915054, -0.340342003540913));
sourcePoints.add(new LatLng(39.4235646246302, -0.340901154018858));
sourcePoints.add(new LatLng(39.4321131753486, -0.342995147300383));
PolylineOptions polyLineOptions = new PolylineOptions();
polyLineOptions.addAll(sourcePoints);
polyLineOptions.width(5);
polyLineOptions.color(Color.BLUE);
mGoogleMap.addPolyline(polyLineOptions);
mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(sourcePoints.get(0), 15));
List<LatLng> snappedPoints = new ArrayList<>();
new GetSnappedPointsAsyncTask().execute(sourcePoints, null, snappedPoints);
}
private String buildRequestUrl(List<LatLng> trackPoints) {
StringBuilder url = new StringBuilder();
url.append("https://roads.googleapis.com/v1/snapToRoads?path=");
for (LatLng trackPoint : trackPoints) {
url.append(String.format("%8.5f", trackPoint.latitude));
url.append(",");
url.append(String.format("%8.5f", trackPoint.longitude));
url.append("|");
}
url.delete(url.length() - 1, url.length());
url.append("&interpolate=true");
url.append(String.format("&key=%s", <your_Google_Maps_API_key>);
return url.toString();
}
private class GetSnappedPointsAsyncTask extends AsyncTask<List<LatLng>, Void, List<LatLng>> {
protected void onPreExecute() {
super.onPreExecute();
}
protected List<LatLng> doInBackground(List<LatLng>... params) {
List<LatLng> snappedPoints = new ArrayList<>();
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(buildRequestUrl(params[0]));
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder jsonStringBuilder = new StringBuilder();
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line+"\n");
jsonStringBuilder.append(line);
jsonStringBuilder.append("\n");
}
JSONObject jsonObject = new JSONObject(jsonStringBuilder.toString());
JSONArray snappedPointsArr = jsonObject.getJSONArray("snappedPoints");
for (int i = 0; i < snappedPointsArr.length(); i++) {
JSONObject snappedPointLocation = ((JSONObject) (snappedPointsArr.get(i))).getJSONObject("location");
double lattitude = snappedPointLocation.getDouble("latitude");
double longitude = snappedPointLocation.getDouble("longitude");
snappedPoints.add(new LatLng(lattitude, longitude));
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return snappedPoints;
}
#Override
protected void onPostExecute(List<LatLng> result) {
super.onPostExecute(result);
PolylineOptions polyLineOptions = new PolylineOptions();
polyLineOptions.addAll(result);
polyLineOptions.width(5);
polyLineOptions.color(Color.RED);
mGoogleMap.addPolyline(polyLineOptions);
LatLngBounds.Builder builder = new LatLngBounds.Builder();
builder.include(result.get(0));
builder.include(result.get(result.size()-1));
LatLngBounds bounds = builder.build();
mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 10));
}
}
}
It's everything ok with your code: there are not enough points for Snap to Roads. You should use Google Maps Directions API instead of Snap to Roads API to get lacking points: format route request, receive and parse response - you need overview_polyline tag points String value - it's encoded polyline of route part For your source points (blue path on figure):
List<LatLng> sourcePoints = new ArrayList<>();
sourcePoints.add(new LatLng(39.4321055669415, -0.343169529033198));
sourcePoints.add(new LatLng(39.4279737815806, -0.334743742804801));
sourcePoints.add(new LatLng(39.4235262880062, -0.341102620562518));
sourcePoints.add(new LatLng(39.4216973481355, -0.340624944612178));
sourcePoints.add(new LatLng(39.4194951574233, -0.335974058847626));
sourcePoints.add(new LatLng(39.4216760915054, -0.340342003540913));
sourcePoints.add(new LatLng(39.4235646246302, -0.340901154018858));
sourcePoints.add(new LatLng(39.4321131753486, -0.342995147300383));
with Google Maps Directions API implementation like that:
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
private static final String TAG = MainActivity.class.getSimpleName();
private GoogleMap mGoogleMap;
private MapFragment mapFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mapFragment = (MapFragment) getFragmentManager()
.findFragmentById(R.id.map_fragment);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
List<LatLng> sourcePoints = new ArrayList<>();
sourcePoints.add(new LatLng(39.4321055669415, -0.343169529033198));
sourcePoints.add(new LatLng(39.4279737815806, -0.334743742804801));
sourcePoints.add(new LatLng(39.4235262880062, -0.341102620562518));
sourcePoints.add(new LatLng(39.4216973481355, -0.340624944612178));
sourcePoints.add(new LatLng(39.4194951574233, -0.335974058847626));
sourcePoints.add(new LatLng(39.4216760915054, -0.340342003540913));
sourcePoints.add(new LatLng(39.4235646246302, -0.340901154018858));
sourcePoints.add(new LatLng(39.4321131753486, -0.342995147300383));
PolylineOptions polyLineOptions = new PolylineOptions();
polyLineOptions.addAll(sourcePoints);
polyLineOptions.width(5);
polyLineOptions.color(Color.BLUE);
mGoogleMap.addPolyline(polyLineOptions);
mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(sourcePoints.get(0), 15));
List<LatLng> directionsPoints = new ArrayList<>();
new GetDirectionPointsAsyncTask().execute(sourcePoints, null, directionsPoints);
}
private String buildDirectionsUrl(List<LatLng> trackPoints) {
if (trackPoints.size() < 2) {
return null;
}
final LatLng origin = trackPoints.get(0);
final LatLng dest = trackPoints.get(trackPoints.size() - 1);
StringBuilder url = new StringBuilder();
url.append("https://maps.googleapis.com/maps/api/directions/json?");
url.append(String.format("origin=%8.5f,%8.5f", origin.latitude, origin.longitude));
url.append(String.format("&destination=%8.5f,%8.5f", dest.latitude, dest.longitude));
// add waypoints, if they exists
if (trackPoints.size() > 2) {
url.append("&waypoints=");
LatLng wayPoint;
for (int ixWaypoint = 1; ixWaypoint < trackPoints.size() - 2; ixWaypoint++) {
wayPoint = trackPoints.get(ixWaypoint);
url.append(String.format("%8.5f,%8.5f|", wayPoint.latitude, wayPoint.longitude));
}
url.delete(url.length() - 1, url.length());
}
url.append(String.format("&key=%s", getResources().getString(R.string.google_maps_key)));
return url.toString();
}
private class GetDirectionPointsAsyncTask extends AsyncTask<List<LatLng>, Void, List<LatLng>> {
protected void onPreExecute() {
super.onPreExecute();
}
protected List<LatLng> doInBackground(List<LatLng>... params) {
List<LatLng> routePoints = new ArrayList<>();
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(buildDirectionsUrl(params[0]));
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();
int responseCode = connection.getResponseCode();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder jsonStringBuilder = new StringBuilder();
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line+"\n");
jsonStringBuilder.append(line);
jsonStringBuilder.append("\n");
}
JSONObject jsonRoot = new JSONObject(jsonStringBuilder.toString());
JSONArray jsonRoutes = jsonRoot.getJSONArray("routes");
if (jsonRoutes.length() < 1) {
return null;
}
JSONObject jsonRoute = jsonRoutes.getJSONObject(0);
JSONObject overviewPolyline = jsonRoute.getJSONObject("overview_polyline");
String overviewPolylineEncodedPoints = overviewPolyline.getString("points");
routePoints = decodePoly(overviewPolylineEncodedPoints);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return routePoints;
}
#Override
protected void onPostExecute(List<LatLng> result) {
super.onPostExecute(result);
PolylineOptions polyLineOptions = new PolylineOptions();
polyLineOptions.addAll(result);
polyLineOptions.width(5);
polyLineOptions.color(Color.RED);
mGoogleMap.addPolyline(polyLineOptions);
LatLngBounds.Builder builder = new LatLngBounds.Builder();
builder.include(result.get(0));
builder.include(result.get(result.size()-1));
LatLngBounds bounds = builder.build();
mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 10));
}
}
//
// Method to decode polyline points
// Courtesy : http://jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java
private List<LatLng> decodePoly(String encoded) {
List<LatLng> poly = new ArrayList<>();
int index = 0, len = encoded.length();
int lat = 0, lng = 0;
while (index < len) {
int b, shift = 0, result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
LatLng p = new LatLng((((double) lat / 1E5)),
(((double) lng / 1E5)));
poly.add(p);
}
return poly;
}
}
you get something like that (red path on figure):
NB! Don't forget to allow Directions API on Google APIs Console
More details about Direction API here and in many online tutorials/examples.
Related
my application is based on GPS data and for that I'm using Fused-location-provider.
From now and then I have seen that there's a gps jitters and some GPS coordinates are off the road. This is unacceptable. What I tried to do was to implement Kalman filter and I did:
fun process(
newSpeed: Float,
newLatitude: Double,
newLongitude: Double,
newTimeStamp: Long,
newAccuracy: Float
) {
if (variance < 0) { // if variance < 0, object is unitialised, so initialise with current values
setState(newLatitude, newLongitude, newTimeStamp, newAccuracy)
} else { // else apply Kalman filter
val duration = newTimeStamp - timeStamp
if (duration > 0) { // time has moved on, so the uncertainty in the current position increases
variance += duration * newSpeed * newSpeed / 1000
timeStamp = newTimeStamp
}
val k = variance / (variance + newAccuracy * newAccuracy)
latitude += k * (newLatitude - latitude)
longitude += k * (newLongitude - longitude)
variance *= (1 - k)
retrieveLocation(newSpeed, longitude, latitude, duration, newAccuracy)
}
}
And I'm using it whenever I receive new location as
KalmanFilter.process(
it.newSpeed,
it.newLatitude,
it.newLongitude,
it.newTimeStamp,
it.newAccuracy
)
This helped to receive little bit more accurate results, but still - it did not fix the GPS jitter that was outside the road (see image):
Things I want to know:
Is my kalman filter implemented correctly? Is there way to improve current solution?
How to avoid a scenerios where coordinate is outside the road? (Something similar to snap-to-roads functionality, but as an algorithm inside app)
Seems on your picture is not jitter (or not only jitter), but gap in GPS data:
there are no points on road between points 1 and 2 on picture and there is no possibilities to add them with any Kalman filter implementation (if they absent in source raw GPS data) because there is no information about the location of the road. If you cannot change the firmware of the tracker device, you can use Snap to Roads of Google Maps Roads API like in this answer:
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mGoogleMap;
private MapFragment mapFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mapFragment = (MapFragment) getFragmentManager()
.findFragmentById(R.id.map_fragment);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
List<LatLng> sourcePoints = new ArrayList<>();
sourcePoints.add(new LatLng(-35.27801,149.12958));
sourcePoints.add(new LatLng(-35.28032,149.12907));
sourcePoints.add(new LatLng(-35.28099,149.12929));
sourcePoints.add(new LatLng(-35.28144,149.12984));
sourcePoints.add(new LatLng(-35.28194,149.13003));
sourcePoints.add(new LatLng(-35.28282,149.12956));
sourcePoints.add(new LatLng(-35.28302,149.12881));
sourcePoints.add(new LatLng(-35.28473,149.12836));
PolylineOptions polyLineOptions = new PolylineOptions();
polyLineOptions.addAll(sourcePoints);
polyLineOptions.width(5);
polyLineOptions.color(Color.BLUE);
mGoogleMap.addPolyline(polyLineOptions);
mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(sourcePoints.get(0), 15));
List<LatLng> snappedPoints = new ArrayList<>();
new GetSnappedPointsAsyncTask().execute(sourcePoints, null, snappedPoints);
}
private String buildRequestUrl(List<LatLng> trackPoints) {
StringBuilder url = new StringBuilder();
url.append("https://roads.googleapis.com/v1/snapToRoads?path=");
for (LatLng trackPoint : trackPoints) {
url.append(String.format("%8.5f", trackPoint.latitude));
url.append(",");
url.append(String.format("%8.5f", trackPoint.longitude));
url.append("|");
}
url.delete(url.length() - 1, url.length());
url.append("&interpolate=true");
url.append(String.format("&key=%s", <your_Google_Maps_API_key>);
return url.toString();
}
private class GetSnappedPointsAsyncTask extends AsyncTask<List<LatLng>, Void, List<LatLng>> {
protected void onPreExecute() {
super.onPreExecute();
}
protected List<LatLng> doInBackground(List<LatLng>... params) {
List<LatLng> snappedPoints = new ArrayList<>();
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(buildRequestUrl(params[0]));
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder jsonStringBuilder = new StringBuilder();
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line+"\n");
jsonStringBuilder.append(line);
jsonStringBuilder.append("\n");
}
JSONObject jsonObject = new JSONObject(jsonStringBuilder.toString());
JSONArray snappedPointsArr = jsonObject.getJSONArray("snappedPoints");
for (int i = 0; i < snappedPointsArr.length(); i++) {
JSONObject snappedPointLocation = ((JSONObject) (snappedPointsArr.get(i))).getJSONObject("location");
double lattitude = snappedPointLocation.getDouble("latitude");
double longitude = snappedPointLocation.getDouble("longitude");
snappedPoints.add(new LatLng(lattitude, longitude));
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return snappedPoints;
}
#Override
protected void onPostExecute(List<LatLng> result) {
super.onPostExecute(result);
PolylineOptions polyLineOptions = new PolylineOptions();
polyLineOptions.addAll(result);
polyLineOptions.width(5);
polyLineOptions.color(Color.RED);
mGoogleMap.addPolyline(polyLineOptions);
LatLngBounds.Builder builder = new LatLngBounds.Builder();
builder.include(result.get(0));
builder.include(result.get(result.size()-1));
LatLngBounds bounds = builder.build();
mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 10));
}
}
}
not for all, but at least for detailed route view (because of limits: 100 GPS points and 2500 request per day per user (IP) and 10 requests per sec.) "online" or "preprocess" full route once, store and show not raw, but already processed route - that is a kind of "Something similar to snap-to-roads functionality, but as an algorithm inside app".
I will be posting all of my codes here and a sample output of my project. I have set the alternative to yes to display the alternate routes but problem is, how do I parse all the distance from all routes? It only gets the distance of the main route but not the alternate routes. How do I change my Parse java class to get all the directions in alternate routes and display it?
public class ThirdFragment extends Fragment implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
LocationListener,DirectionFinderListener,AdapterView.OnItemClickListener {
/**************************************************************/
// private GoogleMap mMap;
private ImageButton btnFindPath;
private AutoCompleteTextView etOrigin;
private AutoCompleteTextView etDestination;
private List<Marker> originMarkers = new ArrayList<>();
private List<Marker> destinationMarkers = new ArrayList<>();
private List<Polyline> polylinePaths = new ArrayList<>();
private ProgressDialog progressDialog;
private static final String LOG_TAG = "Google Places Autocomplete";
private static final String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place";
private static final String TYPE_AUTOCOMPLETE = "/autocomplete";
private static final String OUT_JSON = "/json";
private static final String API_KEY = "MY API KEY HERE";
//FOR COLLAPSING TOOLBAR
private CollapsingToolbarLayout collapsingToolbarLayout = null;
/**************************************************************************************************************/
double latitude;
double longitude;
GoogleMap mMap;
MapView mapView;
View Myview;
GoogleApiClient mGoogleApiClient;
Location mLastLocation;
Marker mCurrLocationMarker;
LocationRequest mLocationRequest;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
Myview = inflater.inflate(R.layout.activity_third_fragment, container, false);
mapView = (MapView) Myview.findViewById(R.id.mapview);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
/********************************************************************/
collapsingToolbarLayout = (CollapsingToolbarLayout) Myview.findViewById(R.id.collapsing_toolbar);
/****************************************************************************************/
btnFindPath = (ImageButton) Myview.findViewById(R.id.btnFindPath);
etOrigin = (AutoCompleteTextView) Myview.findViewById(R.id.etOrigin);
etDestination = (AutoCompleteTextView) Myview.findViewById(R.id.etDestination);
btnFindPath.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sendRequest();
}
});
etOrigin.setAdapter(new GooglePlacesAutocompleteAdapter(getActivity(), R.layout.list_item));
etOrigin.setOnItemClickListener(this);
etDestination.setAdapter(new GooglePlacesAutocompleteAdapter(getActivity(), R.layout.list_item));
etDestination.setOnItemClickListener(this);
return Myview;
}
//**********For changing colors in the directions************************************************************/
/**************************************************************************************************************/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
goToLocationZoom(9.3068, 123.3054, 15);
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
//Initialize Google Play Services
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
} else {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
LatLngBounds Dumaguete = new LatLngBounds(new LatLng(9.267, 123.264), new LatLng(9.33, 123.311));
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
mMap.setMinZoomPreference(15.0f);
mMap.setMaxZoomPreference(20.0f);
mMap.setLatLngBoundsForCameraTarget(Dumaguete);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(Dumaguete.getCenter(), 15));
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mMap.setMyLocationEnabled(true);
}
private void goToLocationZoom(double lat, double lng, int zoom) {
LatLng ll = new LatLng(lat, lng);
CameraUpdate update = CameraUpdateFactory.newLatLngZoom(ll, zoom);
mMap.moveCamera(update);
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
public void onLocationChanged(Location location) {
Log.d("onLocationChanged", "entered");
mLastLocation = location;
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
//Place current location marker
latitude = location.getLatitude();
longitude = location.getLongitude();
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
//mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
Toast.makeText(getActivity(),"Your Current Location", Toast.LENGTH_LONG).show();
Log.d("onLocationChanged", String.format("latitude:%.3f longitude:%.3f",latitude,longitude));
//stop location updates
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
Log.d("onLocationChanged", "Removing Location Updates");
}
Log.d("onLocationChanged", "Exit");
}
private void sendRequest() {
String origin = etOrigin.getText().toString();
String destination = etDestination.getText().toString();
if (origin.isEmpty()) {
Toast.makeText(getActivity(), "Please enter origin address!", Toast.LENGTH_SHORT).show();
return;
}
if (destination.isEmpty()) {
Toast.makeText(getActivity(), "Please enter destination address!", Toast.LENGTH_SHORT).show();
return;
}
try {
new DirectionFinder(this, origin, destination).execute();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
#Override
public void onDirectionFinderStart() {
progressDialog = ProgressDialog.show(getActivity(), "Please wait.",
"Finding direction..!", true);
if (originMarkers != null) {
for (Marker marker : originMarkers) {
marker.remove();
}
}
if (destinationMarkers != null) {
for (Marker marker : destinationMarkers) {
marker.remove();
}
}
if (polylinePaths != null) {
for (Polyline polyline : polylinePaths) {
polyline.remove();
}
}
}
#Override
public void onDirectionFinderSuccess(List<Route> routes) {
progressDialog.dismiss();
polylinePaths = new ArrayList<>();
originMarkers = new ArrayList<>();
destinationMarkers = new ArrayList<>();
Toast.makeText(getActivity(), "Directions found!", Toast.LENGTH_SHORT).show();
for (final Route route : routes) {
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(route.startLocation, 16));
((TextView) Myview.findViewById(R.id.tvDistance)).setText(route.distance.text); //For Distance
originMarkers.add(mMap.addMarker(new MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.start_blue))
.title(route.startAddress)
.position(route.startLocation)));
destinationMarkers.add(mMap.addMarker(new MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.end_green))
.title(route.endAddress)
.position(route.endLocation)));
/******************For Changing color ********************************************************/
mMap.setOnPolylineClickListener(new GoogleMap.OnPolylineClickListener() {
#Override
public void onPolylineClick(Polyline polyline) {
// Flip the values of the red, green and blue components of the polyline's color.
polyline.setColor(polyline.getColor() ^ 0x00ffffff);
// Toast.makeText(getActivity(), "Hello", Toast.LENGTH_SHORT).show();
}
});
/*************************************************************************************************/
Random rnd = new Random();
int color = Color.argb(255, rnd.nextInt(256), rnd.nextInt(257), rnd.nextInt(258));
/**/
PolylineOptions polylineOptions = new PolylineOptions().
geodesic(true).color(color).width(15).clickable(true);
for (int i = 0; i < route.points.size(); i++)
polylineOptions.add(route.points.get(i));
polylinePaths.add(mMap.addPolyline(polylineOptions));
}
}
public void onItemClick(AdapterView adapterView, View view, int position, long id) {
String str = (String) adapterView.getItemAtPosition(position);
Toast.makeText(getActivity(), str, Toast.LENGTH_SHORT).show();
}
public static ArrayList autocomplete(String input) {
ArrayList resultList = null;
HttpURLConnection conn = null;
StringBuilder jsonResults = new StringBuilder();
try {
StringBuilder sb = new StringBuilder(PLACES_API_BASE + TYPE_AUTOCOMPLETE + OUT_JSON);
sb.append("?key=" + API_KEY);
sb.append("&types=establishment&strictbounds&location=9.30684,123.305447&radius=2000");
sb.append("&input=" + URLEncoder.encode(input, "utf8"));
URL url = new URL(sb.toString());
conn = (HttpURLConnection) url.openConnection();
InputStreamReader in = new InputStreamReader(conn.getInputStream());
// Load the results into a StringBuilder
int read;
char[] buff = new char[1024];
while ((read = in.read(buff)) != -1) {
jsonResults.append(buff, 0, read);
}
} catch (MalformedURLException e) {
Log.e(LOG_TAG, "Error processing Places API URL", e);
return resultList;
} catch (IOException e) {
Log.e(LOG_TAG, "Error connecting to Places API", e);
return resultList;
} finally {
if (conn != null) {
conn.disconnect();
}
}
try {
// Create a JSON object hierarchy from the results
JSONObject jsonObj = new JSONObject(jsonResults.toString());
JSONArray predsJsonArray = jsonObj.getJSONArray("predictions");
// Extract the Place descriptions from the results
resultList = new ArrayList(predsJsonArray.length());
for (int i = 0; i < predsJsonArray.length(); i++) {
System.out.println(predsJsonArray.getJSONObject(i).getString("description"));
System.out.println("============================================================");
resultList.add(predsJsonArray.getJSONObject(i).getString("description"));
}
} catch (JSONException e) {
Log.e(LOG_TAG, "Cannot process JSON results", e);
}
return resultList;
}
class GooglePlacesAutocompleteAdapter extends ArrayAdapter implements Filterable {
private ArrayList resultList;
public GooglePlacesAutocompleteAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
}
#Override
public int getCount() {
return resultList.size();
}
#Override
public String getItem(int index) {
return String.valueOf(resultList.get(index));
}
#Override
public Filter getFilter() {
Filter filter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if (constraint != null) {
// Retrieve the autocomplete results.
resultList = autocomplete(constraint.toString());
// Assign the data to the FilterResults
filterResults.values = resultList;
filterResults.count = resultList.size();
}
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results != null && results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
return filter;
}
}
#Override
public void onResume() {
mapView.onResume();
super.onResume();
}
#Override
public void onPause() {
super.onPause();
mapView.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
// mapView.onDestroy();
}
#Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
}//End of CLass ThirdFragment.java
This is my Data Parsing and how do I change it to also get the distance of the alternate routes?
DirectionFInder.java
import android.os.AsyncTask;
import com.google.android.gms.maps.model.LatLng;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
public class DirectionFinder {
private static final String DIRECTION_URL_API = "https://maps.googleapis.com/maps/api/directions/json?";
private static final String GOOGLE_API_KEY = "AIzaSyC1E8NU2jjoQF7dN37bIOz_1fy0fe98YhI";
private DirectionFinderListener listener;
private String origin;
private String destination;
public DirectionFinder(DirectionFinderListener listener, String origin, String destination) {
this.listener = listener;
this.origin = origin;
this.destination = destination;
}
public void execute() throws UnsupportedEncodingException {
listener.onDirectionFinderStart();
new DownloadRawData().execute(createUrl());
}
private String createUrl() throws UnsupportedEncodingException {
String urlOrigin = URLEncoder.encode(origin, "utf-8");
String urlDestination = URLEncoder.encode(destination, "utf-8");
return DIRECTION_URL_API + "origin=" + urlOrigin + "&destination=" + urlDestination +"&alternatives=true" +"&key=" + GOOGLE_API_KEY;
}
private class DownloadRawData extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
String link = params[0];
try {
URL url = new URL(link);
InputStream is = url.openConnection().getInputStream();
StringBuffer buffer = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
return buffer.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String res) {
try {
parseJSon(res);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
private void parseJSon(String data) throws JSONException {
if (data == null)
return;
List<Route> routes = new ArrayList<Route>();
JSONObject jsonData = new JSONObject(data);
JSONArray jsonRoutes = jsonData.getJSONArray("routes");
for (int i = 0; i < jsonRoutes.length(); i++) {
JSONObject jsonRoute = jsonRoutes.getJSONObject(i);
Route route = new Route();
JSONObject overview_polylineJson = jsonRoute.getJSONObject("overview_polyline");
JSONArray jsonLegs = jsonRoute.getJSONArray("legs");
JSONObject jsonLeg = jsonLegs.getJSONObject(0);
JSONObject jsonDistance = jsonLeg.getJSONObject("distance");
JSONObject jsonDuration = jsonLeg.getJSONObject("duration");
JSONObject jsonEndLocation = jsonLeg.getJSONObject("end_location");
JSONObject jsonStartLocation = jsonLeg.getJSONObject("start_location");
route.distance = new Distance(jsonDistance.getString("text"), jsonDistance.getInt("value"));
route.duration = new Duration(jsonDuration.getString("text"), jsonDuration.getInt("value"));
route.endAddress = jsonLeg.getString("end_address");
route.startAddress = jsonLeg.getString("start_address");
route.startLocation = new LatLng(jsonStartLocation.getDouble("lat"), jsonStartLocation.getDouble("lng"));
route.endLocation = new LatLng(jsonEndLocation.getDouble("lat"), jsonEndLocation.getDouble("lng"));
route.points = decodePolyLine(overview_polylineJson.getString("points"));
routes.add(route);
}
listener.onDirectionFinderSuccess(routes);
}
private List<LatLng> decodePolyLine(final String poly) {
int len = poly.length();
int index = 0;
List<LatLng> decoded = new ArrayList<LatLng>();
int lat = 0;
int lng = 0;
while (index < len) {
int b;
int shift = 0;
int result = 0;
do {
b = poly.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = poly.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
decoded.add(new LatLng(
lat / 100000d, lng / 100000d
));
}
return decoded;
}
}
This is the screenshot of the application.
The dark green color is the main route and the pink and blue are the alternate routes. How can I get the distance of the pink and blue as well? Please help.
You are already looping through all of the routes, so storing the distance for each route should be simple. This line of code is where you get the distance for each route:
route.distance = new Distance(jsonDistance.getString("text"), jsonDistance.getInt("value"));'
If you create an array, you can store the value of each route during each iteration of the loop. Let's say you have an array called routeDistances[]. You could do something like this:
for (int i = 0; i < jsonRoutes.length(); i++) {
JSONObject jsonRoute = jsonRoutes.getJSONObject(i);
Route route = new Route();
JSONObject overview_polylineJson = jsonRoute.getJSONObject("overview_polyline");
JSONArray jsonLegs = jsonRoute.getJSONArray("legs");
JSONObject jsonLeg = jsonLegs.getJSONObject(0);
JSONObject jsonDistance = jsonLeg.getJSONObject("distance");
JSONObject jsonDuration = jsonLeg.getJSONObject("duration");
JSONObject jsonEndLocation = jsonLeg.getJSONObject("end_location");
JSONObject jsonStartLocation = jsonLeg.getJSONObject("start_location");
routeDistances[i] = jsonDistance.getInt("value"); // add this line
route.distance = new Distance(jsonDistance.getString("text"), jsonDistance.getInt("value"));
route.duration = new Duration(jsonDuration.getString("text"), jsonDuration.getInt("value"));
route.endAddress = jsonLeg.getString("end_address");
route.startAddress = jsonLeg.getString("start_address");
route.startLocation = new LatLng(jsonStartLocation.getDouble("lat"), jsonStartLocation.getDouble("lng"));
route.endLocation = new LatLng(jsonEndLocation.getDouble("lat"), jsonEndLocation.getDouble("lng"));
route.points = decodePolyLine(overview_polylineJson.getString("points"));
routes.add(route);
}
The line of code will allow you to store the distance for each route. You can then get the distance using the array. For example routeDistances[0] will have the distance for the first route, routeDistances[1] will have the distance for the next route etc.
i want to draw a road direction in android . I tried many times, but I always get the same error.Thank you for your help
Directions Parser
public class DirectionsJSONParser {
public List<List<HashMap<String, String>>> parse(JSONObject jObject) {
List<List<HashMap<String, String>>> routes = new ArrayList<List<HashMap<String, String>>>();
JSONArray jRoutes = null;
JSONArray jLegs = null;
JSONArray jSteps = null;
try {
jRoutes = jObject.getJSONArray("routes");
for (int i=0 ; i<jRoutes.length(); i++)
{
jLegs = ((JSONObject)jRoutes.get(i)).getJSONArray("legs");
List path = new ArrayList<HashMap<String, String>>();
for (int j=0; j<jLegs.length(); j++)
{
jSteps = ( (JSONObject)jLegs.get(j)).getJSONArray("steps");
for (int k=0; k<jSteps.length(); k++)
{
String polyline = "";
polyline = (String)((JSONObject)((JSONObject)jSteps.get(k)).get("polyline")).get("points");
List<LatLng> list = decodePoly(polyline);
for(int l=0; l<list.size(); l++)
{
HashMap<String, String> hm = new HashMap<String, String>();
hm.put("lat", Double.toString(((LatLng)list.get(l)).latitude));
hm.put("lng", Double.toString(((LatLng)list.get(l)).longitude));
path.add(hm);
}
}
routes.add(path);
}
}
} catch (JSONException e) {
e.printStackTrace();
}catch (Exception e)
{
}
return routes;
}
private List<LatLng> decodePoly(String encoded)
{
List<LatLng> poly = new ArrayList<LatLng>();
int index = 0, len = encoded.length();
int lat = 0, lng = 0;
while (index < len) {
int b, shift = 0, result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
LatLng p = new LatLng((((double) lat / 1E5)),
(((double) lng / 1E5)));
poly.add(p);
}
return poly;
}
}
DirectionActivity
public class DirectionActivity extends FragmentActivity {
GoogleMap map;
ArrayList<LatLng> markerPoints;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.deneme_activity);
markerPoints = new ArrayList<LatLng>();
map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.haritafragment)).getMap();
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
map.setMyLocationEnabled(true);
map.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng point) {
if(markerPoints.size()>1)
{
markerPoints.clear();
map.clear();
}
markerPoints.add(point);
MarkerOptions options = new MarkerOptions();
options.position(point);
if(markerPoints.size() == 1)
{
options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
}else if(markerPoints.size() == 2)
{
options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
}
map.addMarker(options);
if(markerPoints.size() >= 2)
{
LatLng origin = markerPoints.get(0);
LatLng dest = markerPoints.get(1);
String url = getDirectionsUrl(origin, dest);
DownloadTask downloadTask = new DownloadTask();
downloadTask.execute();
}
}
});
}
private String getDirectionsUrl(LatLng origin,LatLng dest){
// Origin of route
String str_origin = "origin="+origin.latitude+","+origin.longitude;
// Destination of route
String str_dest = "destination="+dest.latitude+","+dest.longitude;
// Sensor enabled
String sensor = "sensor=false";
// Building the parameters to the web service
String parameters = str_origin+"&"+str_dest+"&"+sensor;
// Output format
String output = "json";
String url = "https://maps.googleapis.com/maps/api/directions/"+output+"?"+parameters;
return url;
}
private String downloadUrl(String strUrl) throws IOException, IOException {
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try{
URL url = new URL(strUrl);
urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while( ( line = br.readLine()) != null){
sb.append(line);
}
data = sb.toString();
br.close();
}catch(Exception e){
Log.d("Exception while downloading url", e.toString());
}finally{
iStream.close();
urlConnection.disconnect();
}
return data;
}
// Fetches data from url passed
private class DownloadTask extends AsyncTask<String, Void, String> {
// Downloading data in non-ui thread
#Override
protected String doInBackground(String... url) {
// For storing data from web service
String data = "";
try{
// Fetching the data from web service
data = downloadUrl(url[0]);
}catch(Exception e){
Log.d("Background Task",e.toString());
}
return data;
}
// Executes in UI thread, after the execution of
// doInBackground()
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
ParserTask parserTask = new ParserTask();
// Invokes the thread for parsing the JSON data
parserTask.execute(result);
}
}
private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String,String>>>>{
#Override
protected List<List<HashMap<String, String>>> doInBackground(String... jsonData) {
JSONObject jObject;
List<List<HashMap<String, String>>> routes = null;
try{
jObject = new JSONObject(jsonData[0]);
DirectionsJSONParser parser = new DirectionsJSONParser();
// Starts parsing data
routes = parser.parse(jObject);
}catch(Exception e){
e.printStackTrace();
}
return routes;
}
#Override
protected void onPostExecute(List<List<HashMap<String, String>>> result) {
ArrayList<LatLng> points = null;
PolylineOptions lineOptions = null;
MarkerOptions markerOptions = new MarkerOptions();
// Traversing through all the routes
for(int i=0;i<result.size();i++){
points = new ArrayList<LatLng>();
lineOptions = new PolylineOptions();
// Fetching i-th route
List<HashMap<String, String>> path = result.get(i);
// Fetching all the points in i-th route
for(int j=0;j<path.size();j++){
HashMap<String,String> point = path.get(j);
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
points.add(position);
}
// Adding all the points in the route to LineOptions
lineOptions.addAll(points);
lineOptions.width(2);
lineOptions.color(Color.RED);
}
// Drawing polyline in the Google Map for the i-th route
map.addPolyline(lineOptions);
}
}
}
and ERROR
04-07 05:59:35.517 19387-19387/com.example.mapdemo E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.mapdemo, PID: 19387
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
at com.example.mapdemo.DirectionActivity$ParserTask.onPostExecute(DirectionActivity.java:215)
at com.example.mapdemo.DirectionActivity$ParserTask.onPostExecute(DirectionActivity.java:189)
at android.os.AsyncTask.finish(AsyncTask.java:636)
at android.os.AsyncTask.access$500(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:653)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
You are not passing url in DownloadTask. Try something like below
downloadTask.execute(url);
I use the MapsActivity class in this project. On my map you can see many markers. I have many known locations, but in my code I just display two locations for example.
I don't understand how to use the direction API and JSON. How can I display the route, distance, and travelling time from my current location (changing) to a known location (constant)?
public class MapsActivity extends FragmentActivity {
private GoogleMap mMap; // Might be null if Google Play services APK is not available.
private Map<Marker, Class<?>> allMarkersMap = new HashMap<Marker, Class<?>>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
setUpMapIfNeeded();
}
private void setUpMap() {
Marker marker1 = mMap.addMarker(new MarkerOptions()
.position(new LatLng(14.608177, 120.967422))
.title("Sample2")
.snippet("zzzzzzz"));
allMarkersMap.put(marker1, MainActivity.class);
Marker marker2 = mMap.addMarker(new MarkerOptions()
.position(new LatLng(14.611335, 120.962160))
.title("Sample1")
.snippet("sssssss"));
allMarkersMap.put(marker2, MainActivity2Activity.class);
mMap.setMyLocationEnabled(true);
mMap.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker marker) {
Class<?> cls = allMarkersMap.get(marker);
Intent intent = new Intent(MapsActivity.this, cls);
startActivity(intent);
}
});
}
Have a look at this tutorial:
Drawing driving route directions between two locations using Google Directions in Google Map Android API V2
It shows how to draw a route map between two points, calculate distance and travel time.
If you are having problems in following the tutorial, download the Android Studio sample project from the link below:
MapDemo.zip
public class DirectionsJSONParser {
/** Receives a JSONObject and returns a list of lists containing latitude and longitude */
public List<List<HashMap<String,String>>> parse(JSONObject jObject){
List<List<HashMap<String, String>>> routes = new ArrayList<List<HashMap<String,String>>>() ;
JSONArray jRoutes = null;
JSONArray jLegs = null;
JSONArray jSteps = null;
try {
jRoutes = jObject.getJSONArray("routes");
/** Traversing all routes */
for(int i=0;i<jRoutes.length();i++){
jLegs = ( (JSONObject)jRoutes.get(i)).getJSONArray("legs");
List path = new ArrayList<HashMap<String, String>>();
/** Traversing all legs */
for(int j=0;j<jLegs.length();j++){
jSteps = ( (JSONObject)jLegs.get(j)).getJSONArray("steps");
/** Traversing all steps */
for(int k=0;k<jSteps.length();k++){
String polyline = "";
polyline = (String)((JSONObject)((JSONObject)jSteps.get(k)).get("polyline")).get("points");
List<LatLng> list = decodePoly(polyline);
/** Traversing all points */
for(int l=0;l<list.size();l++){
HashMap<String, String> hm = new HashMap<String, String>();
hm.put("lat", Double.toString(((LatLng)list.get(l)).latitude) );
hm.put("lng", Double.toString(((LatLng)list.get(l)).longitude) );
path.add(hm);
}
}
routes.add(path);
}
}
} catch (JSONException e) {
e.printStackTrace();
}catch (Exception e){
}
return routes;
}
/**
* Method to decode polyline points
* Courtesy : http://jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java
* */
private List<LatLng> decodePoly(String encoded) {
List<LatLng> poly = new ArrayList<LatLng>();
int index = 0, len = encoded.length();
int lat = 0, lng = 0;
while (index < len) {
int b, shift = 0, result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
LatLng p = new LatLng((((double) lat / 1E5)),
(((double) lng / 1E5)));
poly.add(p);
}
return poly;
}
}
MainActivity.Java
public class MainActivity extends FragmentActivity {
GoogleMap map;
ArrayList<LatLng> markerPoints;
TextView tvDistanceDuration;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvDistanceDuration = (TextView) findViewById(R.id.tv_distance_time);
// Initializing
markerPoints = new ArrayList<LatLng>();
// Getting reference to SupportMapFragment of the activity_main
SupportMapFragment fm = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
// Getting Map for the SupportMapFragment
map = fm.getMap();
// Enable MyLocation Button in the Map
map.setMyLocationEnabled(true);
// Setting onclick event listener for the map
map.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng point) {
// Already two locations
if (markerPoints.size() > 1) {
markerPoints.clear();
map.clear();
}
// Adding new item to the ArrayList
markerPoints.add(point);
// Creating MarkerOptions
MarkerOptions options = new MarkerOptions();
// Setting the position of the marker
options.position(point);
/**
* For the start location, the color of marker is GREEN and
* for the end location, the color of marker is RED.
*/
if (markerPoints.size() == 1) {
options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
} else if (markerPoints.size() == 2) {
options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
}
// Add new marker to the Google Map Android API V2
map.addMarker(options);
// Checks, whether start and end locations are captured
if (markerPoints.size() >= 2) {
LatLng origin = markerPoints.get(0);
LatLng dest = markerPoints.get(1);
// Getting URL to the Google Directions API
String url = getDirectionsUrl(origin, dest);
DownloadTask downloadTask = new DownloadTask();
// Start downloading json data from Google Directions API
downloadTask.execute(url);
}
}
});
}
private String getDirectionsUrl(LatLng origin, LatLng dest) {
// Origin of route
String str_origin = "origin=" + origin.latitude + "," + origin.longitude;
// Destination of route
String str_dest = "destination=" + dest.latitude + "," + dest.longitude;
// Sensor enabled
String sensor = "sensor=false";
// Building the parameters to the web service
String parameters = str_origin + "&" + str_dest + "&" + sensor;
// Output format
String output = "json";
// Building the url to the web service
String url = "https://maps.googleapis.com/maps/api/directions/" + output + "?" + parameters;
return url;
}
/**
* A method to download json data from url
*/
private String downloadUrl(String strUrl) throws IOException {
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try {
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line);
}
data = sb.toString();
br.close();
} catch (Exception e) {
Log.d("Exception while downloading url", e.toString());
} finally {
iStream.close();
urlConnection.disconnect();
}
return data;
}
// Fetches data from url passed
private class DownloadTask extends AsyncTask<String, Void, String> {
// Downloading data in non-ui thread
#Override
protected String doInBackground(String... url) {
// For storing data from web service
String data = "";
try {
// Fetching the data from web service
data = downloadUrl(url[0]);
} catch (Exception e) {
Log.d("Background Task", e.toString());
}
return data;
}
// Executes in UI thread, after the execution of
// doInBackground()
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
ParserTask parserTask = new ParserTask();
// Invokes the thread for parsing the JSON data
parserTask.execute(result);
}
}
/**
* A class to parse the Google Places in JSON format
*/
private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {
// Parsing the data in non-ui thread
#Override
protected List<List<HashMap<String, String>>> doInBackground(String... jsonData) {
JSONObject jObject;
List<List<HashMap<String, String>>> routes = null;
try {
jObject = new JSONObject(jsonData[0]);
DirectionsJSONParser parser = new DirectionsJSONParser();
// Starts parsing data
routes = parser.parse(jObject);
} catch (Exception e) {
e.printStackTrace();
}
return routes;
}
// Executes in UI thread, after the parsing process
#Override
protected void onPostExecute(List<List<HashMap<String, String>>> result) {
ArrayList<LatLng> points = null;
PolylineOptions lineOptions = null;
MarkerOptions markerOptions = new MarkerOptions();
String distance = "";
String duration = "";
if (result.size() < 1) {
Toast.makeText(getBaseContext(), "No Points", Toast.LENGTH_SHORT).show();
return;
}
// Traversing through all the routes
for (int i = 0; i < result.size(); i++) {
points = new ArrayList<LatLng>();
lineOptions = new PolylineOptions();
// Fetching i-th route
List<HashMap<String, String>> path = result.get(i);
// Fetching all the points in i-th route
for (int j = 0; j < path.size(); j++) {
HashMap<String, String> point = path.get(j);
if (j == 0) { // Get distance from the list
distance = (String) point.get("distance");
continue;
} else if (j == 1) { // Get duration from the list
duration = (String) point.get("duration");
continue;
}
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
points.add(position);
}
// Adding all the points in the route to LineOptions
lineOptions.addAll(points);
lineOptions.width(2);
lineOptions.color(Color.RED);
}
tvDistanceDuration.setText("Distance:" + distance + ", Duration:" + duration);
// Drawing polyline in the Google Map for the i-th route
map.addPolyline(lineOptions);
}
}
The code is for drawing the distance between any two points, start is the current location and the other is a location stored in the SQLite db.
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback ,GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private GoogleMap mMap;
ArrayList<LatLng> MarkerPoints;
GoogleApiClient mGoogleApiClient;
Location mLastLocation;
Marker mCurrLocationMarker;
LocationRequest mLocationRequest;
String lat, lon;
LatLng start;
LatLng dest;
String destlat;
String destlon;
public void setLat(String lat) {
this.lat = lat;
}
public void setLon(String lon) {
this.lon = lon;
}
public void setDestlat(String destlat) {
this.destlat = destlat;
}
public void setDestlon(String destlon) {
this.destlon = destlon;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkLocationPermission();
}
// Initializing
MarkerPoints = new ArrayList<>();
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
Log.d("OnmapREady fired", "fired");
//Initialize Google Play Services
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
}
else {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
}
public void mapOperations(){
Log.d("Map operations called","Hope");
LatLng point = start;
// Already two locations
if (MarkerPoints.size() > 1) {
MarkerPoints.clear();
mMap.clear();
}
// Adding new item to the ArrayList
MarkerPoints.add(start);
// adding destination from database
LocationsDB db = new LocationsDB(MapsActivity.this);
String loc = db.getTermValues();
Log.d("location from db",loc);
String[] separated = loc.split(" ");
//try {
Double lt = Double.parseDouble(separated[0]);
Double ln = Double.parseDouble(separated[1]);
dest = new LatLng(lt,ln);
MarkerPoints.add(dest);
//}
//catch(Exception e) {
// Log.d("Wrong target location", e.toString());
//}
// Creating MarkerOptions
MarkerOptions options = new MarkerOptions();
// Setting the position of the marker
options.position(start);
options.position(dest);
/**
* For the start location, the color of marker is GREEN and
* for the end location, the color of marker is RED.
*/
if (MarkerPoints.size() == 1) {
options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
} else if (MarkerPoints.size() == 2) {
options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
}
// Add new marker to the Google Map Android API V2
mMap.addMarker(options);
// Checks, whether start and end locations are captured
if (MarkerPoints.size() >= 2) {
LatLng origin = MarkerPoints.get(0);
LatLng dest = MarkerPoints.get(1);
// Getting URL to the Google Directions API
String url = getUrl(origin, dest);
Log.d("onMapClick", url.toString());
FetchUrl FetchUrl = new FetchUrl();
// Start downloading json data from Google Directions API
FetchUrl.execute(url);
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLng(origin));
mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
}
}
private String getUrl(LatLng origin, LatLng dest) {
// Origin of route
String str_origin = "origin=" + origin.latitude + "," + origin.longitude;
// Destination of route
String str_dest = "destination=" + dest.latitude + "," + dest.longitude;
// Sensor enabled
String sensor = "sensor=false";
// Building the parameters to the web service
String parameters = str_origin + "&" + str_dest + "&" + sensor;
// Output format
String output = "json";
// Building the url to the web service
String url = "https://maps.googleapis.com/maps/api/directions/" + output + "?" + parameters;
return url;
}
/**
* A method to download json data from url
*/
private String downloadUrl(String strUrl) throws IOException {
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try {
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line);
}
data = sb.toString();
Log.d("downloadUrl", data.toString());
br.close();
} catch (Exception e) {
Log.d("Exception", e.toString());
} finally {
iStream.close();
urlConnection.disconnect();
}
return data;
}
// Fetches data from url passed
private class FetchUrl extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... url) {
// For storing data from web service
String data = "";
try {
// Fetching the data from web service
data = downloadUrl(url[0]);
Log.d("Background Task data", data.toString());
} catch (Exception e) {
Log.d("Background Task", e.toString());
}
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
ParserTask parserTask = new ParserTask();
// Invokes the thread for parsing the JSON data
parserTask.execute(result);
}
}
/**
* A class to parse the Google Places in JSON format
*/
private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {
// Parsing the data in non-ui thread
#Override
protected List<List<HashMap<String, String>>> doInBackground(String... jsonData) {
JSONObject jObject;
List<List<HashMap<String, String>>> routes = null;
try {
jObject = new JSONObject(jsonData[0]);
Log.d("ParserTask",jsonData[0].toString());
DataParser parser = new DataParser();
Log.d("ParserTask", parser.toString());
// Starts parsing data
routes = parser.parse(jObject);
Log.d("ParserTask","Executing routes");
Log.d("ParserTask",routes.toString());
} catch (Exception e) {
Log.d("ParserTask",e.toString());
e.printStackTrace();
}
return routes;
}
// Executes in UI thread, after the parsing process
#Override
protected void onPostExecute(List<List<HashMap<String, String>>> result) {
ArrayList<LatLng> points;
PolylineOptions lineOptions = null;
// Traversing through all the routes
for (int i = 0; i < result.size(); i++) {
points = new ArrayList<>();
lineOptions = new PolylineOptions();
// Fetching i-th route
List<HashMap<String, String>> path = result.get(i);
// Fetching all the points in i-th route
for (int j = 0; j < path.size(); j++) {
HashMap<String, String> point = path.get(j);
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
points.add(position);
}
// Adding all the points in the route to LineOptions
lineOptions.addAll(points);
lineOptions.width(10);
lineOptions.color(Color.RED);
Log.d("onPostExecute","onPostExecute lineoptions decoded");
}
// Drawing polyline in the Google Map for the i-th route
if(lineOptions != null) {
mMap.addPolyline(lineOptions);
}
else {
Log.d("onPostExecute","without Polylines drawn");
}
}
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
#Override
public void onConnected(Bundle bundle) {
Log.d("OnConnected fired","fired");
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
lat = String.valueOf(mLastLocation.getLatitude());
lon = String.valueOf(mLastLocation.getLongitude());
start = new LatLng(mLastLocation.getLatitude(),mLastLocation.getLongitude());
Toast.makeText(this,"Connected",Toast.LENGTH_SHORT).show();
mapOperations();
}
else{
Toast.makeText(this,"Failed",Toast.LENGTH_LONG).show();
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onLocationChanged(Location location) {
mLastLocation = location;
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
//Place current location marker
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("Current Position");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mCurrLocationMarker = mMap.addMarker(markerOptions);
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
//stop location updates
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
public boolean checkLocationPermission(){
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Asking user if explanation is needed
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
return false;
} else {
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted. Do the
// contacts-related task you need to do.
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
if (mGoogleApiClient == null) {
buildGoogleApiClient();
}
mMap.setMyLocationEnabled(true);
}
} else {
// Permission denied, Disable the functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
}
return;
}
// other 'case' lines to check for other permissions this app might request.
// You can add here other case statements according to your requirement.
}
}
#Override
protected void onDestroy() {
super.onDestroy();
}
}
This is the code for finding and drawing the routes between the points.
public class DataParser {
/** Receives a JSONObject and returns a list of lists containing latitude and longitude */
public List<List<HashMap<String,String>>> parse(JSONObject jObject){
List<List<HashMap<String, String>>> routes = new ArrayList<>() ;
JSONArray jRoutes;
JSONArray jLegs;
JSONArray jSteps;
try {
jRoutes = jObject.getJSONArray("routes");
/** Traversing all routes */
for(int i=0;i<jRoutes.length();i++){
jLegs = ( (JSONObject)jRoutes.get(i)).getJSONArray("legs");
List path = new ArrayList<>();
/** Traversing all legs */
for(int j=0;j<jLegs.length();j++){
jSteps = ( (JSONObject)jLegs.get(j)).getJSONArray("steps");
/** Traversing all steps */
for(int k=0;k<jSteps.length();k++){
String polyline = "";
polyline = (String)((JSONObject)((JSONObject)jSteps.get(k)).get("polyline")).get("points");
List<LatLng> list = decodePoly(polyline);
/** Traversing all points */
for(int l=0;l<list.size();l++){
HashMap<String, String> hm = new HashMap<>();
hm.put("lat", Double.toString((list.get(l)).latitude) );
hm.put("lng", Double.toString((list.get(l)).longitude) );
path.add(hm);
}
}
routes.add(path);
}
}
} catch (JSONException e) {
e.printStackTrace();
}catch (Exception e){
}
return routes;
}
/**
* Method to decode polyline points
* Courtesy : http://jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java
* */
private List<LatLng> decodePoly(String encoded) {
List<LatLng> poly = new ArrayList<>();
int index = 0, len = encoded.length();
int lat = 0, lng = 0;
while (index < len) {
int b, shift = 0, result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
LatLng p = new LatLng((((double) lat / 1E5)),
(((double) lng / 1E5)));
poly.add(p);
}
return poly;
}
}
I'm trying to draw a route between the current location and another point. I wrote code which can check the current location and also put the point on the map on a map click. At the moment, the program is working perfectly,
but I want to draw another route between the current location and a new point( point witch I added map on Map click listener).
My code is below, does anyone know how I can to add this logic on my code?
public class GPS extends Activity implements
OnMyLocationChangeListener,OnMapClickListener,
OnMapLongClickListener, OnMarkerDragListener {
final int RQS_GooglePlayServices = 1;
private GoogleMap myMap;
Circle myCircle;
Location myLocation;
TextView tvLocInfo, GPSLocation;
LatLng latLng;
boolean markerClicked;
ArrayList<LatLng> markerPoints;
Polygon polygon;
public Button btnline;
double Clicklatitude, Clicklongitude, latitude, longitude;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.gps);
markerPoints=new ArrayList<LatLng>();
btnline = (Button) findViewById(R.id.button1);
tvLocInfo = (TextView) findViewById(R.id.GpsTxt);
GPSLocation = (TextView) findViewById(R.id.GPSLocation);
FragmentManager myFragmentManager = getFragmentManager();
MapFragment myMapFragment = (MapFragment) myFragmentManager
.findFragmentById(R.id.GpsMap);
myMap = myMapFragment.getMap();
myMap.setMyLocationEnabled(true);
myMap.setOnMyLocationChangeListener(this);
myMap.setOnMapClickListener(this);
myMap.setOnMapLongClickListener(this);
myMap.setOnMarkerDragListener(this);
myMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
myMap.setMyLocationEnabled(true);
myMap.setOnMyLocationChangeListener(this);
markerClicked = false;
btnline.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
#Override
protected void onResume() {
super.onResume();
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(getApplicationContext());
if (resultCode == ConnectionResult.SUCCESS) {
Toast.makeText(getApplicationContext(),
"isGooglePlayServicesAvailable SUCCESS", Toast.LENGTH_LONG)
.show();
} else {
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
RQS_GooglePlayServices);
}
}
#Override
public void onMyLocationChange(Location location) {
latitude = location.getLatitude();
// Getting longitude of the current location
longitude = location.getLongitude();
// Creating a LatLng object for the current location
latLng = new LatLng(latitude, longitude);
// Showing the current location in Google Map
myMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
// Zoom in the Google Map
GPSLocation.setText(latitude + " " + longitude);
myMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
LatLng locLatLng = new LatLng(location.getLatitude(),
location.getLongitude());
double accuracy = location.getAccuracy();
if (myCircle == null) {
CircleOptions circleOptions = new CircleOptions().center(locLatLng)
// set center
.radius(accuracy)
// set radius in meters
.fillColor(Color.RED).strokeColor(Color.BLACK)
.strokeWidth(5);
myCircle = myMap.addCircle(circleOptions);
} else {
myCircle.setCenter(locLatLng);
myCircle.setRadius(accuracy);
}
myMap.animateCamera(CameraUpdateFactory.zoomTo(15));
// myMap.animateCamera(CameraUpdateFactory.newLatLng(locLatLng));
}
#Override
public void onMarkerDrag(Marker arg0) {
// TODO Auto-generated method stub
}
#Override
public void onMarkerDragEnd(Marker arg0) {
// TODO Auto-generated method stub
}
#Override
public void onMarkerDragStart(Marker arg0) {
// TODO Auto-generated method stub
}
#Override
public void onMapLongClick(LatLng point) {
}
#Override
public void onMapClick(LatLng point) {
Clicklatitude = point.latitude;
Clicklongitude = point.longitude;
tvLocInfo.setText(Clicklatitude + " " + Clicklongitude);
if (point != null)
myMap.clear();
myMap.addMarker(new MarkerOptions().position(point).draggable(true));
markerClicked = false;
}
}
I want to get a like this result enter link description here
I achieved same thing via this code. This will be some different Code from what you have tried.
First of all Implement your class with this two things
implements OnMapReadyCallback,LocationListener
When you implement OnMapReadyCallback you will get pre-define method called
"OnMapReady"
#Override
public void onMapReady(GoogleMap googleMap) {
destiLati = 40.728634;
destiLong = -73.974956;
mMap = googleMap;
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
mMap.getUiSettings().setZoomControlsEnabled(true);
mMap.getUiSettings().setZoomGesturesEnabled(true);
mMap.getUiSettings().setCompassEnabled(true);
// Add a marker in Destination/Desire point and move the camera
DestinationPoint = new LatLng(destiLati, destiLong);
mMap.addMarker(new MarkerOptions().position(DestinationPoint).title("Destination
Point")
.icon(BitmapDescriptorFactory.fromResource(R.drawable.location)));
//To move camera to Desination Location.
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(DestinationPoint, 10));
//Permission To get Current Location
if (ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) !=
PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mMap.setMyLocationEnabled(true);
}
To get current location I have made one method and when you implement LocationListener
it will give you pre-define method called "onLocationChanged"
private void getLocation() {
try {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5000, 5, this);
}
catch(SecurityException e) {
e.printStackTrace();
}
}
#Override
public void onLocationChanged(Location location) {
//This thing will get User's current location
originLati = location.getLatitude();
originLong = location.getLongitude();
exeTask();
//Log.d(originLati.toString(),"This is the value of orginalati" + originLati.toString() + " " + originLong.toString());
}
To get path between Your current location and destination..
you need to pass data to google API it will write one JSON result
you have to get this result and show it into Polyline(to display path)
private void exeTask(){
String originPl = "origin=" + originLati.toString() + "," + originLong.toString();
String destipl = "destination=" + destiLati.toString() + "," + destiLong.toString();
String sensor = "sensor-false";
String mode = "mode-driving";
String param = originPl + "&" + destipl + "&" + sensor + "&" + mode + "&key='Your_API_KEY'";
final_url = "https://maps.googleapis.com/maps/api/directions/json?" + param;
//Log.d(final_url,"This is the URL which was created");
TaskRequestDirections taskRequestDirections = new TaskRequestDirections();
taskRequestDirections.execute(final_url);
}
private String requestDirection(String reqUrl) throws IOException {
String responseString = "";
InputStream inputStream = null;
HttpURLConnection httpURLConnection = null;
try{
URL url = new URL(reqUrl);
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.connect();
//TO get the in String format response result
inputStream = httpURLConnection.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
StringBuffer stringBuffer = new StringBuffer();
String line = "";
while ((line = bufferedReader.readLine()) != null) {
stringBuffer.append(line);
}
responseString = stringBuffer.toString();
bufferedReader.close();
inputStreamReader.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
inputStream.close();
}
httpURLConnection.disconnect();
}
return responseString;
}
public class TaskRequestDirections extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... strings) {
String responseString = "";
try {
responseString = requestDirection(strings[0]);
} catch (IOException e) {
e.printStackTrace();
}
return responseString;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
//Parse json/ Data will come from here..
TaskParser taskParser = new TaskParser();
taskParser.execute(s);
}
}
public class TaskParser extends AsyncTask<String, Void, List<List<HashMap<String, String>>> > {
#Override
protected List<List<HashMap<String, String>>> doInBackground(String... strings) {
JSONObject jsonObject = null;
List<List<HashMap<String, String>>> routes = null;
try {
jsonObject = new JSONObject(strings[0]);
DirectionsParser directionsParser = new DirectionsParser();
routes = directionsParser.parse(jsonObject);
} catch (JSONException e) {
e.printStackTrace();
}
return routes;
}
#Override
protected void onPostExecute(List<List<HashMap<String, String>>> lists) {
//To get list route and display it into the map
ArrayList points = null;
PolylineOptions polylineOptions = null;
for (List<HashMap<String, String>> path : lists) {
points = new ArrayList();
polylineOptions = new PolylineOptions();
for (HashMap<String, String> point : path) {
double lat = Double.parseDouble(point.get("lat"));
double lon = Double.parseDouble(point.get("lon"));
points.add(new LatLng(lat,lon));
}
polylineOptions.addAll(points);
polylineOptions.width(10);
polylineOptions.color(Color.BLUE);
polylineOptions.geodesic(true);
}
if (polylineOptions!=null) {
mMap.addPolyline(polylineOptions);
} else {
//Toast.makeText(getApplicationContext(), "Direction not found!", Toast.LENGTH_SHORT).show();
}
}
}
And finally call this pre-define Class as it show here to decode polylines and get json array result
public class DirectionsParser {
/**
* Returns a list of lists containing latitude and longitude from a JSONObject
*/
public List<List<HashMap<String, String>>> parse(JSONObject jObject) {
List<List<HashMap<String, String>>> routes = new ArrayList<List<HashMap<String, String>>>();
JSONArray jRoutes = null;
JSONArray jLegs = null;
JSONArray jSteps = null;
try {
jRoutes = jObject.getJSONArray("routes");
// Loop for all routes
for (int i = 0; i < jRoutes.length(); i++) {
jLegs = ((JSONObject) jRoutes.get(i)).getJSONArray("legs");
List path = new ArrayList<HashMap<String, String>>();
//Loop for all legs
for (int j = 0; j < jLegs.length(); j++) {
jSteps = ((JSONObject) jLegs.get(j)).getJSONArray("steps");
//Loop for all steps
for (int k = 0; k < jSteps.length(); k++) {
String polyline = "";
polyline = (String) ((JSONObject) ((JSONObject) jSteps.get(k)).get("polyline")).get("points");
List list = decodePolyline(polyline);
//Loop for all points
for (int l = 0; l < list.size(); l++) {
HashMap<String, String> hm = new HashMap<String, String>();
hm.put("lat", Double.toString(((LatLng) list.get(l)).latitude));
hm.put("lon", Double.toString(((LatLng) list.get(l)).longitude));
path.add(hm);
}
}
routes.add(path);
}
}
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
}
return routes;
}
/**
* Method to decode polyline
* Source : http://jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java
*/
private List decodePolyline(String encoded) {
List poly = new ArrayList();
int index = 0, len = encoded.length();
int lat = 0, lng = 0;
while (index < len) {
int b, shift = 0, result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
LatLng p = new LatLng((((double) lat / 1E5)),
(((double) lng / 1E5)));
poly.add(p);
}
return poly;
}
}
Hope This help :)