Search code examples
androidgpscontrol-flow

What is the correct control flow for getting a one-time fix on the user's location (via GPS)?


I'm looking to find the "correct" way to get a fix on the user's location as a one-time task. At the moment, my execution flow is roughly:

  1. The user presses a button.
  2. The handler (contained in the main Activity code) registers a GPS location listener with the system, set to update as fast as possible, launches an ASyncTask, and finishes.
  3. Pre-execution, the ASyncTask generates a ProgressDialog, effectively blocking any other UI usage.
  4. For it's background task the ASyncTask waits for either a timeout or for a location fix for the GPS.
  5. Post-execution, the ASyncTask either displays some relevant data to the user if a location was found, or displays an error in a toast if it was not. It also de-registers the listener of course.

Now, while this works, there are numerous downsides. Firstly, and quite obviously, all other UI interaction with the app is blocked while a request is being made. This isn't too bad currently, as the app's main function is to perform this task, and there isn't much else to do while it's working - it also stops the user from spamming the button. Additionally, I'm not sure if the post-execution phase of the ASyncTask is really the place to put my location-found logic (it makes an internet call, which is something that itself might be better off inside an ASyncTask?). However, I'm not sure how else to pass back the fact that a location has been found and that the main thread should do something.

I was hoping that someone could inform me as to the "right" way to do this - i.e. is using an ASyncTask like this correct, should there be a Service involved, and how should I deal with the internet-call post-location-found), and perhaps even give some wise words on how in general to deal with the control flow of an app which has to make somewhat "blocking" calls.

I can provide code if needed, might take a bit to get it cut down to a minimum solution.


Solution

  • Blocking calls and blocking UIs are generally to be avoided. See Reto Meier's take on the subject.

    Hence, I'd dump the AsyncTask entirely. Disable the Button that the user uses to kick off the fix request. Use a postDelayed() Runnable for your timeout mechanism. And, allow the user to do something (read help, etc.). Use the progress indicator in the title bar to indicate that you're working on getting the location, dismissing the indicator when you get a fix or when your timeout occurs.

    (it makes an internet call, which is something that itself might be better off inside an ASyncTask?)

    It certainly should not be done on the main application thread. When the location fix comes in, kick off the AsyncTask to fetch the data.