Reputation: 561
I got the correct souce and destination latitude and longitude in map but I am able to drwa line between Source and destination but this line is strait line display in map between source and destination marker. Destination Latitide and Destination Longitude are fetch successfully from Server.
But I want to Draw line between source and destination Like this below.
This is Example. Google Map is also Display CurrectPosition of Source and Destination. How can it Possible?
Please Guide me. Please Help me. Thank you.
My Code is,
public class Map extends FragmentActivity {
GoogleMap googleMap;
SupportMapFragment fm;
double myLat = 23.0137759;
double destLat = 0.0;
double myLng = 72.5158836;
double destLng = 0.0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.navigate_to_me_map);
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
}
Intent intent = getIntent();
destLat = intent.getDoubleExtra("latitude", 0.0);
destLng = intent.getDoubleExtra("longitude", 0.0);
int status = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(getBaseContext());
// Showing status
if (status != ConnectionResult.SUCCESS) { // Google Play Services
int requestCode = 10;
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status,
this, requestCode);
dialog.show();
} else {
SupportMapFragment supportMapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.fullmap);
googleMap = supportMapFragment.getMap();
googleMap.setMyLocationEnabled(true);
}
googleMap
.setOnMyLocationChangeListener(new OnMyLocationChangeListener() {
public void onMyLocationChange(Location location) {
// TODO Auto-generated method stub
myLat = location.getLatitude();
myLng = location.getLongitude();
}
});
drawRoutePath(strAddressOne);
}
}
private void drawRoutePath(String searchText) {
try {
// find current address latlong and true than draw route
// between to points or current loction and search
// address
googleMap.clear();
if (myLat != 0 && myLng != 0) {
LatLng origin = new LatLng(myLat, myLng);
drawMarker(origin);
LatLng dest = new LatLng(destLat, destLng);
drawMarker(dest);
Polyline line = googleMap.addPolyline(new PolylineOptions()
.add(origin, dest).width(5).color(Color.RED));
} else {
Toast.makeText(getApplicationContext(),
"Current Location does not found",
Toast.LENGTH_SHORT).show();
}
}
} catch (Exception e) {
// TODO: handle exception
Log.e("Second ", "drawRoutePath errro " + e.toString());
}
}
private void drawMarker(LatLng point) {
// Creating an instance of MarkerOptions
MarkerOptions markerOptions = new MarkerOptions();
// Setting latitude and longitude for the marker
markerOptions.position(point);
// Adding marker on the Google Map
googleMap.addMarker(new MarkerOptions().position(point).visible(true))
.showInfoWindow();
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(
point.latitude, point.longitude), 6f));
}
}
Upvotes: 0
Views: 7092
Reputation: 1899
Here's the source code to draw a route between the source and destination :
public class MapActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private SupportMapFragment mapFragment;
private GoogleMap map;
private GoogleApiClient mGoogleApiClient;
ArrayList markerPoints;
private LocationRequest mLocationRequest;
private long UPDATE_INTERVAL = 15000; /* 15 secs */
private long FASTEST_INTERVAL = 5000; /* 5 secs */
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
// Marker marker;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!isGooglePlayServicesAvailable()) {
finish();
}
setContentView(R.layout.activity_map);
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
getSupportActionBar().setDisplayShowCustomEnabled(true);
getSupportActionBar().setCustomView(R.layout.custom_actionbar_maps);
markerPoints = new ArrayList();
mapFragment = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map));
if (mapFragment != null) {
mapFragment.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(GoogleMap map) {
loadMap(map);
}
});
} else {
Toast.makeText(this, "Error - Map Fragment was null!!", Toast.LENGTH_SHORT).show();
}
}
protected void loadMap(GoogleMap googleMap) {
map = googleMap;
if (map != null) {
// Map is ready
Toast.makeText(this, "Map Fragment was loaded properly!", Toast.LENGTH_SHORT).show();
map.setMyLocationEnabled(true);
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 = (LatLng) markerPoints.get(0);
LatLng dest = (LatLng) 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);
}
}
});
// Now that map has loaded, let's get our location!
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
connectClient();
} else {
Toast.makeText(this, "Error - Map was null!!", Toast.LENGTH_SHORT).show();
}
}
protected void connectClient() {
// Connect the client.
if (isGooglePlayServicesAvailable() && mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
/*
* Called when the Activity becomes visible.
*/
@Override
protected void onStart() {
super.onStart();
connectClient();
}
/*
* Called when the Activity is no longer visible.
*/
@Override
protected void onStop() {
// Disconnecting the client invalidates it.
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
super.onStop();
}
/*
* Handle results returned to the FragmentActivity by Google Play services
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Decide what to do based on the original request code
switch (requestCode) {
case CONNECTION_FAILURE_RESOLUTION_REQUEST:
/*
* If the result code is Activity.RESULT_OK, try to connect again
*/
switch (resultCode) {
case Activity.RESULT_OK:
mGoogleApiClient.connect();
break;
}
}
}
// Fetches data from url passed
private boolean isGooglePlayServicesAvailable() {
// Check that Google Play services is available
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
// In debug mode, log the status
Log.d("Location Updates", "Google Play services is available.");
return true;
} else {
// Get the error dialog from Google Play services
Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(resultCode, this,
CONNECTION_FAILURE_RESOLUTION_REQUEST);
// If Google Play services can provide an error dialog
if (errorDialog != null) {
// Create a new DialogFragment for the error dialog
ErrorDialogFragment errorFragment = new ErrorDialogFragment();
errorFragment.setDialog(errorDialog);
errorFragment.show(getSupportFragmentManager(), "Location Updates");
}
return false;
}
}
/*
* Called by Location Services when the request to connect the client
* finishes successfully. At this point, you can request the current
* location or start periodic updates
*/
@Override
public void onConnected(Bundle dataBundle) {
// Display the connection status
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (location != null) {
Toast.makeText(this, "GPS location was found!", Toast.LENGTH_SHORT).show();
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 16);
map.animateCamera(cameraUpdate);
//marker = map.addMarker(new MarkerOptions().position(latLng).icon(BitmapDescriptorFactory.fromResource(R.drawable.vehicle_marker)).flat(true).anchor(0.5f,0.5f));
startLocationUpdates();
} else {
Toast.makeText(this, "Current location was null, enable GPS on emulator!", Toast.LENGTH_SHORT).show();
}
}
protected void startLocationUpdates() {
mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
mLocationRequest, this);
}
public void onLocationChanged(Location location) {
// Report to the UI that the location was updated
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
/* if(marker == null){
*//* marker.remove();*//*
marker = map.addMarker(new MarkerOptions().position(latLng).icon(BitmapDescriptorFactory.fromResource(R.drawable.vehicle_marker)));
}
marker.setPosition(latLng);
*/
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 16);
map.animateCamera(cameraUpdate);
String msg = "Updated Location: " +
Double.toString(location.getLatitude()) + "," +
Double.toString(location.getLongitude());
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
/*
* Called by Location Services if the connection to the location client
* drops because of an error.
*/
@Override
public void onConnectionSuspended(int i) {
if (i == CAUSE_SERVICE_DISCONNECTED) {
Toast.makeText(this, "Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
} else if (i == CAUSE_NETWORK_LOST) {
Toast.makeText(this, "Network lost. Please re-connect.", Toast.LENGTH_SHORT).show();
}
}
/*
* Called by Location Services if the attempt to Location Services fails.
*/
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
/*
* Google Play services can resolve some errors it detects. If the error
* has a resolution, try sending an Intent to start a Google Play
* services activity that can resolve error.
*/
if (connectionResult.hasResolution()) {
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(this,
CONNECTION_FAILURE_RESOLUTION_REQUEST);
/*
* Thrown if Google Play services canceled the original
* PendingIntent
*/
} catch (IntentSender.SendIntentException e) {
// Log the error
e.printStackTrace();
}
} else {
Toast.makeText(getApplicationContext(),
"Sorry. Location services not available to you", Toast.LENGTH_LONG).show();
}
}
// Define a DialogFragment that displays the error dialog
public static class ErrorDialogFragment extends DialogFragment {
// Global field to contain the error dialog
private Dialog mDialog;
// Default constructor. Sets the dialog field to null
public ErrorDialogFragment() {
super();
mDialog = null;
}
// Set the dialog to display
public void setDialog(Dialog dialog) {
mDialog = dialog;
}
// Return a Dialog to the DialogFragment.
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return mDialog;
}
}
// 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 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();
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(12);
lineOptions.color(Color.RED);
lineOptions.geodesic(true);
}
// Drawing polyline in the Google Map for the i-th route
map.addPolyline(lineOptions);
}
}
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;
}
}
DirectionsJSONParser.java is given below :
import com.google.android.gms.maps.model.LatLng;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
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 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 decodePoly(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;
}
}
Upvotes: 1