應用程式適當使用位置資訊對使用者有益。舉例來說,如果應用程式協助使用者在走路或開車時規劃路線,或追蹤裝置位置,則必須定期取得裝置定位。除了地理位置 (經緯度) 外,開發人員也可為使用者提供其他資訊,例如方位 (水平方向)、高度,或裝置的速度。應用程式可以從整合式位置預測提供工具取得的 Location
物件中,找到這些資訊和其他內容。作為回應,API 會根據當前可用定位管道 (例如 Wi-Fi 和 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 活動類別參考資料。
注意:如要提高永久儲存空間的用量,可將使用者偏好設定儲存於應用程式的 SharedPreferences
中。請在活動的 onPause()
方法設置共用偏好設定,並在 onResume()
中擷取偏好設定。如要進一步瞭解如何儲存偏好設定,請參閱儲存鍵/值組。
其他資源
如要進一步瞭解,請使用下列資源:
範例
GitHub 的 LocationUpdatesForegroundService 專案
以下為應用程式範例,示範應用程式可繼續使用者發起的動作,且無需持續要求背景位置的存取權。
GitHub 的 LocationUpdatesPendingIntent 專案
要求存取背景位置資訊的應用程式範例。