【问题标题】:LocationManager calling onLocationChanged too often?LocationManager 调用 onLocationChanged 过于频繁?
【发布时间】:2012-03-17 12:39:31
【问题描述】:

我已将 LocationManager 设置为每 2 分钟获取一次当前位置:

locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 120000, 0, this);

这可以正常工作,并且按预期每 2 分钟调用一次 onLocationChanged。但是,它似乎在 10-40(随机数量)秒跨度 2 分钟内被多次调用。我记录了 onLocationChanged 中收到的每个位置,所以这里有一些示例可以了解发生了什么:

17:30

GPS 32.0 50.66318929195404 10.735434293746948 0.0 2010.08.07 17:30:10
GPS 32.0 50.66315710544586 10.735423564910889 0.0 2010.08.07 17:30:14
GPS 32.0 50.66314101219177 10.735418200492859 0.0 2010.08.07 17:30:17
GPS 32.0 50.66314101219177 10.735418200492859 0.0 2010.08.07 17:30:20
GPS 24.0 50.66313564777374 10.735418200492859 0.5 2010.08.07 17:30:24
GPS 32.0 50.663098096847534 10.735573768615723 0.0 2010.08.07 17:30:28         
GPS 32.0 50.663065910339355 10.735611319541931 0.0 2010.08.07 17:30:31

然后我在 2 分钟内没有更新。

17:32

GPS 32.0 50.661821365356445 10.737022161483765 1.0 2010.08.07 17:32:39
GPS 16.0 50.66170871257782 10.737043619155884 1.8200275 2010.08.07 17:32:45
GPS 24.0 50.661579966545105 10.737027525901794 1.25 2010.08.07 17:32:50
GPS 16.0 50.66150486469269 10.73712408542633 1.0 2010.08.07 17:32:55
GPS 12.0 50.661579966545105 10.73715090751648 0.9013878 2010.08.07 17:33:01
GPS 24.0 50.66139221191406 10.737038254737854 1.5811388 2010.08.07 17:33:06
GPS 16.0 50.66141366958618 10.737301111221313 0.70710677 2010.08.07 17:33:12
GPS 16.0 50.66141366958618 10.737301111221313 0.70710677 2010.08.07 17:33:12
GPS 24.0 50.661311745643616 10.737070441246033 1.118034 2010.08.07 17:33:16
GPS 16.0 50.66122591495514 10.737177729606628 1.118034 2010.08.07 17:33:22
GPS 12.0 50.66124200820923 10.737220644950867 1.3462912 2010.08.07 17:33:26
GPS 12.0 50.661311745643616 10.737268924713135 3.6055512 2010.08.07 17:33:25

以此类推……然后在 2 分钟后的 17:35 进行另一组更新。

这是标准行为吗?我预计每 2 分钟只能获得 一个 位置,而它为我提供位置更新的时间跨度似乎相当随机。理想情况下,我宁愿只获得一个位置...有没有办法做到这一点?

【问题讨论】:

    标签: android


    【解决方案1】:

    来自requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener) 的关于minTime 参数的文档:

    “通知的最小时间间隔,以毫秒为单位。此字段仅用作省电提示,位置更新之间的实际时间可能大于或小于此值。”

    因此,您的问题的答案是,是的,这是标准行为,不,您无法更改。

    如果这对您来说是个问题,如果没有经过一定的时间,您可以忽略对回调方法的调用。

    【讨论】:

      【解决方案2】:

      我发现这个问题是因为我遇到了同样的问题。

      我相信我有答案。快速更新正在被触发,因为您将仪表参数设置为 0。

      将 Meters 参数更改为 10 之类的值,如果您的位置更改了 10 或更多,它只会每 2 分钟触发一次 LocationChanged 事件。

      在我进行此更改之前,LocationChanged 每秒会触发多次。现在,它会触发一次。然后每隔 2 分钟,您会在状态栏上看到 GPS 图标,但除非您的位置发生变化,否则该事件不会触发。

      我希望这会有所帮助。这就是为我解决的问题。无需添加任何额外的逻辑来防止误触发。

      【讨论】:

      • +1 - 我当前的设置是 10 米,每 60000 毫秒(1 分钟)一次,当我静止时,位置监视器每 5-10 秒触发一次。我将距离更改为 20 米,并且更新的频率大大降低了......但仍然是零星的和不可预测的。
      【解决方案3】:

      这是我的 LocationListener 实现,用于过滤掉不必要的 onLocationChanged() 事件:

      注意我在我的服务中使用消息。

      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
          }
      
      } 
      

      这在您的主代码中实现如下:

      //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);
      

      【讨论】:

      • 启用accuracyOverride,这会将onLocationChanged()事件的消息减少到每个时间段的两个或三个。否则只有一个。附言public static final int LOCATION_UPDATE_PERIOD_MSEC = 3 * 60 * 1000;//3 分钟
      猜你喜欢
      • 1970-01-01
      • 2011-06-30
      • 1970-01-01
      • 1970-01-01
      • 2013-12-28
      • 2019-12-28
      • 2016-04-29
      • 1970-01-01
      • 2012-02-17
      相关资源
      最近更新 更多