user1096447
user1096447

Reputation: 429

How to get a single location fix from LocationManager, with a timeout?

I am using LocationManager to get a single location fix:

public class MyActivity extends Activity {
    private LocationManager lm;
    private ProgressDialog myDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        LocationListener ll = new MyLocationListener();
        lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1, 1, ll);
        myDialog = ProgressDialog.show(this, null , "Determining Your Location", true);
    }

    class MyLocationListener implements LocationListener {
        public void onLocationChanged(Location location) {
            if (location != null) {
                ...

                lm.removeUpdates(this);
                myDialog.dismiss();
            }
        }
    }
}

As this stands listening for a location could potentially go on forever if a location fix cannot be found. I want to add some robustness to my code by ceasing to listening for a location after 60 seconds, and displaying an error to the user to saying that their location could not be determined.

How can I do this?

Upvotes: 2

Views: 2011

Answers (3)

Adrian Toman
Adrian Toman

Reputation: 11486

You could either user a Handler, Timer or AlarmManager to implement the timeout by calling LocationManager.removeUpdates to stop listening.

A Timer creates an new thread, which may be overkill. The documentation for AlarmManager suggests that "(f)or normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler". The documentation for Handler describes one of the main uses for a Handler is "to schedule messages and runnables to be executed as (sic) some point in the future."

All signs point to Handler as being the most appropriate method of implementing the timeout.

public class MyActivity extends Activity implements LocationListener {
    private final int TIMEOUT = 60000;

    private LocationManager myLocationManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        myLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        myLocationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER,
            this, null);

        Runnable myRunnable = new Runnable() {
            public void run() {
                myLocationManager.removeUpdates(QualityCheckActivity.this);
                // other timeout error code
            }
        };

        Handler myHandler = new Handler();
        myHandler.postDelayed(myRunnable, TIMEOUT);
    }

    @Override
    public void onLocationChanged(Location location) {
        // location fixed code 
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) { }

    @Override
    public void onProviderEnabled(String provider) { }

    @Override
    public void onProviderDisabled(String provider) { }
}

NOTES:

TIMEOUT is, of course, the timeout length in milliseconds. In this case 60,000 milliseconds, or 60 seconds.

I have chosen to implement the LocationListener interface on MyActivity itself so that the LocationListener is easier to access within the Runnable.

Instead of calling LocationManager.requestLocationUpdates: I'm using LocationManager.requestSingleUpdate which will supply just one location fix.

I deliberately haven't implemented Activity.onPause and Activity.onResume. Both the location listening, and timeout, will continue if the Activity is paused.

Upvotes: 2

sunghun
sunghun

Reputation: 1424

You can use Timer and TimerTask as well. When you create handler to utilise postDelayed, you should be careful of memory leak because the handler still refer your Activity or Service event after they are already finished. PostDelayed will be going to the message queue in the main thread. So, make your handler as static or use weak reference.

You need to consider following code to avoid the memory leak.

public class MyService extends Service {

   private static class MyHandler extends Handler {
      WeakReference<MyService> ref;

      public MyHandler(MyService r) {
         ref = = new WeakReference<MyService>(r);
      }

      public void handleMessage(Message msg) {

         MyService service = ref.get();
         if (servic==null) {
            return;
         }

         //Do something here
     }

   }

}

Upvotes: -1

pdiddy
pdiddy

Reputation: 6297

One way would be to use a Handler and use postDelayed after 60 sec to stop the listener.

Handler postDelayed

Upvotes: 1

Related Questions