309 lines
14 KiB
Plaintext
309 lines
14 KiB
Plaintext
page.title=Receiving Location Updates
|
|
trainingnavtop=true
|
|
@jd:body
|
|
|
|
<div id="tb-wrapper">
|
|
<div id="tb">
|
|
|
|
<h2>This lesson teaches you how to</h2>
|
|
<ol>
|
|
<li><a href="#get-last-location">Get the Last Known Location</a></li>
|
|
<li><a href="#updates">Request Location Updates</a></li>
|
|
<li><a href="#callback">Define the Location Update Callback</a></li>
|
|
<li><a href="#stop-updates">Stop Location Updates</a></li>
|
|
<li><a href="#save-state">Save the State of the Activity</a></li>
|
|
</ol>
|
|
|
|
<h2>You should also read</h2>
|
|
<ul>
|
|
<li>
|
|
<a href="{@docRoot}google/play-services/setup.html">Setting up Google Play
|
|
Services</a>
|
|
</li>
|
|
<li>
|
|
<a href="retrieve-current.html">Getting the Last Known Location</a>
|
|
</li>
|
|
</ul>
|
|
|
|
<h2>Try it out</h2>
|
|
|
|
<ul>
|
|
<li>
|
|
<a href="https://github.com/googlesamples/android-play-location/tree/master/LocationUpdates" class="external-link">LocationUpdates</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<p>If your app can continuously track location, it can deliver more relevant
|
|
information to the user. For example, if your app helps the user find their
|
|
way while walking or driving, or if your app tracks the location of assets, it
|
|
needs to get the location of the device at regular intervals. As well as the
|
|
geographical location (latitude and longitude), you may want to give the user
|
|
further information such as the bearing (horizontal direction of travel),
|
|
altitude, or velocity of the device. This information, and more, is available
|
|
in the {@link android.location.Location} object that your app can retrieve
|
|
from the
|
|
<a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html">fused
|
|
location provider</a>.</p>
|
|
|
|
<p>While you can get a device's location with
|
|
<a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#getLastLocation(com.google.android.gms.common.api.GoogleApiClient)">{@code getLastLocation()}</a>,
|
|
as illustrated in the lesson on
|
|
<a href="retrieve-current.html">Getting the Last Known Location</a>,
|
|
a more direct approach is to request periodic updates from the fused location
|
|
provider. In response, the API updates your app periodically with the best
|
|
available location, based on the currently-available location providers such
|
|
as WiFi and GPS (Global Positioning System). The accuracy of the location is
|
|
determined by the providers, the location permissions you've requested, and
|
|
the options you set in the location request.</p>
|
|
|
|
<p>This lesson shows you how to request regular updates about a device's
|
|
location using the
|
|
<a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#requestLocationUpdates(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.location.LocationRequest, com.google.android.gms.location.LocationListener)">{@code requestLocationUpdates()}</a>
|
|
method in the fused location provider.
|
|
|
|
<h2 id="get-last-location">Get the Last Known Location</h2>
|
|
|
|
<p>The last known location of the device provides a handy base from which to
|
|
start, ensuring that the app has a known location before starting the
|
|
periodic location updates. The lesson on
|
|
<a href="retrieve-current.html">Getting the Last Known Location</a> shows you
|
|
how to get the last known location by calling
|
|
<a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#getLastLocation(com.google.android.gms.common.api.GoogleApiClient)">{@code getLastLocation()}</a>.
|
|
The snippets in the following sections assume that your app has already
|
|
retrieved the last known location and stored it as a
|
|
{@link android.location.Location} object in the global variable
|
|
{@code mCurrentLocation}.</p>
|
|
|
|
<p>Apps that use location services must request location permissions. In this
|
|
lesson you require fine location detection, so that your app can get as
|
|
precise a location as possible from the available location providers. Request
|
|
this permission with the
|
|
{@code uses-permission} element in your app manifest, as shown in the
|
|
following example:</p>
|
|
|
|
<pre>
|
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
package="com.google.android.gms.location.sample.locationupdates" >
|
|
|
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
|
</manifest>
|
|
</pre>
|
|
|
|
<h2 id="updates">Request Location Updates</h2>
|
|
|
|
<p>Before requesting location updates, your app must connect to location
|
|
services and make a location request. The lesson on
|
|
<a href="change-location-settings.html">Changing Location Settings</a>
|
|
shows you how to do this. Once a location request is in place you can start
|
|
the regular updates by calling
|
|
<a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#requestLocationUpdates(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.location.LocationRequest, com.google.android.gms.location.LocationListener)">{@code requestLocationUpdates()}</a>.
|
|
Do this in the
|
|
<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">{@code onConnected()}</a>
|
|
callback provided by Google API Client, which is called when the client is
|
|
ready.</p>
|
|
|
|
<p>Depending on the form of the request, the fused location provider either
|
|
invokes the
|
|
<a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener.onLocationChanged()}</a>
|
|
callback method and passes it a {@link android.location.Location} object, or
|
|
issues a
|
|
<a href="{@docRoot}reference/android/app/PendingIntent.html">{@code PendingIntent}</a>
|
|
that contains the location in its extended data. The accuracy and frequency of
|
|
the updates are affected by the location permissions you've requested and the
|
|
options you set in the location request object.</p>
|
|
|
|
<p>This lesson shows you how to get the update using the
|
|
<a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener}</a>
|
|
callback approach. Call
|
|
<a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#requestLocationUpdates(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.location.LocationRequest, com.google.android.gms.location.LocationListener)">{@code requestLocationUpdates()}</a>,
|
|
passing it your instance of the
|
|
<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code GoogleApiClient}</a>,
|
|
the
|
|
<a href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html">{@code LocationRequest}</a>
|
|
object,
|
|
and a <a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener}</a>.
|
|
Define a {@code startLocationUpdates()} method, called from the
|
|
<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">{@code onConnected()}</a>
|
|
callback, as shown in the following code sample:</p>
|
|
|
|
<pre>
|
|
@Override
|
|
public void onConnected(Bundle connectionHint) {
|
|
...
|
|
if (mRequestingLocationUpdates) {
|
|
startLocationUpdates();
|
|
}
|
|
}
|
|
|
|
protected void startLocationUpdates() {
|
|
LocationServices.FusedLocationApi.requestLocationUpdates(
|
|
mGoogleApiClient, mLocationRequest, this);
|
|
}
|
|
</pre>
|
|
|
|
<p>Notice that the above code snippet refers to a boolean flag,
|
|
{@code mRequestingLocationUpdates}, used to track whether the user has
|
|
turned location updates on or off. For more about retaining the value of this
|
|
flag across instances of the activity, see
|
|
<a href="#save-state">Save the State of the Activity</a>.
|
|
|
|
<h2 id="callback">Define the Location Update Callback</h2>
|
|
|
|
<p>The fused location provider invokes the
|
|
<a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html#onLocationChanged(android.location.Location)">{@code LocationListener.onLocationChanged()}</a>
|
|
callback method. The incoming argument is a {@link android.location.Location}
|
|
object containing the location's latitude and longitude. The following snippet
|
|
shows how to implement the
|
|
<a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener}</a>
|
|
interface and define the method, then get the timestamp of the location update
|
|
and display the latitude, longitude and timestamp on your app's user
|
|
interface:</p>
|
|
|
|
<pre>
|
|
public class MainActivity extends ActionBarActivity implements
|
|
ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
|
|
...
|
|
@Override
|
|
public void onLocationChanged(Location location) {
|
|
mCurrentLocation = location;
|
|
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
|
|
updateUI();
|
|
}
|
|
|
|
private void updateUI() {
|
|
mLatitudeTextView.setText(String.valueOf(mCurrentLocation.getLatitude()));
|
|
mLongitudeTextView.setText(String.valueOf(mCurrentLocation.getLongitude()));
|
|
mLastUpdateTimeTextView.setText(mLastUpdateTime);
|
|
}
|
|
}
|
|
</pre>
|
|
|
|
<h2 id="stop-updates">Stop Location Updates</h2>
|
|
|
|
<p>Consider whether you want to stop the location updates when the activity is
|
|
no longer in focus, such as when the user switches to another app or to a
|
|
different activity in the same app. This can be handy to reduce power
|
|
consumption, provided the app doesn't need to collect information even when
|
|
it's running in the background. This section shows how you can stop the
|
|
updates in the activity's
|
|
{@link android.app.Activity#onPause onPause()} method.</p>
|
|
|
|
<p>To stop location updates, call
|
|
<a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#removeLocationUpdates(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.location.LocationListener)">{@code removeLocationUpdates()}</a>,
|
|
passing it your instance of the
|
|
<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code GoogleApiClient}</a>
|
|
object and a
|
|
<a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code LocationListener}</a>,
|
|
as shown in the following code sample:</p>
|
|
|
|
<pre>
|
|
@Override
|
|
protected void onPause() {
|
|
super.onPause();
|
|
stopLocationUpdates();
|
|
}
|
|
|
|
protected void stopLocationUpdates() {
|
|
LocationServices.FusedLocationApi.removeLocationUpdates(
|
|
mGoogleApiClient, this);
|
|
}
|
|
</pre>
|
|
|
|
<p>Use a boolean, {@code mRequestingLocationUpdates}, to track
|
|
whether location updates are currently turned on. In the activity's
|
|
{@link android.app.Activity#onResume onResume()} method, check
|
|
whether location updates are currently active, and activate them if not:</p>
|
|
|
|
<pre>
|
|
@Override
|
|
public void onResume() {
|
|
super.onResume();
|
|
if (mGoogleApiClient.isConnected() && !mRequestingLocationUpdates) {
|
|
startLocationUpdates();
|
|
}
|
|
}
|
|
</pre>
|
|
|
|
<h2 id="save-state">Save the State of the Activity</h2>
|
|
|
|
<p>A change to the device's configuration, such as a change in screen
|
|
orientation or language, can cause the current activity to be destroyed. Your
|
|
app must therefore store any information it needs to recreate the activity.
|
|
One way to do this is via an instance state stored in a
|
|
{@link android.os.Bundle} object.</p>
|
|
|
|
<p>The following code sample shows how to use the activity's
|
|
<a href="{@docRoot}reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)">{@code onSaveInstanceState()}</a>
|
|
callback to save the instance state:</p>
|
|
|
|
<pre>
|
|
public void onSaveInstanceState(Bundle savedInstanceState) {
|
|
savedInstanceState.putBoolean(REQUESTING_LOCATION_UPDATES_KEY,
|
|
mRequestingLocationUpdates);
|
|
savedInstanceState.putParcelable(LOCATION_KEY, mCurrentLocation);
|
|
savedInstanceState.putString(LAST_UPDATED_TIME_STRING_KEY, mLastUpdateTime);
|
|
super.onSaveInstanceState(savedInstanceState);
|
|
}
|
|
</pre>
|
|
|
|
<p>Define an {@code updateValuesFromBundle()} method to restore
|
|
the saved values from the previous instance of the activity, if they're
|
|
available. Call the method from the activity's
|
|
{@link android.app.Activity#onCreate onCreate()} method, as shown in the
|
|
following code sample:</p>
|
|
|
|
<pre>
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
...
|
|
updateValuesFromBundle(savedInstanceState);
|
|
}
|
|
|
|
private void updateValuesFromBundle(Bundle savedInstanceState) {
|
|
if (savedInstanceState != null) {
|
|
// Update the value of mRequestingLocationUpdates from the Bundle, and
|
|
// make sure that the Start Updates and Stop Updates buttons are
|
|
// correctly enabled or disabled.
|
|
if (savedInstanceState.keySet().contains(REQUESTING_LOCATION_UPDATES_KEY)) {
|
|
mRequestingLocationUpdates = savedInstanceState.getBoolean(
|
|
REQUESTING_LOCATION_UPDATES_KEY);
|
|
setButtonsEnabledState();
|
|
}
|
|
|
|
// Update the value of mCurrentLocation from the Bundle and update the
|
|
// UI to show the correct latitude and longitude.
|
|
if (savedInstanceState.keySet().contains(LOCATION_KEY)) {
|
|
// Since LOCATION_KEY was found in the Bundle, we can be sure that
|
|
// mCurrentLocationis not null.
|
|
mCurrentLocation = savedInstanceState.getParcelable(LOCATION_KEY);
|
|
}
|
|
|
|
// Update the value of mLastUpdateTime from the Bundle and update the UI.
|
|
if (savedInstanceState.keySet().contains(LAST_UPDATED_TIME_STRING_KEY)) {
|
|
mLastUpdateTime = savedInstanceState.getString(
|
|
LAST_UPDATED_TIME_STRING_KEY);
|
|
}
|
|
updateUI();
|
|
}
|
|
}
|
|
</pre>
|
|
|
|
<p>For more about saving instance state, see the
|
|
<a href="{@docRoot}reference/android/app/Activity.html#ConfigurationChanges">Android
|
|
Activity</a> class reference.</p>
|
|
|
|
<p class="note"><strong>Note:</strong> For a more persistent storage, you can
|
|
store the user's preferences in your app's
|
|
{@link android.content.SharedPreferences}. Set the shared preference in
|
|
your activity's {@link android.app.Activity#onPause onPause()} method, and
|
|
retrieve the preference in {@link android.app.Activity#onResume onResume()}.
|
|
For more information about saving preferences, read
|
|
<a href="{@docRoot}training/basics/data-storage/shared-preferences.html">Saving
|
|
Key-Value Sets</a>.</p>
|
|
|
|
<p>The next lesson,
|
|
<a href="display-address.html">Displaying a Location Address</a>, shows
|
|
you how to display the street address for a given location.</p>
|