I have a google maps project where you can type in an address and you will get a marker displaying, the address, the duration (travelling by car), and the distance from the users location to point B. It works great!
My problem though, is that whenever I put a location that is not accessed by a car, the app crashes. I'm not looking for anything major, and I do not need anything else than the driving distance, so for the user to just be told that you can't drive here, is just fine for me.
I'm using JSONParsing to parse the address after an UrlRequest. legs, distance, duration, end_address, end-lat, end-lng, are the values that I'm fetching from this file:
legs: [
{
distance: {
text: "547 km",
value: 547015
},
duration: {
text: "5 h 23 min",
value: 19361
},
end_address: "Montreal, Quebec, Kanada",
end_location: {
lat: 45.5017123,
lng: -73.5672184
},
start_address: "Toronto, Ontario, Kanada",
start_location: {
lat: 43.6533096,
lng: -79.3827656
},
steps: [
{
distance: {
text: "0,3 km",
value: 280
},
duration: {
text: "1 min",
value: 66
},
end_location: {
lat: 43.6557259,
lng: -79.3837337
},
html_instructions: "",
polyline: {
points: "e`miGhmocNs#Rm#N]JmA^KBcAZSFWHe#Nk#Pa#Le#L"
},
start_location: {
lat: 43.6533096,
lng: -79.3827656
},
travel_mode: "DRIVING"
},
So my question is, does anyone have any suggestions as to what kind of conditions I should have for this kind of method to run.
if(!=travel_mode: "DRIVING")
{
Toast.makeText(MapsActivity.this, "You cannot drive there",
Toast.LENGTH:SHORT).show();
}
else
{
execute code;
}
Fetch the travel_mode and have it as a condition somehow? Thank you in advance!
My whole code,
The main class, when you press a button the address will be converted
private void init() {
searchText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
dataTransfer = new Object[2];
url = getDirectionsUrl();
GetDistances getDistances = new GetDistances();
dataTransfer[0] = mMap;
dataTransfer[1] = url;
getDistances.execute(dataTransfer);
return false;
}
});
Building the URL...
private String getDirectionsUrl()
{
//WORKS
//https://maps.googleapis.com/maps/api/directions/json?origin=Toronto&destination=Montreal&key=API_KEY"
StringBuilder googleDirectionsUrl = new StringBuilder("https://maps.googleapis.com/maps/api/directions/json?");
//Possible two textfields with origin being another textfield
googleDirectionsUrl.append("origin="+myLat+","+myLng);
googleDirectionsUrl.append("&destination="+searchText.getText().toString());
googleDirectionsUrl.append("&key="+"API_KEY");
return googleDirectionsUrl.toString();
}
Sending the Url to be parsed...
public class DataParser {
private HashMap<String, String> getDuration(JSONArray googleDirectionsJson) {
HashMap<String, String> googleDirectionsMap = new HashMap<>();
String duration = "";
String distance = "";
String title = "";
Log.d("json response", googleDirectionsJson.toString());
try {
duration = googleDirectionsJson.getJSONObject(0).getJSONObject("duration").getString("text");
distance = googleDirectionsJson.getJSONObject(0).getJSONObject("distance").getString("text");
title = googleDirectionsJson.getJSONObject(0).getString("end_address");
googleDirectionsMap.put("duration", duration);
googleDirectionsMap.put("distance", distance);
googleDirectionsMap.put("end_address", title);
} catch (JSONException e) {
e.printStackTrace();
}
return googleDirectionsMap;
}
public HashMap<String, String> parseDirections(String jsonData) {
JSONArray jsonArray = null;
JSONObject jsonObject;
try {
jsonObject = new JSONObject(jsonData);
jsonArray = jsonObject.getJSONArray("routes").getJSONObject(0).getJSONArray("legs");
} catch (JSONException e) {
e.printStackTrace();
}
return getDuration(jsonArray);
}
private HashMap<String, Double> getLatLng(JSONArray googleLatLngJson) {
HashMap<String, Double> googleLatLngMap = new HashMap<>();
Double latitude = 0.0;
Double longitude = 0.0;
try {
latitude = googleLatLngJson.getJSONObject(0).getJSONObject("end_location").getDouble("lat");
longitude = googleLatLngJson.getJSONObject(0).getJSONObject("end_location").getDouble("lng");
googleLatLngMap.put("lat", latitude);
googleLatLngMap.put("lng", longitude);
Log.d("json response", googleLatLngMap.toString());
} catch (JSONException e) {
e.printStackTrace();
}
return googleLatLngMap;
}
public HashMap<String, Double> parseLatLng(String jsonData) {
JSONArray jsonArray = null;
JSONObject jsonObject;
try {
jsonObject = new JSONObject(jsonData);
jsonArray = jsonObject.getJSONArray("routes").getJSONObject(0).getJSONArray("legs");
} catch (JSONException e) {
e.printStackTrace();
}
return getLatLng(jsonArray);
}
}
Getting the values from the JSONparsed hashmaps and putting them into new hashmaps to add the markers with their values
public class GetDistances extends AsyncTask<Object, String, String>{
GoogleMap mMap;
String url;
String googleDirectionsData;
String duration, distance;
Double latitude, longitude;
LatLng latLng;
String title;
#Override
protected String doInBackground(Object... objects) {
mMap = (GoogleMap)objects[0];
url = (String)objects[1];
HttpHandler httpHandler = new HttpHandler();
try
{
googleDirectionsData = httpHandler.readUrl(url);
}
catch(IOException e)
{
e.printStackTrace();
}
return googleDirectionsData;
}
#Override
protected void onPostExecute(String s)
{
DataParser parser = new DataParser();
HashMap<String, String> directionsList = null;
directionsList = parser.parseDirections(s);
duration = directionsList.get("duration");
distance = directionsList.get("distance");
title = directionsList.get("end_address");
HashMap<String, Double> positionList = null;
positionList = parser.parseLatLng(s);
latitude = positionList.get("lat");
longitude = positionList.get("lng");
latLng = (new LatLng(latitude, longitude));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 13));
MarkerOptions markerOptions = new MarkerOptions()
.position(latLng)
.draggable(true)
.title(title);
markerOptions.snippet("Distance: " + distance + ", " + "Duration: " + duration);
mMap.addMarker(markerOptions);
}
}
"API_KEY" - is my actual key, just trying to keep it private.
SOLVED
I just made a try catch in the onPostExecute method, and it solved the crash.
public class GetDestination extends AsyncTask<Object, String, String>{
GoogleMap mMap;
String url;
String googleDirectionsData;
String duration, distance;
Double latitude, longitude;
LatLng latLng;
String title;
private static Context context;
public GetDestination(Context c){
context = c;
}
public static void showToast(){
Toast.makeText(context, "You can't drive through the oceans!", Toast.LENGTH_LONG).show();
}
#Override
protected String doInBackground(Object... objects) {
mMap = (GoogleMap)objects[0];
url = (String)objects[1];
HttpHandler httpHandler = new HttpHandler();
try
{
googleDirectionsData = httpHandler.readUrl(url);
}
catch(IOException e)
{
e.printStackTrace();
}
return googleDirectionsData;
}
#Override
protected void onPostExecute(String s)
{
try {
DataParser parser = new DataParser();
HashMap<String, String> directionsList = null;
directionsList = parser.parseDirections(s);
duration = directionsList.get("duration");
distance = directionsList.get("distance");
title = directionsList.get("start_address");
HashMap<String, Double> positionList = null;
positionList = parser.parseLatLng(s);
latitude = positionList.get("lat");
longitude = positionList.get("lng");
latLng = (new LatLng(latitude, longitude));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 13));
MarkerOptions markerOptions = new MarkerOptions()
.position(latLng)
.draggable(true)
.title(title);
markerOptions.snippet("Distance: " + distance + ", " + "Duration: " + duration);
mMap.addMarker(markerOptions);
}
catch (Exception e)
{
showToast();
e.printStackTrace();
}
}
}
Be sure to pass in the context in the Mainactivity class,
searchText1.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
dataTransfer = new Object[2];
url = getDirectionsUrl();
GetDestination getDestination = new GetDestination(MapsActivity.this);
dataTransfer[0] = mMap;
dataTransfer[1] = url;
getDestination.execute(dataTransfer);
return false;
}
});
It's great that you have solved the problem yourself. Congrats.
But the better approach will be to put a log in the response and check the difference between the two responses i.e drivable and not drivable.
In this way, you could read the exact response and based on the response you can show different messages to the user.
And of course, a try, catch could be there to handle any kind of exception.
Hope this Helps.
Related
Here IS My Code example which works fine for "Schools,Restaurants" but not working for Filling stations..I think the space is the problem..
case R.id.B_restaurant:
mMap.clear();
dataTransfer = new Object[2];
String restaurant = "restaurant";
url = getUrl(latitude, longitude, restaurant);
getNearbyPlacesData = new com.example.husnainbutt.driveescuev22.**GetNearbyPlacesData();**
dataTransfer[0] = mMap;
dataTransfer[1] = url;
getNearbyPlacesData.execute(dataTransfer);
Toast.makeText(MapsActivity.this, "Showing Nearby Restaurants", Toast.LENGTH_LONG).show();
break;
And GetNearbyplaces is following below It seems to look fine but i can't figure out the problem with keyword which includes space plz help me soi can save my time ..!!
public class GetNearbyPlacesData extends AsyncTask<Object, String, String> {
String googlePlacesData;
GoogleMap mMap;
String url;
#Override
protected String doInBackground(Object... objects) {
mMap = (GoogleMap)objects[0];
url = (String)objects[1];
com.example.husnainbutt.driveescuev22.DownloadURL downloadUrl = new com.example.husnainbutt.driveescuev22.DownloadURL();
try {
googlePlacesData = downloadUrl.readUrl(url);
} catch (IOException e) {
e.printStackTrace();
}
return googlePlacesData;
}
#Override
protected void onPostExecute(String s) {
List<HashMap<String, String>> nearbyPlaceList = null;
com.example.husnainbutt.driveescuev22.DataParser parser = new com.example.husnainbutt.driveescuev22.DataParser();
nearbyPlaceList = parser.parse(s);
showNearbyPlaces(nearbyPlaceList);
}
private void showNearbyPlaces(List<HashMap<String,String>> nearbyPlaceList)
{
for(int i = 0;i<nearbyPlaceList.size() ; i++)
{
MarkerOptions markerOptions = new MarkerOptions();
HashMap<String , String> googlePlace = nearbyPlaceList.get(i);
Log.d("onPostExecute","Entered into showing locations");
String placeName = googlePlace.get("place_name");
String vicinity = googlePlace.get("vicinity");
double lat = Double.parseDouble( googlePlace.get("lat") );
double lng = Double.parseDouble( googlePlace.get("lng"));
LatLng latLng = new LatLng(lat, lng);
markerOptions.position(latLng);
markerOptions.title(placeName +" : "+ vicinity);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE));
mMap.addMarker(markerOptions);
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(10));
}
}
}
You could use the Place-Types:
https://developers.google.com/places/supported_types?hl=de
Using the type "gas_station" should help.
Currently I am working with a project to get current latitude and longitude, I got that. Now I want the latitude and longitude send to MySQL database using Android. HTTP part of this program is not working.
LocationManager locationManager;
String mprovider;
String lat="", lon="";
private String Tag="MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b1=(Button)findViewById(R.id.button);
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
postData(lat, lon);
}
});
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
mprovider = locationManager.getBestProvider(criteria, false);
if (mprovider != null && !mprovider.equals("")) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
Location location = locationManager.getLastKnownLocation(mprovider);
locationManager.requestLocationUpdates(mprovider, 0, 0, this);
if (location != null) {
onLocationChanged(location);
} else
Toast.makeText(getBaseContext(), "No Location Provider Found Check Your Code", Toast.LENGTH_SHORT).show();
}
}
private void postData(String la, String lo) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost htget = new HttpPost("http://192.168.1.2/yy.php/"+la+"/"+lo);
try {
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(htget);
String resp = response.getStatusLine().toString();
Toast.makeText(this, resp, Toast.LENGTH_SHORT).show();
} catch (ClientProtocolException e) {
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onLocationChanged(Location location) {
lat = Double.toString(location.getLatitude());
lon = Double.toString(location.getLongitude());
TextView tv = (TextView) findViewById(R.id.textView2);
tv.setText("Your Location is:" + lat + "--" + lon);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
you can send data form android to server over http. here is more details
Use mysql's spatial extensions.
For making tables and using it with Google Maps api refer this:
Using MySQL and PHP with Google Maps
Before you start, I have few questions:
Which version of gmaps API are you working with?
How are you parsing the map marker (lat. long.) data?
How are you triggering the save (lat long/ map marker data event).
Workable method: create a JSON parser for parsing the Marker data (which is the JSON Object here).
public class MarkerJSONParser {
/** gets a JSONObject and returns a list */
public List<HashMap<String,String>> parse(JSONObject jObject){
JSONArray jMarkers = null;
try {
/** gets all the elements in the 'markers' array */
jMarkers = jObject.getJSONArray("markers");
} catch (JSONException e) {
e.printStackTrace();
}
/** enjoining getMarkers with the array of json object
* here each JSON object is a marker
*/
return getMarkers(jMarkers);
}
private List<HashMap<String, String>> getMarkers(JSONArray jMarkers){
int markersCount = jMarkers.length();
List<HashMap<String, String>> markersList = new ArrayList<HashMap<String,String>>();
HashMap<String, String> marker = null;
/** Parsing and adding each marker to the list object */
for(int i=0; i<markersCount;i++){
try {
/** Call getMarker with marker JSON object to parse the marker */
marker = getMarker((JSONObject)jMarkers.get(i));
markersList.add(marker);
}catch (JSONException e){
e.printStackTrace();
}
}
return markersList;
}
/** Parsing the Marker JSON object */
private HashMap<String, String> getMarker(JSONObject jMarker){
HashMap<String, String> marker = new HashMap<String, String>();
String lat = "-NA-";
String lng ="-NA-";
try {
// Latitude extraction
if(!jMarker.isNull("lat")){
lat = jMarker.getString("lat");
}
// Longitude extraction
if(!jMarker.isNull("lng")){
lng = jMarker.getString("lng");
}
marker.put("lat", lat);
marker.put("lng", lng);
} catch (JSONException e) {
e.printStackTrace();
}
return marker;
}
}
Paste this in your MySQL's MainActivity.java:
// enjoining OnClick Event listener for the GoogleMap
mGoogleMap.setOnMapClickListener(new OnMapClickListener() {
#Override
public void onMapClick(LatLng latlng) {
addMarker(latlng);
sendToServer(latlng);
}
});
// enjoining location retrieval
new RetrieveTask().execute();
}
// Marking lat. long. on the GoogleMaps
private void addMarker(LatLng latlng) {
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latlng);
markerOptions.title(latlng.latitude + "," + latlng.longitude);
mGoogleMap.addMarker(markerOptions);
}
// Enjoining bg thread to save marker inMySQL server
private void sendToServer(LatLng latlng) {
new SaveTask().execute(latlng);
}
// bg thread to save the marker in MySQL server
private class SaveTask extends AsyncTask<LatLng, Void, Void> {
#Override
protected Void doInBackground(LatLng... params) {
String lat = Double.toString(params[0].latitude);
String lng = Double.toString(params[0].longitude);
String strUrl = "http://www.yourserverurllocation.com";
URL url = null;
try {
url = new URL(strUrl);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(
connection.getOutputStream());
outputStreamWriter.write("lat=" + lat + "&lng="+lng);
outputStreamWriter.flush();
outputStreamWriter.close();
InputStream iStream = connection.getInputStream();
BufferedReader reader = new BufferedReader(new
InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while( (line = reader.readLine()) != null){
sb.append(line);
}
reader.close();
iStream.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
I'm using google maps to show some markers. The markers are download from a database and, at the same time, I get the distancematrix from google api, between the current position of the user and the marker that I get from the database.
My problem is that I was doing this with .get, bloking my ui (I've read that .get blocked the ui:
dataFromAsyncTask = testAsyncTask.get();
Now, I'm trying to do the same without blocking the ui, but I'm not be able to get at the same time, or in a good way, the distance for this markers.
I appreciate some help, please.
This is my code with my old and wrong .get:
for (City city : listCity.getData()) {
geoPoint = city.getLocation();
nameBeach = city.getName();
if (geoPoint == null) {
} else {
latitude = String.valueOf(geoPoint.getLatitude());
longitude = String.valueOf(geoPoint.getLongitude());
startRetrievenDistanceAndDuration();
try {
dataFromAsyncTask = testAsyncTask.get();
} catch (InterruptedException i) {
} catch (ExecutionException e) {
}
mMap.addMarker(new MarkerOptions().position(new LatLng(geoPoint.getLatitude(), geoPoint.getLongitude()))
.title(nameCity)
.snippet(dataFromAsyncTask)
.icon(BitmapDescriptorFactory.defaultMarker()));
}
}
startRetrievenDistanceAndDuration method:
private void startRetrievenDistanceAndDuration() {
final String url;
testAsyncTask = new DistanceBetweenLocations(new FragmentCallback() {
#Override
public void onTaskDone(String result) {
}
});
url = "https://maps.googleapis.com/maps/api/distancematrix/json?origins=" + currentLatitude + "," + currentlongitude + "&destinations=" + latitude + "," + longitude + "&key=xxx";
testAsyncTask.execute(new String[]{url});
}
public interface FragmentCallback {
public void onTaskDone(String result);
AsyncTask class:
#Override
protected String doInBackground(String... params) {
HttpURLConnection urlConnection = null;
URL url = null;
StringBuilder result = null;
String duration = "";
String distance = "";
try {
url=new URL(params[0]);
}catch (MalformedURLException m){
}
try {
urlConnection = (HttpURLConnection) url.openConnection();
}catch (IOException e){}
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
result = new StringBuilder();
String line;
while((line = reader.readLine()) != null) {
result.append(line);
}
}catch (IOException e){
} finally {
urlConnection.disconnect();
}
try {
JSONObject jsonObject = new JSONObject(result.toString());
JSONArray jsonArray = jsonObject.getJSONArray("rows");
JSONObject object_rows = jsonArray.getJSONObject(0);
JSONArray jsonArrayElements = object_rows.getJSONArray("elements");
JSONObject object_elements = jsonArrayElements.getJSONObject(0);
JSONObject object_duration = object_elements.getJSONObject("duration");
JSONObject object_distance = object_elements.getJSONObject("distance");
duration = object_duration.getString("text");
distance = object_distance.getString("text");
} catch (JSONException e) {
e.printStackTrace();
}
return distance + ", " + duration;
}
#Override
protected void onPostExecute(String result) {
mFragmentCallback.onTaskDone(result);
}
}
I'm trying to do this, but I only show the last marker of my list:
Call in the loop the method:
startRetrievenDistanceAndDuration();
And in onTaskDone try to put the marker, but only get the last marker of my list
#Override
public void onTaskDone(String result) {
mMap.addMarker(new MarkerOptions().position(new LatLng(geoPoint.getLatitude(), geoPoint.getLongitude()))
.title(nameBeach)
.snippet(result)
.icon(BitmapDescriptorFactory.defaultMarker()));
}
UPDATED AFTER CHANGES: (still don't work)
I can parse the data in Asynctask and send it in onPostExecute, but I only get one value, and not the 9 values that I have....
MAIN ACTIVITY:
DistanceBetweenLocations task = new DistanceBetweenLocations(mlatituDouble, mlongitudeDouble){
#Override
protected void onPostExecute(HashMap<String, String> result) {
super.onPostExecute(result);
String name = result.get("beachName");
String distance = result.get("distance");
String duration = result.get("duration");
String latitue = result.get("latitude");
String longitude = result.get("longitude");
Double mlatituDouble = Double.parseDouble(latitue);
Double mlongitudeDouble = Double.parseDouble(longitude);
if (mMap == null) {
mMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.mapView))
.getMap();
Toast.makeText(getActivity(), "mMap NO null", Toast.LENGTH_SHORT).show();
mMap.addMarker(new MarkerOptions().position(new LatLng(mlatituDouble, mlongitudeDouble))
.title(name)
.snippet(distance + " " + duration)
.icon(BitmapDescriptorFactory.defaultMarker()));
}
}
};
task.execute();
ASYNCTASK CLASS:.
public class DistanceBetweenLocations extends AsyncTask<String, String, HashMap<String, String>> {
Double currentLatitude;
Double currentlongitude;
public BeachMap beachMap;
public BackendlessCollection<Beach> dataBeach;
public GoogleMap mMap;
String latitude;
String longitude;
HashMap<String, String> map;
public DistanceBetweenLocations(Double currentLatitude, Double currentlongitude){
this.currentLatitude = currentLatitude;
this.currentlongitude = currentlongitude;
}
#Override
protected HashMap<String, String> doInBackground(String... params) {
dataBeach = beachMap.listBeach;
for (Beach city : dataBeach.getData()) {
GeoPoint geoPoint = city.getLocation();
String nameBeach = city.getName();
if (geoPoint == null) {
} else {
latitude = String.valueOf(geoPoint.getLatitude());
longitude = String.valueOf(geoPoint.getLongitude());
HttpURLConnection urlConnection = null;
URL url = null;
StringBuilder result = null;
String duration = "";
String distance = "";
try {
url = new URL("https://maps.googleapis.com/maps/api/distancematrix/json?origins=" + currentLatitude + "," + currentlongitude + "&destinations=" + latitude + "," + longitude + "&key=xxxx");
} catch (MalformedURLException m) {
}
try {
urlConnection = (HttpURLConnection) url.openConnection();
} catch (IOException e) {
}
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
} catch (IOException e) {
} finally {
urlConnection.disconnect();
}
try {
JSONObject jsonObject = new JSONObject(result.toString());
JSONArray jsonArray = jsonObject.getJSONArray("rows");
JSONObject object_rows = jsonArray.getJSONObject(0);
JSONArray jsonArrayElements = object_rows.getJSONArray("elements");
JSONObject object_elements = jsonArrayElements.getJSONObject(0);
JSONObject object_duration = object_elements.getJSONObject("duration");
JSONObject object_distance = object_elements.getJSONObject("distance");
duration = object_duration.getString("text");
distance = object_distance.getString("text");
map = new HashMap<String, String>();
map.put("beachName", nameBeach);
map.put("distance", distance);
map.put("duration", duration);
map.put("latitude", latitude);
map.put("longitude", longitude);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
return map;
}
}
I'll use your last code (the "UPDATED AFTER CHANGES"), ok?
If I get it right, your DistanceBetweenLocations result will be a list of beaches geolocation data. So, on every iteration of the for loop in doInBackground, you are replacing the value of "map" variable, this is your problem.
To solve your problem, you can have a List of HashMap or a List of a Pojo like this:
public class BeachPojo {
private String beachName;
private String distance;
private String duration;
private String latitude;
private String longitude;
public String getBeachName() {
return beachName;
}
public void setBeachName(String beachName) {
this.beachName = beachName;
}
public String getDistance() {
return distance;
}
public void setDistance(String distance) {
this.distance = distance;
}
public String getDuration() {
return duration;
}
public void setDuration(String duration) {
this.duration = duration;
}
public String getLatitude() {
return latitude;
}
public void setLatitude(String latitude) {
this.latitude = latitude;
}
public String getLongitude() {
return longitude;
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}
}
Using the Pojo, your AsyncTask will be like this:
public class DistanceBetweenLocations extends AsyncTask<String, String, List<BeachPojo>> {
Double currentLatitude;
Double currentlongitude;
public BeachMap beachMap;
public BackendlessCollection<Beach> dataBeach;
public GoogleMap mMap;
String latitude;
String longitude;
public DistanceBetweenLocations(Double currentLatitude, Double currentlongitude){
this.currentLatitude = currentLatitude;
this.currentlongitude = currentlongitude;
}
#Override
protected List<BeachPojo> doInBackground(String... params) {
List<BeachPojo> list = new ArrayList<BeachPojo>();
BeachPojo pojo;
dataBeach = beachMap.listBeach;
for (Beach city : dataBeach.getData()) {
GeoPoint geoPoint = city.getLocation();
String nameBeach = city.getName();
if (geoPoint == null) {
} else {
latitude = String.valueOf(geoPoint.getLatitude());
longitude = String.valueOf(geoPoint.getLongitude());
HttpURLConnection urlConnection = null;
URL url = null;
StringBuilder result = null;
String duration = "";
String distance = "";
try {
url = new URL("https://maps.googleapis.com/maps/api/distancematrix/json?origins=" + currentLatitude + "," + currentlongitude + "&destinations=" + latitude + "," + longitude + "&key=xxxx");
} catch (MalformedURLException m) {
}
try {
urlConnection = (HttpURLConnection) url.openConnection();
} catch (IOException e) {
}
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
} catch (IOException e) {
} finally {
urlConnection.disconnect();
}
try {
JSONObject jsonObject = new JSONObject(result.toString());
JSONArray jsonArray = jsonObject.getJSONArray("rows");
JSONObject object_rows = jsonArray.getJSONObject(0);
JSONArray jsonArrayElements = object_rows.getJSONArray("elements");
JSONObject object_elements = jsonArrayElements.getJSONObject(0);
JSONObject object_duration = object_elements.getJSONObject("duration");
JSONObject object_distance = object_elements.getJSONObject("distance");
duration = object_duration.getString("text");
distance = object_distance.getString("text");
pojo = new BeachPojo();
pojo.setBeachName(nameBeach);
pojo.setDistance(distance);
pojo.setDuration(duration);
pojo.setLatitude(latitude);
pojo.setLongitude(longitude);
list.add(pojo);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
return list;
}
}
Now you have a List to iterate. I have adjusted the code a little bit to this goal:
DistanceBetweenLocations task = new DistanceBetweenLocations(mlatituDouble, mlongitudeDouble){
#Override
protected void onPostExecute(List<BeachPojo> result) {
super.onPostExecute(result);
if (mMap == null) {
mMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.mapView))
.getMap();
}
Double beachLatitude;
Double beachLongitude;
for (BeachPojo pojo : result) {
beachLatitude = Double.parseDouble(pojo.getLatitude());
beachLongitude = Double.parseDouble(pojo.getLongitude());
mMap.addMarker(new MarkerOptions().position(new LatLng(beachLatitude, beachLongitude))
.title(pojo.getBeachName())
.snippet(pojo.getDistance() + " " + pojo.getDuration())
.icon(BitmapDescriptorFactory.defaultMarker()));
}
}
};
task.execute();
I hope you understand the idea of returning a List from your AsyncTask and loop throught the result on onPostExecute method.
Note: this is an implementation without knowing the real code, then you should adjust to your reality.
I'm not exactly sure what you're trying to do but I think you've made this more complicated then it has to be.
From what I understand you have a list of City objects and you use them to construct some URLs from which you retrieve a JSON object that is use to construct MarkerOptions objects.
You can do that using a AsyncTask like this:
public class Task extends AsyncTask<City, Void, Markers> {
String currentLatitude;
String currentlongitude;
public Task(String currentLatitude, String currentlongitude){
this.currentLatitude = currentLatitude;
this.currentlongitude = currentlongitude;
}
#Override
protected String doInBackground(City... cities) {
final Markers mMap = ...;
for (City city : cities) {
GeoPoint geoPoint = city.getLocation();
String nameBeach = city.getName();
if (geoPoint != null) {
String latitude = String.valueOf(geoPoint.getLatitude());
String longitude = String.valueOf(geoPoint.getLongitude());
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
try {
URL url = new URL("https://maps.googleapis.com/maps/api/distancematrix/json?origins=" + currentLatitude + "," + currentlongitude + "&destinations=" + latitude + "," + longitude + "&key=xxx";);
urlConnection = (HttpURLConnection) url.openConnection();
reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
JSONObject jsonObject = new JSONObject(result.toString()).getJSONArray("rows").getJSONObject(0).getJSONArray("elements").getJSONObject(0);
String duration = jsonObject.getJSONObject("duration").getString("text");
String distance = jsonObject.getJSONObject("distance").getString("text");
mMap.addMarker(new MarkerOptions().position(new LatLng(geoPoint.getLatitude(), geoPoint.getLongitude()))
.title(nameBeach)
.snippet(distance + ", " + duration)
.icon(BitmapDescriptorFactory.defaultMarker()));
} catch (Exception e) {
e.printStackTrace();
} finally {
if(reader!=null){
try {
reader.close();
}catch (Exception e){
e.printStackTrace();
}
}
if (urlConnection != null) {
try {
urlConnection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
return mMap;
}
}
And here is how you can use this task.
public class Login extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(...);
Task task = new Task(currentLatitude, currentlongitude){
#Override
protected void onPostExecute(Markers markers) {
super.onPostExecute(markers);
//This runs on the UI thread and "markers" is the "mMap" object that was create on the background thread.
}
};
List<City> cities = ....
task.execute(cities.toArray(new City[cities.size()]));
}
}
The idea is that you need to execute all the long running operation in the AsyncTask's doInBackground(...) method. Also, you don't need to create other objects to deal with the AsyncTask response, you can override the task's onPostExecute(...) inside the class you've created the task in.
I have been finding ways to resolve on how to pass multiple values from one class to the other.
I recently found a way which is to use putSerializable to do it but has not been successful. I only been able to return the last longitude and latitude to the other class.
This is my array json string:
{"longitude":"101.9366229","latitude":"1.236459"},
{"longitude":"101.930041","latitude":"1.224119"}]
Below are my code to pass the values:
class Findfriends extends AsyncTask<String, String, JSONObject> {
final String TAG = "Findfriends.java";
protected JSONObject doInBackground(String... args) {
// TODO Auto-generated method stub
// here Check for success tag
try {
HashMap<String, String> params = new HashMap<>();
params.put("username", args[0]);
JSONObject json = jsonParser.makeHttpRequest(
GET_FRIENDS, "POST", params);
if (json != null) {
Log.d("JSON result", json.toString());
return json;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(JSONObject json) {
if (json != null) {
Toast.makeText(Borrower_AP.this, json.toString(),
Toast.LENGTH_LONG).show();
try {
dataJsonArr = json.getJSONArray("Posts");
for (int i = 0; i < dataJsonArr.length(); i++) {
JSONObject c = dataJsonArr.getJSONObject(i);
Longitude = c.getDouble("longitude");
Latitude = c.getDouble("latitude");
Log.e(TAG, "Longitude: " + Longitude
+ ", Latitude: " + Latitude);
coordinates.setLongt(Longitude);
coordinates.setLat(Latitude);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
public class Coordinates implements Serializable {
private Double lat;
private Double longt;
public Double getLat () {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
public Double getLongt() {
return longt;
}
public void setLongt(Double longt) {
this.longt = longt;
}
}
Get the values back:
Intent intent=this.getIntent();
Bundle bundle=intent.getExtras();
Coordinates coordinates=(Coordinates)bundle.getSerializable("coordinates");
System.out.println("Lat:" + coordinates.getLat());
System.out.println("Long:" + coordinates.getLongt());
for your requirement you need Arraylist of your class Coordinates just add objects to it in loop where you parsing json and just send it to another activity and in new activity get it by casting it to Coordinates arraylist
here is the sample
if i consider coordinates in onpost method is arraylist
ArrayList<Coordinates> coordinates=new ArrayList<Coordinates>();
in your onpost forloop
use following
for (int i = 0; i < dataJsonArr.length(); i++) {
JSONObject c = dataJsonArr.getJSONObject(i);
Longitude = c.getDouble("longitude");
Latitude = c.getDouble("latitude");
Log.e(TAG, "Longitude: " + Longitude
+ ", Latitude: " + Latitude);
Coordinates coordinatesobj=new Coordinates();
coordinatesobj.setLongt(Longitude);
coordinatesobj.setLat(Latitude);
coordinates.add(coordinatesobj);
}
where you starting new activity there put below
Intent intent = new Intent(SourceActivity.this, TargetActivity.class);
intent.putExtra("key", coordinates);
at receiving side activity
Intent intent=this.getIntent();
Bundle bundle=intent.getExtras();
ArrayList<Coordinates> coordinates=( ArrayList<Coordinates>)bundle.getSerializable("key");
hope it helps
i successfully created google map .i can check mylocation and i wrote code witch can add point in google map (touch listener) and draw line between start location and point . and now i want to check distance . i do not know how i can this
i googled one example but this code does not working right?i always has one distance
this is a my code if anyone knows solution please help me
thanks
public class GPS extends Activity implements
OnMyLocationChangeListener, OnMapClickListener {
final int RQS_GooglePlayServices = 1;
private GoogleMap myMap;
Circle myCircle;
TextView tvLocInfo, GPSLocation;
LatLng latLng;
boolean markerClicked;
ArrayList<LatLng> markerPoints;
double Startlatitude, Startlongitude, Endlatitude, Endlongitude;
public Button gpssize;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.gps);
markerPoints = new ArrayList<LatLng>();
gpssize = (Button) findViewById(R.id.gpssize);
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.getUiSettings().setZoomControlsEnabled(true);
myMap.getUiSettings().setCompassEnabled(true);
myMap.getUiSettings().setMyLocationButtonEnabled(true);
myMap.setMyLocationEnabled(true);
myMap.setOnMyLocationChangeListener(this);
gpssize.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
double distance;
Location locationA = new Location("");
locationA.setLatitude(Startlatitude);
locationA.setLongitude(Startlongitude);
Location locationB = new Location("");
locationB.setLatitude(Endlatitude);
locationB.setLongitude(Endlongitude);
distance = locationA.distanceTo(locationB) / 1000;
Toast.makeText(getApplicationContext(), "" + distance,
Toast.LENGTH_LONG).show();
}
});
myMap.setOnMapClickListener(this);
myMap.setTrafficEnabled(true);
markerClicked = false;
}
#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) {
Startlatitude = location.getLatitude();
Startlongitude = location.getLongitude();
latLng = new LatLng(Startlatitude, Startlongitude);
myMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
GPSLocation.setText(Startlatitude + " " + Startlongitude);
// 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)
.radius(accuracy)
.fillColor(Color.RED).strokeColor(Color.BLACK).strokeWidth(5);
myCircle = myMap.addCircle(circleOptions);
} else {
myCircle.setCenter(locLatLng);
myCircle.setRadius(accuracy);
}
myMap.animateCamera(CameraUpdateFactory.zoomTo(15));
}
private String getDirectionsUrl(LatLng origin, LatLng dest) {
String str_origin = "origin=" + Startlatitude + "," + Startlongitude;
String str_dest = "destination=" + dest.latitude + "," + dest.longitude;
String sensor = "sensor=false";
String parameters = str_origin + "&" + str_dest + "&" + sensor;
String output = "json";
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);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.connect();
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;
}
private class DownloadTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... url) {
String data = "";
try {
data = downloadUrl(url[0]);
} catch (Exception e) {
Log.d("Background Task", e.toString());
}
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
ParserTask parserTask = new ParserTask();
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();
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();
for (int i = 0; i < result.size(); i++) {
points = new ArrayList<LatLng>();
lineOptions = new PolylineOptions();
List<HashMap<String, String>> path = result.get(i);
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"));
tvLocInfo.setText(lat + " " + lng);
LatLng position = new LatLng(lat, lng);
points.add(position);
}
lineOptions.addAll(points);
lineOptions.width(7);
lineOptions.geodesic(true);
lineOptions.color(getResources().getColor(R.color.mapColor));
}
myMap.addPolyline(lineOptions);
}
}
#Override
public void onMapClick(LatLng point) {
if (markerPoints.size() > 0) {
markerPoints.clear();
myMap.clear();
}
markerPoints.add(point);
MarkerOptions options = new MarkerOptions();
options.position(point);
if (markerPoints.size() == 1) {
options.icon(BitmapDescriptorFactory
.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
}
myMap.addMarker(options);
if (markerPoints.size() >= 1) {
LatLng dest = markerPoints.get(0);
LatLng origin = new LatLng(Endlatitude, Endlongitude);
String url = getDirectionsUrl(origin, dest);
DownloadTask downloadTask = new DownloadTask();
downloadTask.execute(url);
}
}
}
Try on this way to get Distance between to LatLng Points:
float[] distances = new float[1];
Location.distanceBetween(locationA.latitude, locationA.longitude,
locationB.latitude, locationB.longitude,
distances);
System.out.println("Distance: " + distances[0]);