LocationManager calling onLocationChanged too often?

后端 未结 3 618
借酒劲吻你
借酒劲吻你 2021-02-03 12:14

I\'ve set up the LocationManager to get the current location every 2 minutes:

locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 120000, 0, thi         


        
相关标签:
3条回答
  • 2021-02-03 12:56

    this is my LocationListener implementation to filter out unnecessary onLocationChanged() events:

    NOTE I use messages in my service.

    public class GPSlocationListener implements LocationListener 
    {
        //member variables
        private Handler mParentHandler;//points to Handler of parent
        private long mTimeBetweenLocationEvents;
        private long mTimeOfLastLocationEvent;
        private boolean mAccuracyOverride;
        private float mLastAccuracy;
        private boolean mOverrideLocation;
    
        //constants
        private static final float INVALID_ACCURACY = 999999.0f;
        private static final String TAG = "GPSlocationListener";
    
    
        //constructor
        public GPSlocationListener(Handler parentMsgHandler, long timeBetweenLocationEvents, boolean accuracyOverride)
        {
            mParentHandler = parentMsgHandler;
            mTimeOfLastLocationEvent = 0;
            mAccuracyOverride = accuracyOverride;
            mLastAccuracy = INVALID_ACCURACY;
            mOverrideLocation = false;
            mTimeBetweenLocationEvents = timeBetweenLocationEvents;
        }
    
        //EVENT: onLocationChanged()
        // send GPS coordinates to CommService
        public void onLocationChanged(Location loc)
        {
            Log.d(TAG, "onLocationChanged() triggered. Accuracy = "+Float.toString(loc.getAccuracy()));
            mOverrideLocation = false;
    
            if (loc != null)
            {
                //if a more accurate coordinate is available within a set of events, then use it (if enabled by programmer)
                if (mAccuracyOverride == true)
                {
                    //whenever the expected time period is reached invalidate the last known accuracy
                    // so that we don't just receive better and better accuracy and eventually risk receiving
                    // only minimal locations
                    if (loc.getTime() - mTimeOfLastLocationEvent >= mTimeBetweenLocationEvents)
                    {
                        mLastAccuracy = INVALID_ACCURACY;
                    }
    
    
                    if (loc.hasAccuracy())
                    {
                        final float fCurrentAccuracy = loc.getAccuracy();
    
                        //the '<' is important here to filter out equal accuracies !
                        if ((fCurrentAccuracy != 0.0f) && (fCurrentAccuracy < mLastAccuracy))
                        {
                            mOverrideLocation = true;
                            mLastAccuracy = fCurrentAccuracy;
                        }
                    }
                }
    
                //ensure that we don't get a lot of events
                // or if enabled, only get more accurate events within mTimeBetweenLocationEvents
                if (  (loc.getTime() - mTimeOfLastLocationEvent >= mTimeBetweenLocationEvents)
                    ||(mOverrideLocation == true) )
                {
                    //be sure to store the time of receiving this event !
                    mTimeOfLastLocationEvent = loc.getTime();
    
                    //send message to parent containing the location object
                    Message msgToMain = mParentHandler.obtainMessage();
                    msgToMain.what = Constants.MSG_LOCATION_CHANGED;
                    msgToMain.obj = loc;
                    mParentHandler.sendMessage(msgToMain);
                }
            }
        }
    
        public void onProviderDisabled(String provider)
        {
            // TODO Auto-generated method stub
        }
    
        public void onProviderEnabled(String provider)
        {
            // TODO Auto-generated method stub
        }
    
        public void onStatusChanged(String provider, int status, Bundle extras)
        {
            // TODO Auto-generated method stub
        }
    
    } 
    

    this is implemented as follows in your main code:

    //create the APIthread (which exposes mAPIhandler back to this service)
    mAPIthread = new APIthread(mApiHandler);
    mAPIthread.start();
    
    
    //use the LocationManager class to obtain GPS locations
    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);    
    
    locationListener = new GPSlocationListener(mApiHandler, Constants.LOCATION_UPDATE_PERIOD_MSEC, true);
    
    //this will call GPSlocationListener.onLocationChanged()
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 
                                           //3 mins NOTE: approximate value
                                           Constants.LOCATION_UPDATE_PERIOD_MSEC,
                                           //no distance updates desired
                                               0,
                                               locationListener);
    
    0 讨论(0)
  • 2021-02-03 13:00

    From the documentation of requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener) concering the minTime parameter:

    "the minimum time interval for notifications, in milliseconds. This field is only used as a hint to conserve power, and actual time between location updates may be greater or lesser than this value."

    So the answer to your questions, yes this is standard behavior and, no you cannot change this.

    If this is a problem for you, you could ignore calls to the callback method if a certain amount of time hasn't passed.

    0 讨论(0)
  • 2021-02-03 13:17

    I found this question because I had the same problem.

    I believe I have the answer. The rapid updates are being fired because you have the meters parameter set to 0.

    Change the meters parameter to something like 10 and it will only fire the LocationChanged event every 2 minutes IF your location changed by 10 or more.

    Before I made this change, LocationChanged was firing multiple times a second. Now, it fires once. Then every 2 minutes, you will see the GPS icon on the status bar, but unless your location changed, the event doesn't fire.

    I hope this helps. This is what fixed it for me. Didn't have to add any extra logic to prevent false fires.

    0 讨论(0)
提交回复
热议问题