Android – 跨多个活动实现LocationListener的最佳方式

我一直在这个问题上停留了一段时间。 我正在开发一个应用程序,在几个不同的活动中使用相当广泛的位置。 我find的每个例子都在每个Activity中使用一个单独的LocationListener。 这在我的情况下是不可行的。

我想知道在多个活动中跟踪用户位置的最有效的方法是什么。 现在,我创build了一个实现LocationListener的服务,并使用广播来更新Activity基类中的静态lat和long字段。 这意味着服务总是在运行,这并不理想。 但是,如果我closures了服务并且只在需要的时候重新启动它,那么获得一个好的位置需要时间。 我需要在Activity的onCreate()中的位置数据。 如果我尝试在活动基类中实现它,那也是一样的。 如果我不断地在onResume / onCreate中注册监听器,并在onPause()中取消注册,则需要花费太多的时间来开始接收更新。 我也尝试创build一个服务,我可以绑定,所以它只在我需要一个位置时开始。 但是我有同样的问题,绑定到服务并开始获取更新需要很长时间。

我现在使用的服务可以工作,但是从我读过的所有内容来看,我不应该使用一个不断运行的服务来处理这样的琐事。 但应用程序的全部重点是根据用户的当前位置提供相关的数据。 所以我有一个服务只是在后台运行,并定期提供更新。 导致我在这一点上重新审视devise的一个主要问题是,我最近发现,如果用户在没有打开GPS的情况下启动应用程序,然后启用onProviderEnabled(),则不会调用onProviderEnabled()。 在这种情况下,应用程序无法识别GPS已启用,因此可以开始监听更新。

我认为我从看例子中了解LocationManager和LocationListener,但似乎无法将其应用于需要多个活动中的位置数据的情况。 任何帮助或build议将不胜感激。

我通常会实现这个要求的方式是使用绑定的Service实现,如SDK文档中的Local Service Sample中的实现。 显然你熟悉服务的优点,只允许你创build一次所有的位置代码。

通过绑定访问服务允许服务启动和停止自己,这样当应用程序不在前台时它不会运行(只要不再有活动被绑定,它就会死掉)。 关键在IMO做好这个工作的方法是在onStart()和UNBIND中的onStop()绑定服务,因为当你从一个Activity移动到另一个Activity时,这两个调用重叠(第二个Activity在第一个Activity停止前启动)。 当在应用程序内部移动时,这使服务免于死亡,并且只在整个应用程序(或至less对位置感兴趣的任何部分)离开前景时才使服务死亡。

使用绑定,您不必在广播中传递位置数据,因为活动可以直接调用服务上的方法来获取最新的位置。 然而,作为一种指示新的更新何时可用的方法,广播仍然是有利的…但是这只是成为通知监听活动调用服务上的getLocation()方法。

我的$ 0.02。 希望帮助!

我遇到了同样的问题,我尝试用Devunwired的良好答案来解决这个问题,但是我遇到了一些麻烦。 我找不到停止服务的方法,当我完成我的应用程序时,GPS模块仍在运行。 所以我find了另一种方式:

我写了一个GPS.java类:

 public class GPS { private IGPSActivity main; // Helper for GPS-Position private LocationListener mlocListener; private LocationManager mlocManager; private boolean isRunning; public GPS(IGPSActivity main) { this.main = main; // GPS Position mlocManager = (LocationManager) ((Activity) this.main).getSystemService(Context.LOCATION_SERVICE); mlocListener = new MyLocationListener(); mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener); // GPS Position END this.isRunning = true; } public void stopGPS() { if(isRunning) { mlocManager.removeUpdates(mlocListener); this.isRunning = false; } } public void resumeGPS() { mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener); this.isRunning = true; } public boolean isRunning() { return this.isRunning; } public class MyLocationListener implements LocationListener { private final String TAG = MyLocationListener.class.getSimpleName(); @Override public void onLocationChanged(Location loc) { GPS.this.main.locationChanged(loc.getLongitude(), loc.getLatitude()); } @Override public void onProviderDisabled(String provider) { GPS.this.main.displayGPSSettingsDialog(); } @Override public void onProviderEnabled(String provider) { } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } } } 

这个类用于每个需要GPS坐标的Activity。 每个活动必须实现以下接口(通信所需):

 public interface IGPSActivity { public void locationChanged(double longitude, double latitude); public void displayGPSSettingsDialog(); } 

现在我的主要活动如下所示:

 public class MainActivity extends Activity implements IGPSActivity { private GPS gps; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); gps = new GPS(this); } @Override protected void onResume() { if(!gps.isRunning()) gps.resumeGPS(); super.onResume(); } @Override protected void onStop() { gps.stopGPS(); super.onStop(); } public void locationChanged(double longitude, double latitude) { Log.d(TAG, "Main-Longitude: " + longitude); Log.d(TAG, "Main-Latitude: " + latitude); } @Override public void displayGPSSettingsDialog() { Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivity(intent); } } 

和第二个这样的:

 public class TEST4GPS extends Activity implements IGPSActivity{ private GPS gps; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.gps = new GPS(this); } @Override public void locationChanged(double longitude, double latitude) { Log.d("TEST", "Test-Longitude: " + longitude); Log.d("TEST", "Test-Latitude: " + latitude); } @Override protected void onResume() { if(!gps.isRunning()) gps.resumeGPS(); super. onResume(); } @Override protected void onStop() { gps.stopGPS(); super.onStop(); } @Override public void displayGPSSettingsDialog() { Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivity(intent); } } 

它不像Devunwired的解决scheme那样美丽,但它适用于我。 CYA

你可以让你的服务把你的lat&long coords写到一个sqlite数据库中,这样你就不会有服务绑定的开销,你的coords可以在所有的活动中被访问。

也许在你的主要活动中,你可以检查GPS状态,如果它被closures,你可以提示用户启用它。 一旦启用GPS,启动您的服务。

这是一个非常简单和直接的方法来做到这一点:

在您的主要活动中:

 private boolean mFinish; @Override public void onBackPressed() { mFinish = true; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mFinish = false; ... } @Override public void onPause(){ super.onPause(); if (mFinish) { // remove updates here mLocationManager.removeUpdates(mLocationListener); } } 

这将只会删除更新监听器,如果你在你的主要活动中按Back,但保持不变。

这不是最好的方法,但它是一个简单的复制粘贴解决scheme。

确保你不要调用位置监听器,如果它已经在运行(例如在屏幕上旋转),否则你将最终在后台运行多个监听器。