GPSmaster
GPSmaster

Reputation: 914

How to time out GPS signal acquisition

My app uses the LocationListener to get one position fix and then removeUpdates() once every minute (to conserve battery). The problem is that if a user moves inside then it will perpetually look for a signal, burning more battery. I was wondering if anyone knows of a public method within Location Manager I can use to removeUpdates if a signal isn't acquired within 15 seconds. I would then check for a position fix every five minutes until the user moves back outdoors. Does this make sense? Maybe there is a better method to timeout GPS signal acquisition? I have looked through the Location Manager public methods but I can't seem to find a way to do it. Thanks so much for your help! -Dom

Upvotes: 9

Views: 10591

Answers (3)

Max Belli
Max Belli

Reputation: 187

Well my solution to this problem is somewhat very simple and I don't know if it's good practice. Let's assume we have a long named timeToQuit that determines how many millis you wanna wait before aborting the search for a position just put:

locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 
                              2000, 0, locationListener);
Handler handler = new Handler();    // android.os.Handler
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        locationManager.removeUpdates(locationListener);
    }
};
handler.postDelayed(runnable, timeToQuit);

Of course you have to have a LocationListener and your own LocationListener. Values in locationManager.requestLocationUpdates are from my app so you propapbly should adapt them. This code works like a charm for me. I know I'm a little late, but I couldn't find this approach anywhere and propably it helps someone. Cheers

Upvotes: 0

GPSmaster
GPSmaster

Reputation: 914

So this is what I ended up doing.

This is what i added to the LocationListener note the global variables timertest and loccounter:

public class MyLocationListener implements LocationListener

{
    public void onStart() {
        if (timertest==false) {
            timertest=true;
            serviceHandler = new Handler();
            serviceHandler.postDelayed( new timer(),1000L );
        }
    }
    class timer implements Runnable {
          public void run() {
            ++loccounter;
            if (runtest==true && loccounter>8) {
                dt=200;
                runtest=false;
                stoplistening();
            } else serviceHandler.postDelayed( this, 1000L );
          }
    }
}

I start the timer right before requesting location updates.

public void locupdate(int minTime, float minDistance) {
    mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    mlocListener = new MyLocationListener();
    if (mlocListener != null && mlocManager != null) {
        mlocManager.removeUpdates(mlocListener);
    }
    loccounter=0;
    ((MyLocationListener) mlocListener).onStart();
    runtest=true;
    mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
                minTime, minDistance, mlocListener);
}

and one last method within the location listener:

    public void stoplistening() {
        mlocManager.removeUpdates(mlocListener);
        loccounter=0;
    }

Hope this helps someone

Upvotes: 4

lomza
lomza

Reputation: 9726

Although GPSmaster's answer is accepted, I want to post the link to more elegant and simpler solution, I think - https://gist.github.com/777790/86b405debd6e3915bfcd8885c2ee11db2b96e3df. I have tried it myself and it worked =)

In case the link doesn't work, this is a custom LocationListener by amay077:

/**
 * Initialize instance.
 *
 * @param locaMan the base of LocationManager, can't set null.
 * @param timeOutMS timeout elapsed (mili seconds)
 * @param timeoutListener if timeout, call onTimeouted method of this.
 */
public TimeoutableLocationListener(LocationManager locaMan, long timeOutMS,
        final TimeoutLisener timeoutListener) {
    this.locaMan  = locaMan;
    timerTimeout.schedule(new TimerTask() {

        @Override
        public void run() {
            if (timeoutListener != null) {
                timeoutListener.onTimeouted(TimeoutableLocationListener.this);
            }
            stopLocationUpdateAndTimer();
        }
    }, timeOutMS);
}

/***
 * Location callback.
 *
 * If override on your concrete class, must call base.onLocation().
 */
@Override
public void onLocationChanged(Location location) {
    stopLocationUpdateAndTimer();
}

@Override
public void onProviderDisabled(String s) { }

@Override
public void onProviderEnabled(String s) { }

@Override
public void onStatusChanged(String s, int i, Bundle bundle) { }

private void stopLocationUpdateAndTimer() {
    locaMan.removeUpdates(this);

    timerTimeout.cancel();
    timerTimeout.purge();
    timerTimeout = null;
}

public interface TimeoutLisener {
    void onTimeouted(LocationListener sender);
}

Upvotes: 8

Related Questions