Saturday, August 22, 2009

Building location aware applications

There are 3 basic ways your typical smart phone can acquire a location fix, these being :

  • Cell Tower Triangulation
  • GPS
  • WiFi Scanning
Cell Tower Triangulation is the least accurate of the 3 methods. The accuracy varies by about 2-5 km in my experience. But it does have a couple of advantages, it works fine indoors and is quick to compute.

GPS is the one most people are familiar with, and it offers the highest accuracy. It can pinpoint your location down to a few meters. However, it typically doesn't work well indoors (if at all), and acquiring an accurate fix can take up to several minutes. The longer the GPS is running the more accurate a fix can be obtained.

WiFi Scanning is relatively a new idea and is pretty interesting one. Imagine sending out a fleet of vehicles down every major thoroughfare, each armed with sensitive WiFi detection equipment. You then record the location of every WAP they detect along with the relative signal strength. Once you've collected enough data, any WiFi enabled device in the area can look around at the nearby WAPs (it doesn't actually have to connect to them), and use the data to deduce a reasonable approximation of the device's current position. It's fast to compute, it works indoors, and has decent accuracy (I typically get about 200m). Another interesting aspect of this type of system is that it can correct/improve itself. If you have a WiFi fix and a GPS fix at the same time, that information can be recorded to improve accuracy in the future.

You want to avoid writing any type of application that requires continuous/real-time location data for extended periods of time. The bottom line is, if you're crunching GPS data, the CPU is not sleeping, and you're running down the battery. The best you can do is to wake the device up at repeated intervals, get a fix, and then let it go back to sleep. This is a realistic technique and it works, but is not without limitations. An application designed to alert you when a friend is "nearby", would always have the chance of not polling for a fix was while your friend was within range. So you have to find a balance between the polling frequency, and the granularity that your app requires.

Also never underestimate the finicky nature of users regarding battery life. If they feel their device's battery is suddenly under-performing, they will look for an application to blame. If they see a flashing GPS icon, it's usually the first thing that raises an eyebrow.

Wednesday, August 19, 2009

blog relocation

This blog has been relocated to http://foo.jasonhudgins.com/, if you try and hit the old blog page you'll be redirected here. I'm currently swamped with work and falling behind on my blogging, but I've got a couple of new posts floating around in my head.

Monday, August 3, 2009

HTTP connection reuse in Android

Alright, time for something new and hopefully useful, re-using HTTP connections in your application.

I've yet to write an Android application that doesn't make any HTTP requests, and they tend to do it frequently. Since all of my applications are also heavily concurrent, passing around a default HttpClient instance will give you thread contention issues and possibly bad dreams later that night. Establishing a new TCP connection to the same server for each request is wasteful, so I'd like to be able to re-use those connections, via the same HttpClient, and do so in a thread safe way.

This is easily accomplished with a singleton/factory thingy like so:


public class HttpClientFactory {

private static DefaultHttpClient client;

public synchronized static DefaultHttpClient getThreadSafeClient() {

if (client != null)
return client;

client = new DefaultHttpClient();

ClientConnectionManager mgr = client.getConnectionManager();

HttpParams params = client.getParams();
client = new DefaultHttpClient(
new ThreadSafeClientConnManager(params,
mgr.getSchemeRegistry()), params);

return client;
}
}

Now whenever you need an HttpClient instance in your app, you can just do this:

HttpClient client = HttpClientFactory.getThreadSafeClient();

Like most things in HttpClient 4.x, it's very easy to do, the hardest part is just figuring out exactly how to do it. A buddy @google told me that 4.x just performs so better than 3.x that was the reason for the behind switch (early versions of Android used the 3.x releases). Until next weekend..