Android:LocationManager与Google Play服务

我想要构build一个以获取用户当前位置为中心的应用程序,然后通过Google Places APIfind离他/她近的兴趣点(如酒吧,餐馆等)。

在networkingsearch开始的地方,我遇到了一些使用LocationManager类的教程,还有一些使用Google Play服务的教程来查找用户的位置。

一见钟情,他们俩都做同样的事情,但是因为我是新手,所以有点困惑,我不知道哪种方法最适合我的需要。 所以,我想问你:

这两种查找地点的方法有什么区别(如果有的话)?

Android上的用户位置

在Android上获取用户的位置比在iOS上稍微简单一些。 开始混淆,有两种完全不同的方式可以做到这一点。 第一个是使用android.location.LocationListener Android API,第二个是使用Google Play服务API的com.google.android.gms.location.LocationListener 。 我们来看看他们两个。

  1. Android的位置API

    Android的位置API使用三个不同的提供者来获取位置 –

    • LocationManager.GPS_PROVIDER – 此提供商使用卫星确定位置。 根据条件,此提供程序可能需要一段时间才能返回位置修复程序。
    • LocationManager.NETWORK_PROVIDER – 此提供商根据小区塔和WiFi接入点的可用性来确定位置。 结果通过networking查找来检索。
    • LocationManager.PASSIVE_PROVIDER – 此提供程序将返回其他提供程序生成的位置。 当其他应用程序或服务请求时,您无需实际请求自己的位置,就会被动地接收位置更新。

其要点是从系统获取LocationManager对象,实现LocationListener ,并在LocationManager上调用requestLocationUpdates

这是一个代码片段:

  LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); // Define a listener that responds to location updates LocationListener locationListener = new LocationListener() { public void onLocationChanged(Location location) { // Called when a new location is found by the network location provider. makeUseOfNewLocation(location); } public void onStatusChanged(String provider, int status, Bundle extras) {} public void onProviderEnabled(String provider) {} public void onProviderDisabled(String provider) {} }; // Register the listener with the Location Manager to receive location updates locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener); 

Google的位置策略API指南很好地解释了代码。 但是他们也提到,在大多数情况下,通过使用Google位置服务API ,您可以获得更好的电池性能以及更准确的性能。 现在混乱开始了!

  1. Google的位置服务API

Google的位置服务API是Google Play服务APK的一部分(以下介绍如何设置 )。 他们build立在Android的API之上。 这些API提供了一个“Fused Location Provider”,而不是上面提到的提供者。 这个提供商根据准确性,电池使用情况等自动select要使用的底层提供商。它的速度很快,因为您可以从系统级服务获取位置信息,并不断进行更新。 而且您可以使用更多高级function,如地理围栏。

要使用Google的位置服务,您的应用需要连接到GooglePlayServicesClient 。 要连接到客户端,您的活动(或片段等)需要实现GooglePlayServicesClient.ConnectionCallbacksGooglePlayServicesClient.OnConnectionFailedListener接口。 这是一个示例代码:

  public class MyActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener { LocationClient locationClient; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); locationClient = new LocationClient(this, this, this); } @Override public void onConnected(Bundle bundle) { Location location = locationClient.getLastLocation() ; Toast.makeText(this, "Connected to Google Play Services", Toast.LENGTH_SHORT).show(); } @Override public void onDisconnected() { Toast.makeText(this, "Connected from Google Play Services.", Toast.LENGTH_SHORT).show(); } @Override public void onConnectionFailed(ConnectionResult connectionResult) { // code to handle failed connection // this code can be found here — http://developer.android.com/training/location/retrieve-current.html } 
  • 为什么locationClient.getLastLocation()空?

locationClient.getLastLocation()从客户端获取最后一个已知位置。 但是,如果至less有一个客户端连接到熔合位置提供程序,它将只保留后台位置。 一旦第一个客户端连接,它将立即尝试获得一个位置。 如果您的活动是第一个连接的客户端,并且您立即在onConnected()调用getLastLocation() ,那么第一个位置可能不够用。这将导致locationnull

为了解决这个问题,你必须等待(不确定地),直到提供者获得位置,然后调用getLastLocation() ,这是不可能知道的。 另一个(更好的)选项是实现com.google.android.gms.location.LocationListener接口来接收定期的位置更新(并在第一次更新后将其closures)。

  public class MyActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener { // . . . . . . . . more stuff here LocationRequest locationRequest; LocationClient locationClient; @Override protected void onCreate(Bundle savedInstanceState) { // . . . . other initialization code locationClient = new LocationClient(this, this, this); locationRequest = new LocationRequest(); // Use high accuracy locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); // Set the update interval to 5 seconds locationRequest.setInterval(UPDATE_INTERVAL); // Set the fastest update interval to 1 second locationRequest.setFastestInterval(FASTEST_INTERVAL); } // . . . . . . . . other methods @Override public void onConnected(Bundle bundle) { Location location = locationClient.getLastLocation(); if (location == null) locationClient.requestLocationUpdates(locationRequest, this); else Toast.makeText(getActivity(), "Location: " + location.getLatitude() + ", " + location.getLongitude(), Toast.LENGTH_SHORT).show(); } // . . . . . . . . other methods @Override public void onLocationChanged(Location location) { locationClient.removeLocationUpdates(this); // Use the location here!!! } 

在这个代码中,你正在检查客户端是否已经有最后的位置(在onConnected )。 如果不是,请求位置更新,并在获得更新后立即closures请求(在onLocationChanged()callback中)。

请注意, locationClient.requestLocationUpdates(locationRequest, this); 必须位于onConnectedcallback之内,否则您将得到IllegalStateException因为您将尝试请求位置而不连接到Google Play服务客户端。

  • 用户已禁用位置服务

很多时候,用户会禁用位置服务(以节省电池或隐私的原因)。 在这种情况下,上面的代码仍然会请求位置更新,但onLocationChanged永远不会被调用。 您可以通过检查用户是否禁用位置服务来停止请求。

如果您的应用程序要求他们启用位置服务,则您需要显示消息或祝酒。 不幸的是,无法检查用户是否在Google的位置服务API中禁用了位置服务。 为此,您将不得不诉诸于Android的API。

在你的onCreate方法中:

  LocationManager manager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE); if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && !manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { locationEnabled = false; Toast.makeText(getActivity(), "Enable location services for accurate data", Toast.LENGTH_SHORT).show(); } else locationEnabled = true; 

在你的onConnected方法中使用locationEnabled标志,如下所示:

  if (location != null) { Toast.makeText(getActivity(), "Location: " + location.getLatitude() + ", " + location.getLongitude(), Toast.LENGTH_SHORT).show(); } else if (location == null && locationEnabled) { locationClient.requestLocationUpdates(locationRequest, this); } 

感谢Rahul Jiresal

您应该使用Google Play服务位置API而不是LocationManager。 根据文件:

Google Play服务位置API优先于Android框架位置API(android.location),作为向您的应用添加位置感知的一种方式。 如果您目前正在使用Android框架位置API,则强烈build议您尽快切换到Google Play服务位置API。

至于为什么切换,谷歌这样说:

Google位置服务API是Google Play服务的一部分,提供了一个更强大的高级框架,可以自动处理位置提供商,用户移动和位置准确性。 它还根据您提供的功耗参数处理位置更新调度。 在大多数情况下,通过使用位置服务API,您可以获得更好的电池性能以及更适当的准确性。

根据我的经验,“更准确”并不意味着更好。 除非我错过了一些东西,如果你想确保使用GPS,LocationManager是唯一的出路。 我们使用我们的应用跟踪车辆,除非我错过了某些东西,否则Google Play服务会经常提供一些非常不准确的位置。

Google位置服务API是Google Play服务的一部分,提供了一个更强大的高级框架,可以自动处理位置提供商用户移动位置准确性 。 它还根据您提供的功耗参数处理位置更新调度。 在大多数情况下,通过使用位置服务API,您可以获得更好的电池性能以及更适当的准确性。

Google Play服务位置APIAndroid Framework位置API之间的更详细的差异可以在这里find

我一直在使用Google Location Services API。 它确实有其优点,因为它包含了确定职位的几个来源的复杂性。 然而,它包含的太多 ,所以当你得到一个奇怪的位置,你无法确定从哪里来的奇怪的位置。

在现实生活中,我有几个怪胎价值观,离实际位置10公里远。 唯一的解释是,这些疯狂的地点源于谷歌Wi-Fi或NWK数据库中的错误 – 由于Wi-Fi和networking拓扑结构每天都在变化,因此会一直存在错误。 但不幸的是(令人惊讶的是)API并没有提供关于个人职位如何派生的信息。

这就给你带来了一些问题,例如根据对速度,加速度,轴承等的合理性检查来滤除怪异值。

…或者返回到旧的框架API,只使用GPS,这是我可能会做的,直到谷歌改进融合的API。