0

In one of my activities i need to be able to do a geocoding (find a location by address String search). The problem is that my results are much too broad. When i search for "mcdonalds" i get results that are in different parts of the USA. How can i make it so a user can search for nearby restaurants (or any location) and the results will be within a certain distance? I basically need more precise results for my application. Here is a screenshot of whats happening: enter image description here

public class MainActivity extends MapActivity {
HelloItemizedOverlay itemizedOverlay;
List<Overlay> mapOverlays;
Drawable drawable;


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    MapView myMap = (MapView) findViewById(R.id.mapview);
    myMap.setBuiltInZoomControls(true);

    MapController mc = myMap.getController();

    mapOverlays = myMap.getOverlays();
    drawable = this.getResources().getDrawable(R.drawable.androidmarker);
    itemizedOverlay = new HelloItemizedOverlay(drawable, this);

    //geopoints are cordinates in microdegrees or degrees * E6
    GeoPoint point = new GeoPoint(34730300, -86586100);
    //GeoPoint point2 = locatePlace("texas", mc); //HelloItemizedOverlay.locatePlace("Texas", mc, myMap);

    //overlayitems are items that show the point of location to the user
    OverlayItem overlayitem = new OverlayItem(point, "Hola, Mundo!", "im in huntsville");
    //OverlayItem overlayitem2 = new OverlayItem(point2, "Texas", "hi");

    //itemizedoverlay is used here to add a drawable to each of the points
    itemizedOverlay.addOverlay(overlayitem);
    //itemizedOverlay.addOverlay(overlayitem2);

    //this adds the drawable to the map

    //this method converts the search address to locations on the map and then finds however many you wish to see.
    locatePlace("mcdonalds", mc, 5);
    mapOverlays.add(itemizedOverlay);

    //this animates to the point desired (i plan on having "point" = current location of the user)
    mc.animateTo(point);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

@Override
protected boolean isRouteDisplayed(){
    return false;
}

public void locatePlace(String locName, MapController mc, int numberToDisplay)
{   // code to make the google search via string work

    // i use the Geocoder class is used to handle geocoding and reverse-geocoding. So make an instance of this class to work with the methods included
    Geocoder geoCoder1 = new Geocoder(this, Locale.getDefault());
    try {
        List<Address> searchAddresses = geoCoder1.getFromLocationName(locName, numberToDisplay);  // gets a max of 5 locations
        if (searchAddresses.size() > 0)
            {
            //iterate through using an iterator loop (for loop would have been fine too)
            //Iterator<Address> iterator1 = searchAddresses.iterator();
            for (int i=0; i < searchAddresses.size(); i++){
            //while (iterator1.hasNext()){
                //step1 get a geopoint
                GeoPoint tempGeoP = new GeoPoint( (int) (searchAddresses.get(i).getLatitude()*1E6), (int) (searchAddresses.get(i).getLongitude()*1E6) );
                //step2 add the geopoint to the Overlay item 
                OverlayItem tempOverlayItm = new OverlayItem(tempGeoP, locName, "this is " + locName);
                //step3 add the overlay item to the itemized overlay
                HelloItemizedOverlay tempItemizedOverlay = new HelloItemizedOverlay(drawable, this);  // its breakking here.........
                tempItemizedOverlay.addOverlay(tempOverlayItm);
                //the itemized overlay is added to the map Overlay
                mapOverlays.add(tempItemizedOverlay);
            }

            }
        } catch (IOException e)
        {
            e.printStackTrace();
            // Log.e("the error", "something went wrong: "+ e);
        }//finally   {}
    }
}

// here is the important code from the Itemized overlay class

public HelloItemizedOverlay(Drawable defaultMarker, Context context)
    {
        super(boundCenter(defaultMarker));
        myContext = context;
    }

    public void addOverlay(OverlayItem overlay){
        mOverlays.add(overlay);
        populate();
    }

Thanks, Adam

Here is some code after adjusting to Vishwa's comments:

 // these 2 variables are my current location
    latitudeCurrent  = 34730300;   // make this dynamic later
    longitudeCurrent = -86586100;  // make this dynamic later


LLlatitude  = (latitudeCurrent - 100000)/(1E6); //lowerleft latitude = original lat - (1)*degree/10
LLlongitude = (longitudeCurrent+ 100000)/(1E6);//lowerleft longitude = original longitude - (1)*degree/10
URlatitude  = (latitudeCurrent + 100000)/(1E6); //upperright latitude = original + (1)*degree/10
URlongitude = (longitudeCurrent+ 100000)/(1E6); //upperright longitude = original longitude + (1)*degree/10

        try {
            List<Address> searchAddresses = geoCoder1.getFromLocationName(locName, numberToDisplay, LLlatitude, LLlongitude, URlatitude, URlongitude); 

after creating a square of allowable results from the getfromlocationname()

Kara
  • 6,115
  • 16
  • 50
  • 57
Goku
  • 1,565
  • 1
  • 29
  • 62

1 Answers1

1

Here's what you need to do:

1.) Obtain the user's current location using GPS, here's an answer that'll help you do that.

2.) Next, figure out in what radius do you wish to display your results, i.e do you need results that are within 2 miles of the user's location or 5 miles or so on.

3.) Figure out what this (refers to point 2) translates into in terms of latitude and longitude values, so basically you will have to define a bounding-box with a lowerLeftLatitude, lowerLeftLongitude, lowerRightLatitude, lowerRightLongitude. These calculations can be done by figuring out how much one longitude translates into in terms of miles (again, this calculation will probably be approximate because the distance between longitude changes from places to place due to the very nature of how longitudes work (read this: http://en.wikipedia.org/wiki/Longitude if you wish to make adjustments based on each person's location)

4.) Use the following method (it's a variant of getFromLocationName) instead of using the version that you are using right now: http://developer.android.com/reference/android/location/Geocoder.html#getFromLocationName(java.lang.String, int, double, double, double, double). Read how this method works, basically you will be specifying the bounding box values as well now apart from the name (i.e McDonalds). So now, you will get more user-location-specific results.

Let me know how it goes/ if you need more help

Here's the code for getting the JSON response from the Places API: Once again DON'T forget to replace the "AddYourOwnKeyHere" with your Places API key

try
{
HttpPost httppost = new HttpPost("https://maps.googleapis.com/maps/api/place/search/json?location=34.730300,-86.586100&radius=19308&types=food&name=mcdonalds&sensor=false&key=AddYourOwnKeyHere");
HttpClient httpclient = new DefaultHttpClient();
response = httpclient.execute(httppost);
String data = EntityUtils.toString(response.getEntity());
JSONObject json = new JSONObject(data);
//Parse the JSONObject now
} catch (Exception e) {
e.printStackTrace();
}
Community
  • 1
  • 1
A Random Android Dev
  • 2,691
  • 1
  • 18
  • 17
  • so i tried what you said, but now i dont get any results displayed on the map. i set up the "square" (each side should be apox 12 miles since it is +-.1 degree from the center point) using the gerFromLocationName() but its still not finding any restaurants. It almost seems that the box is too small (even though there are like 10 mcdonalds in that area). Ill post the critical code above in my question. – Goku Oct 10 '12 at 19:24
  • Try running this url in your browser and : https://maps.googleapis.com/maps/api/place/search/json?location=34.730300,-86.586100&radius=19308&types=food&name=mcdonalds&sensor=false&key=AddYourOwnKeyHere (replace your key there) – A Random Android Dev Oct 10 '12 at 20:16
  • can you repost that link. it apears to be broken: { "html_attributions" : [], "results" : [], "status" : "REQUEST_DENIED" } – Goku Oct 10 '12 at 22:05
  • @adamkim once you open the link in a browser change the end of the url (it says key=AddYourOwnKey and replace that with key=//The Google Places API key you have//) as I said in my earlier comment, replace your key in the url. – A Random Android Dev Oct 10 '12 at 22:46
  • Sorry google places api key? ill go get one. I had no idea what google places was – Goku Oct 11 '12 at 14:37
  • So i got the api key and i see the returned json. How do i get my android application to get the callback from that URL? I think i know how to parse the Json if i can just get the data in my app – Goku Oct 12 '12 at 19:03
  • @adamkim I've added the code to get the callback from the URL. It's a basic HTTPPost request. Hope this solves all your issues, cheers! – A Random Android Dev Oct 12 '12 at 20:53
  • Thanks! ill try it over the weekend – Goku Oct 12 '12 at 21:03
  • Where can I go to learn about the methods and objects you are using (HTTPPose, HTTPClient, DefaultHTTPClient() etc.)? it really bothers me to do copy paste programming so i would like to learn what exactly is going on. Thanks again – Goku Oct 12 '12 at 22:38
  • 1
    Well, the way I learn these things is by googling each term followed by 'android'. So, to learn about DefaultHTTPClient, you would google 'DefaultHTTPClient Android' and click on the official developer.android.com/randomstuffintheURL. So in the case of DefaultHTTPClient that page would be: http://developer.android.com/reference/org/apache/http/impl/client/DefaultHttpClient.html Cheers – A Random Android Dev Oct 13 '12 at 02:34
  • Vishwa, one last question for you. I am getting a problem located at this question (still unresolved): http://stackoverflow.com/questions/12904818/how-do-i-figure-out-how-to-debug-this-httpresponse/12905105#comment17509911_12905105 the only main difference between this and your code is that the instead of response = httpclient.execute(httppost); i did: HttpResponse response = httpclient.execute(httppost); execute() returns an HttpResponse object so this sould be right? im getting an exception but not sure how i fix it. thanks a ton. – Goku Oct 17 '12 at 14:23
  • 1
    @adamkim instead of using https://maps.googleapis.com/blahblahblah use http instead, so it would be http://maps.googleapis.com/blahblahblah. The HTTPS is provided to as an option if you wish to be extra cautious about things like user location and stuff. Don't worry about it though, it's not imperative that you use it. – A Random Android Dev Oct 17 '12 at 16:12