views:

86

answers:

4

Hello everyone. I'm currently developing an app for Android which uses google map service. Because users will be able to see thousands of markers I would like to load only those which are currently within the map bounds (i.e. when user look at specific map tile). I know how to do it with javascript/html. However, Android doesn't seem to provide any similar methods such as containsLatLng(latlng) or getBounds (I only found getLatitudeSpan and getLongitudeSpan, but don't know how can I use them in order to achieve the similar effect).

Can anyone give me some hint on that? I would greatly appreciate any help or at least pointing myself in the right direction.

+2  A: 

You could use getMapCenter and just add or subtract the latitude span or longitude span (divided by 2 of course) to find the bounds.

LordTwaroog
Thank you for the hint Twaroog - it worked quite well. I was able to move further with my project a bit thanks to you.
Pavel
No problem, I do it the same way in my project as well.
LordTwaroog
+2  A: 

Where are those place-marks coming from? If they are coming from a web service, check if the web service supports spatial queries. If its a basic point in extent (rectangular envelope) you could do something like this:

Note: (xmin, ymin -> xmax, ymax) are the bounds of your rectangle (extent).

def is_point_in_rect(px, py, xmin, ymin, xmax, ymax):
  if px >= xmin and px <= xmax:
    if py >= ymin and py <= ymax:
      return True
  else:
    return False

This is something very simple. You can even use the Google Maps Data API to store your place-marks and that has a mechanism to execute spatial queries.

If your data is on Google App Engine, then you could use GeoPt based queries or you could roll your own spatial index. Check out http://code.google.com/p/geomodel/

Rahul
They are coming from local sql db at the moment Rahul, but in the future I would like to expand this to remote db as well.
Pavel
+2  A: 

Hi,

I'm doing something similar to yourself but I'm using a server. The reason I'm doing so is for computational reasons. When the application first starts a HTTP request is sent to a php script which contains a MySQL query. The php script recieves the users current lat / long and gives back in a JSON all points within 1KM of the current location. The application then parses that JSON into a local MySQL database and does stuff with it.

To send the HTTP request and parse the JSON into a database I'm doing the following..

  //http post
 try{
         HttpClient httpclient = new DefaultHttpClient();
         HttpPost httppost = new HttpPost("http://URL");
         httppost.setEntity(new UrlEncodedFormEntity(parameters));
         HttpResponse response = httpclient.execute(httppost);
         HttpEntity entity = response.getEntity();
         InputStream is = entity.getContent();

 //convert response to string

        BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
         StringBuilder sb = new StringBuilder();
         String line = null;
         while ((line = reader.readLine()) != null) {
                 sb.append(line + "\n");
         }
         is.close();

         result=sb.toString();
 }catch(Exception e){
     new AlertDialog.Builder(this)
      .setTitle("Woops!")
      .setMessage("Getlocations:It appears the server is not reachable. Check your connectivity and try again.")
      .setPositiveButton("Ok", new DialogInterface.OnClickListener() {

        public void onClick(DialogInterface dialog,
                int which) {
            //User wants to start activity..

        }
       })
       .show();
         Log.e("log_tag", "Error in connection or convert "+e.toString());
 }

 //parse json data
 try{
     System.out.println("parsing data");
         JSONArray jArray = new JSONArray(result);
         if(icount != 0){
             try{
                 SQLiteDatabase db = tweets.getWritableDatabase();
                 db.delete(TABLE_NAME,null,null);
             }finally {
                 tweets.close();
             }
         }
         //TODO: Change this to num
         for(int i=0;i<jArray.length() && q < 1;i++){
             System.out.println("ARRAY LENGTH " +  jArray.length());
                q++;
                 JSONObject json_data = jArray.getJSONObject(i);

                        System.out.println("Getting Info");
                         Double lat = json_data.getDouble("lat");
                         Double lng = json_data.getDouble("lng");
                         String link = json_data.getString("link");
                         String message = json_data.getString("message");
                         String sname = json_data.getString("sname");
                         String name = json_data.getString("name");
                         //Add each entry to SQL database...
                         System.out.println("Adding table row!");
                         try{
                             addloc(name,sname,message,link,lat,lng);
                         } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } finally {
                             tweets.close();
                         }
                         count();


        }
 }catch(JSONException e){
     new AlertDialog.Builder(this)
      .setTitle("Woops!")
      .setMessage("Getlocations: It appears something went wrong processing the information.")
      .setPositiveButton("Ok", new DialogInterface.OnClickListener() {

        public void onClick(DialogInterface dialog,
                int which) {
            //User wants to start activity..

        }
       })
       .show();
         Log.e("log_tag", "Error parsing data "+e.toString());
 }

For this to work all you need is a short php file which takes the Lat / lng Something like...

  <?php
  mysql_connect("host","user","pass");
  mysql_select_db("database");
  $lat = $_REQUEST['currlat'];
  $lng = $_REQUEST['currlng'];
  $q=mysql_query("QUERY") or die(mysql_error());
  if (mysql_num_rows($q) == 0) {
 echo "No rows found, nothing to print so am exiting";
exit;
 }
if(!q){
echo "NO RESULT";
exit;
}
 while($e=mysql_fetch_assoc($q))
    $output[]=$e;
 print(json_encode($output));

 mysql_close();
 ?>

That'll take in the values and print results in JSON.

//edit: To get the lat / lng in the first place I'm using the GPS.

Hope this helps.

Aidanc
Interesting Aidanc. This is is indeed very helpful. Thank you very much for sharing this code!
Pavel
No problem, note in my php I'm not using prepared statements. If you were to make this production code you'd need to knock that around a little bit.
Aidanc
+2  A: 

The answer would depend on where your markers are coming from. Are they stored within the Android device itself or are they coming from a web server? Either way, if you need to represent thousands of locations symultaneously you might need to implement some form of clustering, which can be done on the client or on the server, if markers come from the web.

See, for example this server side clusterer (2 different versions):

http://maps.forum.nu/server_side_clusterer

http://maps.forum.nu/server_side_clusterer/index2.php

or a client side clusterer:

http://gmaps-utility-library.googlecode.com/svn/trunk/markerclusterer/1.0/

Another alternative would be to use custom tiles, (like Google does), but depending on your exact needs it may be overkill.

Marcelo