GPS in an AsyncTask in Android

I recently encountered the need to have an AsyncTask in an Android app that gets the current GPS position, then fetches some data from the network upon getting the position. This isn’t very straightforward to do, since the GPS stuff uses a callback driven model. I did a quick search and came up with a lot of Stack Overflow solutions to the problem that were really bad. Most of them suggested launching a GPS request, then having some sort of loop that spins until the location comes in. At least one of them didn’t even have any sort of delay in the loop, making it burn up your phone’s battery while it waited.

It turns out to be pretty simple to solve this problem, using the Looper class, which is a bit of a confusing thing. The looper will establish a loop which waits for events/messages within the AsyncTask thread. Once the position comes in, you have the code exit the loop, and then continue on with your network request. Here’s the basic idea:


public class AsyncTaskGps extends AsyncTask implements LocationListener {
private Location location;
@Override
protected Object doInBackground(Objectarg0) {
LocationManager lm = (LocationManager) arg0[0];
Looper.prepare();
// Request GPS updates. The third param is the looper to use, which defaults the the one for
// the current thread.
lm.requestSingleUpdate(LocationManager.GPS_PROVIDER, this, null);
Looper.loop(); // start waiting…when this is done, we'll have the location in this.location
try {
// now go use the location to load some data
URL url = new URL("…?latitude="+location.getLatitude()+"&longitude="+location.getLongitude());
URLConnection con = url.openConnection();
InputStream is = con.getInputStream();
byte[] data = new byte[1024];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len = –1;
do {
len = is.read(data);
if (len > 0) {
baos.write(data, 0, len);
}
} while (len > –1);
// parse data and do stuff…
} catch (IOException e) {
Log.e("LoadScheduleTask", "Error", e);
} catch (JSONException e) {
Log.e("LoadScheduleTask", "Error", e);
}
return null;
}
@Override
protected void onPostExecute(Object result) {
// notify someone we are done…
}
@Override
public void onLocationChanged(Location location) {
// Store the location, then get the current thread's looper and tell it to
// quit looping so it can continue on doing work with the new location.
this.location = location;
Looper.myLooper().quit();
}
}

3 thoughts on “GPS in an AsyncTask in Android

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s