合理使用位置信息可能对您的应用用户有益。例如,如果您的应用帮助用户在步行或驾驶时找到方向,或者您的应用跟踪资产的位置,则需要定期获取设备的位置。除了地理位置(纬度和经度)之外,您可能还希望向用户提供更多信息,例如设备的方位(水平行进方向)、高度或速度。此信息以及更多信息可在您的应用可以从Location
对象中检索到的融合位置提供程序中获得。作为回应,API 会根据当前可用的位置提供程序(例如 WiFi 和 GPS(全球定位系统))定期向您的应用更新最佳可用位置。位置的准确性由提供程序、您已请求的位置权限以及您在位置请求中设置的选项决定。
本课程将向您展示如何使用融合位置提供程序中的requestLocationUpdates()
方法请求有关设备位置的定期更新。
获取最后已知位置
设备的最后已知位置提供了一个方便的起点,确保应用在开始定期位置更新之前拥有已知位置。关于获取最后已知位置的课程向您展示了如何通过调用getLastLocation()
来获取最后已知位置。以下部分中的代码片段假设您的应用已检索到最后已知位置并将其作为全局变量mCurrentLocation
中的Location
对象存储。
发出位置请求
在请求位置更新之前,您的应用必须连接到位置服务并发出位置请求。关于更改位置设置的课程将向您展示如何执行此操作。一旦位置请求到位,您就可以通过调用requestLocationUpdates()
来启动定期更新。
根据请求的形式,融合位置提供程序会调用LocationCallback.onLocationResult()
回调方法并向其传递Location
对象的列表,或者发出包含其扩展数据中位置的PendingIntent
。更新的准确性和频率会受到您已请求的位置权限以及您在位置请求对象中设置的选项的影响。
本课程将向您展示如何使用LocationCallback
回调方法来获取更新。调用requestLocationUpdates()
,向其传递LocationRequest
对象的实例和LocationCallback
。按照以下代码示例中所示定义startLocationUpdates()
方法
Kotlin
override fun onResume() { super.onResume() if (requestingLocationUpdates) startLocationUpdates() } private fun startLocationUpdates() { fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper()) }
Java
@Override protected void onResume() { super.onResume(); if (requestingLocationUpdates) { startLocationUpdates(); } } private void startLocationUpdates() { fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper()); }
请注意,上述代码片段引用了一个布尔标志requestingLocationUpdates
,用于跟踪用户是否已打开或关闭位置更新。如果用户已关闭位置更新,您可以告知他们您的应用的位置需求。有关在活动实例之间保留布尔标志值的更多信息,请参阅保存活动的狀態。
定义位置更新回调
融合位置提供程序将调用LocationCallback.onLocationResult()
回调方法。传入参数包含一个Location
对象列表,其中包含位置的纬度和经度。以下代码片段展示了如何实现LocationCallback
接口并定义该方法,然后获取位置更新的时间戳并在您的应用用户界面上显示纬度、经度和时间戳
Kotlin
private lateinit var locationCallback: LocationCallback // ... override fun onCreate(savedInstanceState: Bundle?) { // ... locationCallback = object : LocationCallback() { override fun onLocationResult(locationResult: LocationResult?) { locationResult ?: return for (location in locationResult.locations){ // Update UI with location data // ... } } } }
Java
private LocationCallback locationCallback; // ... @Override protected void onCreate(Bundle savedInstanceState) { // ... locationCallback = new LocationCallback() { @Override public void onLocationResult(LocationResult locationResult) { if (locationResult == null) { return; } for (Location location : locationResult.getLocations()) { // Update UI with location data // ... } } }; }
停止位置更新
考虑当活动不再处于焦点状态时(例如,用户切换到另一个应用或同一应用中的其他活动时)是否要停止位置更新。这有助于降低功耗,前提是应用即使在后台运行也不需要收集信息。本节介绍如何在活动的onPause()
方法中停止更新。
要停止位置更新,请调用removeLocationUpdates()
,并向其传递一个LocationCallback
,如下面的代码示例所示。
Kotlin
override fun onPause() { super.onPause() stopLocationUpdates() } private fun stopLocationUpdates() { fusedLocationClient.removeLocationUpdates(locationCallback) }
Java
@Override protected void onPause() { super.onPause(); stopLocationUpdates(); } private void stopLocationUpdates() { fusedLocationClient.removeLocationUpdates(locationCallback); }
使用布尔值requestingLocationUpdates
跟踪当前是否已启用位置更新。在活动的onResume()
方法中,检查位置更新是否当前处于活动状态,如果未启用则启用它们。
Kotlin
override fun onResume() { super.onResume() if (requestingLocationUpdates) startLocationUpdates() }
Java
@Override protected void onResume() { super.onResume(); if (requestingLocationUpdates) { startLocationUpdates(); } }
保存活动状态。
设备配置的更改(例如屏幕方向或语言的更改)可能会导致当前活动被销毁。因此,您的应用必须存储任何需要重新创建活动的信息。一种方法是通过存储在Bundle
对象中的实例状态来实现。
下面的代码示例演示如何使用活动的onSaveInstanceState()
回调来保存实例状态。
Kotlin
override fun onSaveInstanceState(outState: Bundle?) { outState?.putBoolean(REQUESTING_LOCATION_UPDATES_KEY, requestingLocationUpdates) super.onSaveInstanceState(outState) }
Java
@Override protected void onSaveInstanceState(Bundle outState) { outState.putBoolean(REQUESTING_LOCATION_UPDATES_KEY, requestingLocationUpdates); // ... super.onSaveInstanceState(outState); }
定义一个updateValuesFromBundle()
方法,以从活动的先前实例(如果可用)恢复保存的值。从活动的onCreate()
方法调用该方法,如下面的代码示例所示。
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { // ... updateValuesFromBundle(savedInstanceState) } private fun updateValuesFromBundle(savedInstanceState: Bundle?) { savedInstanceState ?: return // Update the value of requestingLocationUpdates from the Bundle. if (savedInstanceState.keySet().contains(REQUESTING_LOCATION_UPDATES_KEY)) { requestingLocationUpdates = savedInstanceState.getBoolean( REQUESTING_LOCATION_UPDATES_KEY) } // ... // Update UI to match restored state updateUI() }
Java
@Override public void onCreate(Bundle savedInstanceState) { // ... updateValuesFromBundle(savedInstanceState); } private void updateValuesFromBundle(Bundle savedInstanceState) { if (savedInstanceState == null) { return; } // Update the value of requestingLocationUpdates from the Bundle. if (savedInstanceState.keySet().contains(REQUESTING_LOCATION_UPDATES_KEY)) { requestingLocationUpdates = savedInstanceState.getBoolean( REQUESTING_LOCATION_UPDATES_KEY); } // ... // Update UI to match restored state updateUI(); }
有关保存实例状态的更多信息,请参阅Android Activity 类参考。
注意: 对于更持久性的存储,您可以将用户首选项存储在应用的SharedPreferences
中。在活动的onPause()
方法中设置共享首选项,并在onResume()
中检索该首选项。有关保存首选项的更多信息,请阅读保存键值对。
其他资源
要了解更多信息,请利用以下资源:
示例
- 示例应用 演示在 Android 中接收位置更新。