I am developing an android application which displays a map. When it loads, it displays some addresses and sets markers for them.
When I click on any marker it should display a value in a custom view. But the custom text which is received from a json parser, gets a null value. When I click on the marker again, it sets correct value.
When I click on second marker it display 1st marker value. When I click on 2nd marker again it displays correct value. This process continues
Here's my code:
private class GeocoderTask extends AsyncTask<String, Void, List<Address>>{
private Context mainContxt;
Geocoder geocoder;
public GeocoderTask(Context con){
mainContxt=con;
}
#Override
protected List<Address> doInBackground(String... locationName) {
Geocoder geocoder = new Geocoder(mainContxt);
List<Address> addresses = null;
try {
addresses = geocoder.getFromLocationName(locationName[0],1);
} catch (IOException e) {
e.printStackTrace();
}
return addresses;
}
#Override
protected void onPostExecute(List<Address> addresses) {
for(int i=0;i<addresses.size();i++){
Address address = (Address) addresses.get(i);
latLng = new LatLng(address.getLatitude(), address.getLongitude());
String addressText = String.format("%s, %s",
address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "",
address.getCountryName());
markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title(addressText);
if(i==0) {
googleMap.animateCamera(CameraUpdateFactory.zoomBy(14),2000,null);
googleMap.animateCamera(CameraUpdateFactory.newLatLng(latLng));
}
googleMap.addMarker(markerOptions);
}
googleMap.setOnMarkerClickListener(new OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker_address) {
location=marker_address.getTitle();
Toast.makeText(getApplicationContext(),location, Toast.LENGTH_LONG).show();
new LoadSingleProperty().execute();
//new LoadImage().execute();
return false;
}
});
googleMap.setInfoWindowAdapter(new InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker arg0) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
View myContentView = getLayoutInflater().inflate(
R.layout.custom_marker, null);
tempnew_price=getPrice(temptotal_price+"" +email);
TextView tvTitle = ((TextView) myContentView
.findViewById(R.id.title));
// tvTitle.setText(location);
tvSnippet = ((TextView) myContentView
.findViewById(R.id.snippet));
ivProperty = ((ImageView) myContentView
.findViewById(R.id.image_property));
tvTitle.setText(tempcovered_area+ " "+tempnew_price+System.getProperty("line.separator")+templocation);
tvSnippet.setText("A "+ tempbedroom + " "+tempproperty_type);
// new LoadImage().execute();
ivProperty.setImageBitmap(bmp);
return myContentView;
}
});
googleMap.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker arg0) {
Intent intent = new Intent(getBaseContext(),
search_property_activity.class);
intent.putExtra("Email", email);
startActivity(intent);
}
});
}
}
this is my loadsingle class coding.....
class LoadSingleProperty extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MainActivityMap.this);
pDialog.setMessage("Loading Location. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
protected String doInBackground(String... args) {
List<NameValuePair> params = new ArrayList<NameValuePair>();
if(location!=null && !location.equals("")){
params.add(new BasicNameValuePair("Location", location));
json= jsonParser.makeHttpRequest(url_loc_address, "GET", params);
}
Log.d("MyLocation: ", json.toString());
try {
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
address = json.getJSONArray(TAG_ALL_ADDRESS);
//for (int i = 0; i < address.length(); i++) {
JSONObject c = address.getJSONObject(0);
templocation = c.getString(TAG_LOCATION);
tempcovered_area=c.getString(TAG_COVERED_AREA);
temptotal_price=c.getString(TAG_Total_Price);
tempbedroom=c.getString(TAG_BEDROOM);
tempproperty_type=c.getString(TAG_PROPERTY_TYPE);
tempemail=c.getString(TAG_EMAIL);
//}
} else {
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String file_url) {
pDialog.dismiss();
new GeocoderTask(MainActivityMap.this).execute(location);
}
}
Help me friends ...thx in advance
Create a constructor for LoadSingleProperty
class LoadSingleProperty extends AsyncTask<String, String, String> {
Marker mMarker;
public LoadSingleProperty(Marker marker){
mMarker = marker;
}
.
.
.
}
and pass your marker object to it.
new LoadSingleProperty(marker_address).execute();
Once parsing is done set your marker's title using setTitle() method for the marker
mMarker.setTitle(c.getString(TAG_PROPERTY_TYPE));
where you currently do this
tempproperty_type=c.getString(TAG_PROPERTY_TYPE);
Don't forget to refresh your info window once title is reset
How to force refresh contents of the markerInfoWindow
You may also want to show some sort of a loading icon till this time since you're performing a network request.
EDIT:
In case you're using a custom titleview, get a reference to InfoWindowAdapter object before setting as a adapter to googleMap
InfoWindowAdapter infoWindowAdapter = new InfoWindowAdapter() {...
Once parsing is complete, get info window view for mMarker object by calling
infoWindowAdapter.getInfoWindow(mMarker);
Find your textView from the view obtained above and set its text. Then refresh your info window by calling showInfoWindow() to update the info window.
Also please refer this link.
The info window that is drawn is not a live view. The view is rendered
as an image (using View.draw(Canvas)) at the time it is returned. This
means that any subsequent changes to the view will not be reflected by
the info window on the map. To update the info window later (for
example, after an image has loaded), call showInfoWindow()
private class GeocoderTask extends AsyncTask<String, Void, List<Address>> {
private Context mainContxt;
Geocoder geocoder;
public GeocoderTask(Context con) {
mainContxt = con;
}
#Override
protected List<Address> doInBackground(String... locationName) {
Geocoder geocoder = new Geocoder(mainContxt);
List<Address> addresses = null;
try {
addresses = geocoder.getFromLocationName(locationName[0], 1);
} catch (IOException e) {
e.printStackTrace();
}
return addresses;
}
#Override
protected void onPostExecute(List<Address> addresses) {
for (int i = 0; i < addresses.size(); i++) {
Address address = (Address) addresses.get(i);
latLng = new LatLng(address.getLatitude(),
address.getLongitude());
String addressText = String.format(
"%s, %s",
address.getMaxAddressLineIndex() > 0 ? address
.getAddressLine(0) : "", address
.getCountryName());
markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title(addressText);
if (i == 0) {
googleMap.animateCamera(CameraUpdateFactory.zoomBy(14),
2000, null);
googleMap.animateCamera(CameraUpdateFactory
.newLatLng(latLng));
}
googleMap.addMarker(markerOptions);
}
}
}
Then you write below code
googleMap.setOnMarkerClickListener(new OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker_address) {
location = marker_address.getTitle();
new LoadSingleProperty().execute();
return false;
}
});
Take another customeWindowAdapter or else use the present one only and set that in onPostExecute() method of 'LoadSingleProperty' AsyncTask..
This will solve that.
ping here you have any queries
Related
I am trying to add an image I have in parse to a google map info window, I can add the image from resource but I am unable to load my existing parse image to the image view inside my infowindow. I have loaded the image from parse in other areas of my app, but it seems that the info window is out of scope. Is there a way to load this parse image inside my infowindow? I do not want to use a resource file because the images are different in parse. The 2 sections of my code are below:
class NearbyEventTask extends AsyncTask<String, Void, ArrayList<Item>>
{
Random r;
Context context;
public NearbyEventTask(Context context){
r = new Random();
this.context = context;
}
public LatLng getRandomLocation(Location center, double radius) {
// Convert radius from meters to degrees
double radiusInDegrees = radius / 111000;
double u = r.nextDouble();
double v = r.nextDouble();
double w = radiusInDegrees * Math.sqrt(u);
double t = 2 * Math.PI * v;
double lat = w * Math.cos(t);
double lon = w * Math.sin(t);
double new_lat = lat / Math.cos(center.getLongitude());
return new LatLng(new_lat + center.getLatitude(), lon + center.getLongitude());
}
#Override
protected ArrayList<Item> doInBackground(String... params) {
ArrayList<Item> list = new ArrayList<Item>();
ParseQuery<ParseObject> query = ParseQuery.getQuery("Places");
if(searchType!=null && searchType.length()>0) {
ArrayList<String> types = new ArrayList<String>();
for(String type: searchType.split("\\|")) types.add(type);
query.whereContainedIn("category", types);
}
if(lastKnownLocation!=null) {
query.whereNear("location", new ParseGeoPoint(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude()));
}
try {
List<ParseObject> objects = query.find();
for(ParseObject obj : objects){
ParseGeoPoint point = obj.getParseGeoPoint("location");
Item item = new Item(obj.getString("name"), obj.getString("category"), obj.getString("description"), point.getLatitude(), point.getLongitude());
item.vicinity = obj.getString("description") + " | "+obj.getDate("event_date");
list.add(item);
if(obj.getParseFile("icon")!=null) {
item.setIcon(obj.getParseFile("icon").getUrl());
item.downloadIcon(context);
}
}
} catch (ParseException e) {
}
return list;
}
#Override
protected void onPostExecute(final ArrayList<Item> arrayList) {
if(isCancelled()) return;
if(googleMap!=null) {
googleMap.clear();
mMarker2Item.clear();
LatLngBounds.Builder boundBuilder = new LatLngBounds.Builder();
for (Item item : arrayList) {
MarkerOptions opts = new MarkerOptions()
.position(item.location())
.title(item.name);
if(item.iconBitmap!=null){
opts = opts.icon(BitmapDescriptorFactory.fromBitmap(item.iconBitmap));
}
Marker newMarker = googleMap.addMarker(opts);
newMarker.setSnippet(item.vicinity);
mMarker2Item.put(newMarker, item);
boundBuilder.include(item.location());
}
try {
if (firstTime) {
firstTime = false;
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngBounds(boundBuilder.build(), 200);
googleMap.moveCamera(cameraUpdate);
googleMap.animateCamera(cameraUpdate, 1000, null);
}
} catch (Exception ex) {
}
} else mHandler.postDelayed(new Runnable() {
#Override
public void run() {
onPostExecute(arrayList);
}
}, 500);
}
}
#Override
public void onMapReady(final GoogleMap googleMap) {
googleMap.setMyLocationEnabled(true);
this.googleMap = googleMap;
googleMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
// Use default InfoWindow frame
#Override
public View getInfoWindow(Marker arg0) {
return null;
}
// Defines the contents of the InfoWindow
#Override
public View getInfoContents(Marker marker) {
View v = getActivity().getLayoutInflater().inflate(R.layout.maps_infowindow, null);
v.setLayoutParams(new LinearLayout.LayoutParams((int) (mapFragment.getView().getMeasuredWidth() * .9), LinearLayout.LayoutParams.WRAP_CONTENT));
((TextView) v.findViewById(R.id.title)).setText(marker.getTitle());
((TextView) v.findViewById(R.id.desc)).setText(marker.getSnippet());
ImageView icon = (ImageView) v.findViewById(R.id.imageView5);
icon.getLayoutParams().height = 800; // OR
icon.getLayoutParams().width = 800;
ArrayList<Item> list = new ArrayList<Item>();
ParseQuery<ParseObject> query = ParseQuery.getQuery("Places");
if(searchType!=null && searchType.length()>0) {
ArrayList<String> types = new ArrayList<String>();
for(String type: searchType.split("\\|")) types.add(type);
query.whereContainedIn("icon", types);
}
try {
List<ParseObject> objects = query.find();
for(ParseObject obj : objects){
if(obj.getParseFile("icon")!=null) {
Picasso.with(getActivity()).load(obj.getParseFile("icon").getUrl()).into(icon, new MarkerCallback(marker));
}
}
} catch (ParseException e) {
}
return v;
}
}
);
CODE UPDATED: If you look at my NearbyEventTast class at the top, you can see how the code was implemented to get the data back from parse. I am trying to do the same thing by creating a new NearbyEventTast but I fail to load the correct image. It always shows the same image (I think its the first one in parse) and displays it for all objects instead of the corresponden image. Any idiea whats going on? Thank you!
As I am not much aware of Parse. But I have also face this issue to show a image from URL into info window.
First of all, the reason infowindow is not showing the downloaded image because MapFragment renders the view into a Canvas and then draws that. What you're seeing in the info window aren't the views you created, but a "picture" or "screenshot" of them. You basically need to call showInfoWindow() again on the Marker object, and that will re-render the Canvas and your image will now be visible.
Or you can use the Picasso Library to load the image. I am using the Picasso callback option in my app.
First you need to create a Class that will implements a Picasso Callback Interface and in the Constructor recieve a marker to call a show info window when image loads.
public static class MarkerCallback implements Callback {
private Marker marker;
public MarkerCallback(Marker marker) {
this.marker = marker;
}
#Override
public void onSuccess() {
if (marker != null && marker.isInfoWindowShown()) {
marker.hideInfoWindow();
marker.showInfoWindow();
}
}
#Override
public void onError() {
}
}
How to use it.
public View getInfoContents(Marker marker) {
View v = getActivity().getLayoutInflater().inflate(R.layout.maps_infowindow, null);
v.setLayoutParams(new LinearLayout.LayoutParams((int) (mapFragment.getView().getMeasuredWidth() * .9), LinearLayout.LayoutParams.WRAP_CONTENT));
((TextView) v.findViewById(R.id.title)).setText(marker.getTitle());
((TextView) v.findViewById(R.id.desc)).setText(marker.getSnippet());
ImageView markerIcon = (ImageView) v.findViewById(R.id.imageView5);
Picasso.with(MainActivity.this).load(imgUrl).into(markerIcon, new MarkerCallback(marker));
}
Hope this will help you.
I'm working on a small app and have implemented Google Maps and Places api. Currently i'm able to see all my markers on the map and clustering working fine. I'm able to zoom in the clusters open up and able to see the markers. I have a spinner that has different types and once selected that type is passed to the places search string.
This is my maps code that includes the clustering:
public class MapsActivity extends FragmentActivity implements LocationListener,ClusterManager.OnClusterItemInfoWindowClickListener<MyItem> {
GoogleMap mMap;
double myLatitude = 0;
double myLongitude = 0;
HashMap<String, String> mMarker = new HashMap<String, String>();
PlaceJSONParser placeJsonParser = new PlaceJSONParser();
private ClusterManager<MyItem> mClusterManager;
protected MyItem clickedClusterItem;
String[] placeType;
String[] placeTypeName;
Spinner spinPlaceType;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mMap = mapFragment.getMap();
onMapReady();
// Array of place types
placeType = getResources().getStringArray(R.array.placeType);
// Array of place type names
placeTypeName = getResources().getStringArray(R.array.placeTypeName);
// Creating an array adapter with an array of Place types
// to populate the spinner
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, R.layout.spinner_item, R.id.textview, placeTypeName);
// Getting reference to the Spinner
spinPlaceType = (Spinner) findViewById(R.id.spinPlaceType);
// Setting adapter on Spinner to set place types
spinPlaceType.setAdapter(adapter);
spinPlaceType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
int selectedPosition = spinPlaceType.getSelectedItemPosition();
final String type = placeType[selectedPosition];
StringBuilder sb = new StringBuilder(
"https://maps.googleapis.com/maps/api/place/nearbysearch/json?");
sb.append("location=" + myLatitude + "," + myLongitude);
sb.append("&type=" + type);
sb.append("&radius=4000");
sb.append("&key=PLACES_KEY");
// Creating a new non-ui thread task to download Google place json
// data
PlacesTask placesTask = new PlacesTask();
// Invokes the "doInBackground()" method of the class PlaceTask
placesTask.execute(sb.toString());
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
StringBuilder sb = new StringBuilder(
"https://maps.googleapis.com/maps/api/place/nearbysearch/json?");
sb.append("location=" + myLatitude + "," + myLongitude);
sb.append("&type=restaurant");
sb.append("&radius=4000");
sb.append("&key=PLACES_KEY");
// Creating a new non-ui thread task to download Google place json
// data
PlacesTask placesTask = new PlacesTask();
// Invokes the "doInBackground()" method of the class PlaceTask
placesTask.execute(sb.toString());
}
});
// Will display next 20 places returned form the next_page_token
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab_more);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Finding you some more places.", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
StringBuilder sb = new StringBuilder(
"https://maps.googleapis.com/maps/api/place/nearbysearch/json?");
sb.append("pagetoken=" + placeJsonParser.getNext_Page_token());
sb.append("&key=PLACES_KEY");
// Creating a new non-ui thread task to download Google place json
// data
if (placeJsonParser.getNext_Page_token() == null || placeJsonParser.getNext_Page_token() == ""){
Snackbar.make(view, "No more places left to find.", Snackbar.LENGTH_SHORT)
.setAction("Action", null).show();
}
PlacesTask placesTask = new PlacesTask();
// Invokes the "doInBackground()" method of the class PlaceTask
placesTask.execute(sb.toString());
}
});
mMap.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker marker) {
Intent detailsIntent = new Intent(getBaseContext(), PlaceDetailsActivity.class);
String reference = mMarker.get(marker.getId());
marker.getPosition();
detailsIntent.putExtra("reference", reference);
detailsIntent.putExtra("markerLat", myLatitude);
detailsIntent.putExtra("markerLong", myLongitude);
startActivity(detailsIntent);
}
});
}
public void onMapReady(){
// Enabling MyLocation in Google Map
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setCompassEnabled(true);
mMap.getUiSettings().setZoomControlsEnabled(true);
// Getting LocationManager object from System Service
// LOCATION_SERVICE
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
// Creating a criteria object to retrieve provider
Criteria criteria = new Criteria();
// Getting the name of the best provider
String provider = locationManager.getBestProvider(criteria, true);
// Getting Current Location From GPS
Location location = locationManager.getLastKnownLocation(provider);
// onLocationChanged(location);
if (location != null) {
onLocationChanged(location);
}
}
/**
* A method to download json data from url
*/
private String downloadUrl(String strUrl) throws IOException {
String referer ="";
StringBuilder jsonResults = new StringBuilder();
HttpURLConnection conn = null;
try {
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
conn = (HttpURLConnection) url.openConnection();
if (referer != null) {
conn.setRequestProperty("Referer", referer);
}
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);
}
// Displays the list of places found in the terminal.
Log.i("Data", "Places Found: " + jsonResults);
} catch (MalformedURLException e) {
Log.i("Google Places Utility", "Error processing Places API URL");
return null;
} catch (IOException e) {
Log.i("Google Places Utility", "Error connecting to Places API");
return null;
} finally {
if (conn != null) {
conn.disconnect();
}
}
return jsonResults.toString();
}
/**
* A class, to download Google Places
*/
private class PlacesTask extends AsyncTask<String, Integer, String> {
String data = null;
// Invoked by execute() method of this object
#Override
protected String doInBackground(String... url) {
try {
data = downloadUrl(url[0]);
} catch (Exception e) {
Log.d("Background Task", e.toString());
}
return data;
}
// Executed after the complete execution of doInBackground() method
#Override
protected void onPostExecute(String result) {
ParserTask parserTask = new ParserTask();
// Start parsing the Google places in JSON format
// Invokes the "doInBackground()" method of the class ParseTask
parserTask.execute(result);
}
}
/**
* A class to parse the Google Places in JSON format
*/
private class ParserTask extends
AsyncTask<String, Integer, List<HashMap<String, String>>> {
JSONObject jObject;
// Invoked by execute() method of this object
#Override
protected List<HashMap<String, String>> doInBackground(
String... jsonData) {
List<HashMap<String, String>> places = null;
try {
jObject = new JSONObject(jsonData[0]);
/** Getting the parsed data as a List construct */
places = placeJsonParser.parse(jObject);
} catch (Exception e) {
Log.d("Exception", e.toString());
}
return places;
}
// Executed after the complete execution of doInBackground() method
#Override
protected void onPostExecute(List<HashMap<String, String>> list) {
// Clears all the existing markers
mMap.clear();
setUpClusterer(list);
}
}
private void setUpClusterer(List<HashMap<String, String>> list) {
// Position the map.
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(myLatitude,myLongitude), 13));
// Initialize the manager with the context and the map.
// (Activity extends context, so we can pass 'this' in the constructor.)
mClusterManager = new ClusterManager<MyItem>(this, mMap);
// Point the map's listeners at the listeners implemented by the cluster
// manager.
mMap.setOnCameraChangeListener(mClusterManager);
mMap.setOnMarkerClickListener(mClusterManager);
mMap.setInfoWindowAdapter(mClusterManager.getMarkerManager());
mMap.setOnInfoWindowClickListener(mClusterManager);
mClusterManager.setOnClusterItemInfoWindowClickListener(this);
mClusterManager
.setOnClusterItemClickListener(new ClusterManager.OnClusterItemClickListener<MyItem>() {
#Override
public boolean onClusterItemClick(MyItem item) {
clickedClusterItem = item;
return false;
}
});
// Add cluster items (markers) to the cluster manager.
addItems(list);
mClusterManager.getMarkerCollection().setOnInfoWindowAdapter(
new MyCustomAdapterForItems());
}
public class MyCustomAdapterForItems implements GoogleMap.InfoWindowAdapter {
private final View myContentsView;
MyCustomAdapterForItems() {
myContentsView = getLayoutInflater().inflate(
R.layout.info_window, null);
}
#Override
public View getInfoWindow(Marker marker) {
TextView tvTitle = ((TextView) myContentsView
.findViewById(R.id.txtTitle));
TextView tvSnippet = ((TextView) myContentsView
.findViewById(R.id.txtSnippet));
tvTitle.setText(clickedClusterItem.getTitle());
tvSnippet.setText(clickedClusterItem.getSnippet());
return myContentsView;
}
#Override
public View getInfoContents(Marker marker) {
return null;
}
}
private void addItems(List<HashMap<String, String>> list) {
double latitude;
double longitude;
for (int i = 0; i < list.size(); i++) {
HashMap<String, String> hmPlace = list.get(i);
// Getting latitude of the place
latitude = Double.parseDouble(hmPlace.get("lat"));
// Getting longitude of the place
longitude = Double.parseDouble(hmPlace.get("lng"));
String name = hmPlace.get("place_name");
// Getting vicinity
String vicinity = hmPlace.get("vicinity");
MyItem offsetItem = new MyItem(latitude, longitude, hmPlace.get("reference"), name, vicinity);
mClusterManager.addItem(offsetItem);
}
}
public void onClusterItemInfoWindowClick(MyItem item) {
Intent placesIntent = new Intent(getBaseContext(), PlaceDetailsActivity.class);
String reference = item.getReference();
placesIntent.putExtra("name", item.getTitle());
placesIntent.putExtra("reference", reference);
placesIntent.putExtra("sourcelat", myLatitude);
placesIntent.putExtra("sourcelng", myLongitude);
startActivity(placesIntent);
}
#Override
public void onLocationChanged(Location location) {
myLatitude = location.getLatitude();
myLongitude = location.getLongitude();
LatLng myLocation = new LatLng(myLatitude, myLongitude);
mMap.moveCamera(CameraUpdateFactory.newLatLng(myLocation));
mMap.animateCamera(CameraUpdateFactory.zoomTo(13));
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
}
my myItem class to get info for the markers:
package com.example.tariq.outandabout;
import com.google.android.gms.maps.model.LatLng;
import com.google.maps.android.clustering.ClusterItem;
public class MyItem implements ClusterItem {
LatLng mPosition;
private String reference,placeTitle,snippet;
public MyItem(double lat, double lng,String val,String title, String snip) {
mPosition = new LatLng(lat, lng);
reference=val;
placeTitle=title;
snippet = snip;
}
#Override
public LatLng getPosition() {
// TODO Auto-generated method stub
return mPosition;
}
public String getReference() {
// TODO Auto-generated method stub
return reference;
}
public String getTitle() {
// TODO Auto-generated method stub
return placeTitle;
}
public String getSnippet() {
// TODO Auto-generated method stub
return snippet;
}
}
Currently only red markers are getting displayed but I was wondering if there is a way to have a different markers depending on the type selected from the spinner, For example if I select Hospital then the markers are shown as little hospital icons, if I select ATM, then a little ATM icon appears.
Any help will be appreciated.
Firstly you have to store all the info you need (at this situation just LatLng and marker icon) insite ClusterItem object.
public class MarkerItem implements ClusterItem {
private String title;
private String snippet;
private LatLng latLng;
private BitmapDescriptor icon;
public MarkerItem(MarkerOptions markerOptions) {
this.latLng = markerOptions.getPosition();
this.title = markerOptions.getTitle();
this.snippet = markerOptions.getSnippet();
this.icon = markerOptions.getIcon();
}
#Override
public LatLng getPosition() {
return latLng;
}
public String getTitle() {
return title;
}
public String getSnippet() {
return snippet;
}
public void setLatLng(LatLng latLng) {
this.latLng = latLng;
}
public BitmapDescriptor getIcon() {
return icon;
}
public void setIcon(BitmapDescriptor icon) {
this.icon = icon;
}
}
The next step would be to make cluster renderer show your icon instead of default maker icon. To achieve that, you need to extend DefaultClusterRenderer object:
public class ClusterRenderer extends DefaultClusterRenderer<MarkerItem> {
public ClusterRenderer(Context context, GoogleMap map, ClusterManager<MarkerItem> clusterManager) {
super(context, map, clusterManager);
clusterManager.setRenderer(this);
}
#Override
protected void onBeforeClusterItemRendered(MarkerItem markerItem, MarkerOptions markerOptions) {
if (markerItem.getIcon() != null) {
markerOptions.icon(markerItem.getIcon()); //Here you retrieve BitmapDescriptor from ClusterItem and set it as marker icon
}
markerOptions.visible(true);
}
}
Finally, you have to initialize the clusterRenderer and markerItems
ClusterManager clusterManager = new ClusterManager<>(context, googleMap);
ClusterRenderer clusterRenderer = new ClusterRenderer<>(activity, googleMap, clusterManager); // not needed to use clusterManager.setRenderer method since i made it in constructor
MarkerOptions markerOptions = new MarkerOptions()
.position(new LatLng(latitude, longitude))
.icon(BitmapDescriptorFactory.fromResource(R.drawable.your_resource_icon));
MarkerItem markerItem = new MarkerItem(markerOptions);
clusterManager.addItem(markerItem);
You can implement your own logic, which icon you want to pass to markerItem here.
EDIT
To pass different icons, you could create a separate method for that
Example:
public MarkerOptions getMarkerOptions(LatLng latLng, String title, String snippet, int iconRes) {
return new MarkerOptions()
.title(title)
.snippet(snippet)
.position(latLng)
.icon(BitmapDescriptorFactory.fromResource(iconRes));
}
EDIT 2
I updated MarkerItem class to suit your needs, replace your MyItem class with MarkerItem class. Add your items using this class and update it to suit your needs
I have created a infowindow for a marker and trying to set the address of a particular location by tapping on it but its not doing anything. Where am I making mistake?
map.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker marker) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
LayoutInflater layoutInflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(R.layout.info_window, null, false);
anchor_name = (TextView) view.findViewById(R.id.ancor_name);
anchor_address = (TextView) view.findViewById(R.id.address_a);
LatLng latlng = marker.getPosition();
AsyncTask<LatLng, Void, String> mytask = new AsyncTask<LatLng, Void, String>() {
#Override
protected String doInBackground(LatLng... params) {
return getParticularLocationAddress(params[0]);
}
#Override
protected void onPostExecute(String result) {
anchor_address.setText(result);
anchor_name.setText("Ravi");
}
};
mytask.execute(latlng);
//anchor_address.setText(getParticularLocationAddress(latlng));
return view;
}
});
getParticularLocationAddress method is given as
public String getParticularLocationAddress(LatLng latlng) {
double longitude = latlng.longitude;
double latitude = latlng.latitude;
String marker_address = null;
try {
if (longitude != 0) {
Geocoder geo = new Geocoder(this.getApplicationContext(), Locale.getDefault());
addresses = geo.getFromLocation(latitude, longitude, 1);
marker_address = addresses.get(0).getAddressLine(0) + ", "
+ addresses.get(0).getAddressLine(1);
} else {
marker_address = "Can't resolve";
}
} catch (Exception e) {
e.printStackTrace();
}
return marker_address;
}
I have written a program in which on button click i am getting the nearby atms from json . This is the link
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=19.052696,72.8713694&radius=1000&types=atm&sensor=true&key=AIzaSyA8szrI9Ue4EwyUwTgz7Nk0c39qMal0pN4
I want to plot the atms on google map but the problem is only the last atm is being displayed on the map
Code : Method to get the atm names , latitude , longitude and vicinity
public void showAtm(){
String getAtmUrl =
"https://maps.googleapis.com/maps/api/place/nearbysearch/json?
location="+lat+","+lng+"&radius=1000&types=atm&sensor=true
&key=AIzaSyA8szrI9Ue4EwyUwTgz7Nk0c39qMal0pN4";
try{
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(getAtmUrl).build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
Map_Activity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getBaseContext(), "Request to atm
locations failed", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void onResponse(Call call, Response response) throws
IOException {
Log.i("response ", "onResponse(): " + response);
String result = response.body().string();
Log.i("result",result);
try{
JSONObject jsonObject = new JSONObject(result);
String resultData = jsonObject.getString("results");
JSONArray urlDetails = new JSONArray(resultData);
for (int i = 0 ; i < urlDetails.length(); i++){
JSONObject json = urlDetails.getJSONObject(i);
geometry = json.getString(GOEMETRY);
vicinity = json.getString(VICINITY);
JSONObject jsonGeometry = new JSONObject(geometry);
String geoLocation =
jsonGeometry.getString(LOCATION);
JSONObject jsonLatLng = new JSONObject(geoLocation);
atmLat = jsonLatLng.getDouble(LATITUDE);
atmLong = jsonLatLng.getDouble(LONGITUDE);
atmName = json.getString(ATM_NAME);
Log.i("JsonArrayAtm", "" + atmName);
Log.i("JsonArrayGeometry",geometry);
Log.i("LatLong",""+atmLat+" , "+atmLong);
Log.i("Vicinity", vicinity);
runOnUiThread(new Runnable() {
#Override
public void run() {
moveAtmMap(atmLat ,atmLong );
}
});
}
}catch (Exception e){
e.printStackTrace();
}
}
});
}catch (Exception e){
e.printStackTrace();
}
}
///////////////////////////// atm locations map ///////////////////
private void moveAtmMap(Double amtLatitude,Double atmLongitude){
fragment.getMap().clear();
CameraPosition position = CameraPosition.builder()
.target(new LatLng(amtLatitude, atmLongitude))
.zoom(16f)
.bearing(0.0f)
.tilt(0.0f)
.build();
String msg = amtLatitude+ ", " + atmLongitude;
LatLng latLng = new LatLng(amtLatitude, atmLongitude);
fragment.getMap().addMarker(new MarkerOptions()
.position(latLng));
fragment.getMap().setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter()
{
#Override
public View getInfoWindow(Marker marker) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
View v = getLayoutInflater().inflate(R.layout.atm_custom_window,
null);
TextView atmHeader = (TextView) v.findViewById(R.id.atmName);
TextView atmLocation = (TextView)
v.findViewById(R.id.atmLocation);
atmHeader.setText(atmName);
atmLocation.setText(vicinity);
return v;
}
});
fragment.getMap().setMapType(GoogleMap.MAP_TYPE_NORMAL);
fragment.getMap().setTrafficEnabled(true);
fragment.getMap().setMyLocationEnabled(true);
fragment.getMap().animateCamera(CameraUpdateFactory
.newCameraPosition(position), null);
}
How do i achieve the above , can anyone suggest me ?
Thanks
You have written the method as,
private void moveAtmMap(Double amtLatitude,Double atmLongitude){
fragment.getMap().clear();
...
}
so every time this method will be called, it will clear all previous markers and you will end up having only the last marker.
Edit
for (int i = 0 ; i < urlDetails.length(); i++){
JSONObject json = urlDetails.getJSONObject(i);
String geometry = json.getString(GOEMETRY);
String vicinity = json.getString(VICINITY);
JSONObject jsonGeometry = new JSONObject(geometry);
String geoLocation = jsonGeometry.getString(LOCATION);
JSONObject jsonLatLng = new JSONObject(geoLocation);
double atmLat = jsonLatLng.getDouble(LATITUDE);
double atmLong = jsonLatLng.getDouble(LONGITUDE);
String atmName = json.getString(ATM_NAME);
runOnUiThread(new Runnable() {
#Override
public void run() {
moveAtmMap(atmLat, atmLong, atmName, vicinity, geometry);
}
});
}
and change method like,
private void moveAtmMap(Double amtLatitude,Double atmLongitude, String name, String vicinity, String geometry)
If you want to clear markers from previous web service hit, then do it before you start adding markers for new service hit, like before the for loop.
Remove this line from the method moveAtmMap:
fragment.getMap().clear();
For the first time, write it before for loop in onResponse.
Try this simple code,
for(int i=0;i<jsonArray.length();i++){
MarkerOptions markerOptions;
markerOptions = new MarkerOptions().position(new LatLng(lattitude,
longitude)
).title("Title").snippet("This is snippet");
markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.marker_icon));
marker = googleMap.addMarker(markerOptions);
}
Just replace lattitude,longitude with your values.
If you want to have instance of each marker,then you can put each "marker" object into hashmap with key as marker id. Let me know your feedback.
Note: remove this line - fragment.getMap().clear(); because it will clear map everytime when compiler comes into loop and it will take only last object. this is what happenng right now.
I tried to use reverse geocoding with AsyncTask but but the parameters of latitude and longitude that passes through the method doInBackground() are not happening correctly. any idea?
public class SitesAdapter extends ArrayAdapter<StackSite> {
public static Double lat;
public static Double lng;
#Override
public View getView(int pos, View convertView, ViewGroup parent){
...
lat = -1.80;
lng = -80.20;
...
}
public void start(){
new GetAddressTask(mContext).execute(lat, lng);
}
public static class GetAddressTask extends AsyncTask<Double, Void, String> {
//mContext
#Override
protected String doInBackground(Double... params) {
Geocoder gc = new Geocoder(mContext, Locale.getDefault());
List<Address> list = null;
String city = "";
double latitude = params[0];
double longitude = params[1];
try {
list = gc.getFromLocation(lat, lng, 1);
} catch (IOException e) {
e.printStackTrace();
}
if (list != null && list.size() > 0) {
Address address = list.get(0);
city = String.format("%s, %s", address.getAdminArea(), address.getCountryName());
}
return city;
}
#Override
protected void onPostExecute(String city) {
tituloTxt.setText(city);
}
}
}
error:
11-21 15:10:24.409: E/Trace(24502): error opening trace file: No such file or directory (2)
Well after so only had to do this to pass the coordinates. First add coordinate to constructor LatLng(double latitude, double longitude) and pass the parameters.
lat = -1.80;
lng = -80.20;
LatLng latlng = new LatLng(lat, lng);
new GetAddressTask(mContext).execute(lat, lng);
Then inside the doInbackground method get parameters.
public static class GetAddressTask extends AsyncTask<LatLng, Void, String> {
//mContext
#Override
protected String doInBackground(LatLng... params) {
Geocoder gc = new Geocoder(mContext, Locale.getDefault());
List<Address> list = null;
String city = "";
LatLng loc = params[0]; //Get all parameters: latitude and longitude
try {
list = gc.getFromLocation(loc.latitude, loc.longitude, 1); //get specific parameters
} catch (IOException e) {
e.printStackTrace();
}
if (list != null && list.size() > 0) {
Address address = list.get(0);
city = String.format("%s, %s", address.getAdminArea(), address.getCountryName());
return city;
}else{
return "City no found";
}
}
#Override
protected void onPostExecute(String city) {
tituloTxt.setText(city);
}
}
before calling execute method, u can just create a constructor ,in which you can initialize your class data members which can be further used in doInBackground(..).
Add two variables to your class and set them when you create async task, then use them in method. Simple.
public class GetAddressTask extends AsyncTask<String, Void, String> {
Context mContext;
float lat,lin;
public void setLat(int lat){...}
//rest of class
of course you can make everything static (fields and setters).
Edit.
If you are calling execute with some parameters, remember that your values have to be set before calling execute.