| page.title=Retrieving the Current Location |
| trainingnavtop=true |
| @jd:body |
| <div id="tb-wrapper"> |
| <div id="tb"> |
| |
| <h2>This lesson teaches you to</h2> |
| <ol> |
| <li><a href="#AppPermissions">Specify App Permissions</a></li> |
| <li><a href="#CheckServices">Check for Google Play services</a></li> |
| <li><a href="#DefineCallbacks">Define Location Services Callbacks</a></li> |
| <li><a href="#ConnectClient">Connect the Location Client</a></li> |
| <li><a href="#GetLocation">Get the Current Location</a></li> |
| </ol> |
| |
| <h2>You should also read</h2> |
| <ul> |
| <li> |
| <a href="{@docRoot}google/play-services/setup.html">Setup Google Play Services SDK</a> |
| </li> |
| </ul> |
| |
| <h2>Try it out</h2> |
| |
| <div class="download-box"> |
| <a href="http://developer.android.com/shareables/training/LocationUpdates.zip" class="button">Download the sample</a> |
| <p class="filename">LocationUpdates.zip</p> |
| </div> |
| |
| </div> |
| </div> |
| |
| <p> |
| Location Services automatically maintains the user's current location, so all your app has to do |
| is retrieve it as needed. The location's accuracy is based on the location permissions you've |
| requested and location sensors that are currently active for the device. |
| <p> |
| Location Services sends the current location to your app through a location client, which is |
| an instance of the Location Services class |
| <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html">LocationClient</a></code>. |
| All requests for location information go through this client. |
| </p> |
| <p class="note"> |
| <strong>Note:</strong> Before you start the lesson, be sure that your development environment |
| and test device are set up correctly. To learn more about this, read the |
| <a href="{@docRoot}google/play-services/setup.html">Setup</a> section in the Google Play |
| services guide. |
| </p> |
| <!-- |
| Specify App Permissions |
| --> |
| <h2 id="AppPermissions">Specify App Permissions</h2> |
| <p> |
| Apps that use Location Services must request location permissions. Android has two location |
| permissions: {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} |
| and {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION}. The |
| permission you choose controls the accuracy of the current location. If you request only coarse |
| location permission, Location Services obfuscates the returned location to an accuracy |
| that's roughly equivalent to a city block. |
| </p> |
| <p> |
| Requesting {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} implies |
| a request for {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION}. |
| </p> |
| <p> |
| For example, to add {@link android.Manifest.permission#ACCESS_COARSE_LOCATION |
| ACCESS_COARSE_LOCATION}, insert the following as a child element of the |
| <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html"><manifest></a></code> |
| element: |
| </p> |
| <pre> |
| <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> |
| </pre> |
| <!-- |
| Check for Google Play Services |
| --> |
| <h2 id="CheckServices">Check for Google Play Services</h2> |
| <p> |
| Location Services is part of the Google Play services APK. Since it's hard to anticipate the |
| state of the user's device, you should always check that the APK is installed before you attempt |
| to connect to Location Services. To check that the APK is installed, call |
| <code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesUtil.html#isGooglePlayServicesAvailable(android.content.Context)">GooglePlayServicesUtil.isGooglePlayServicesAvailable()</a></code>, |
| which returns one of the |
| integer result codes listed in the reference documentation for |
| <code><a href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html">ConnectionResult</a></code>. |
| If you encounter an error, call |
| <code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesUtil.html#getErrorDialog(int, android.app.Activity, int)">GooglePlayServicesUtil.getErrorDialog()</a></code> |
| to retrieve localized dialog that prompts users to take the correct action, then display |
| the dialog in a {@link android.support.v4.app.DialogFragment}. The dialog may allow the |
| user to correct the problem, in which case Google Play services may send a result back to your |
| activity. To handle this result, override the method |
| {@link android.support.v4.app.FragmentActivity#onActivityResult onActivityResult()}. |
| </p> |
| <p> |
| Since you usually need to check for Google Play services in more than one place in your code, |
| define a method that encapsulates the check, then call the method before each connection |
| attempt. The following snippet contains all of the code required to check for Google |
| Play services: |
| </p> |
| <pre> |
| public class MainActivity extends FragmentActivity { |
| ... |
| // Global constants |
| /* |
| * Define a request code to send to Google Play services |
| * This code is returned in Activity.onActivityResult |
| */ |
| private final static int |
| CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000; |
| ... |
| // Define a DialogFragment that displays the error dialog |
| public static class ErrorDialogFragment extends DialogFragment { |
| // Global field to contain the error dialog |
| private Dialog mDialog; |
| // Default constructor. Sets the dialog field to null |
| public ErrorDialogFragment() { |
| super(); |
| mDialog = null; |
| } |
| // Set the dialog to display |
| public void setDialog(Dialog dialog) { |
| mDialog = dialog; |
| } |
| // Return a Dialog to the DialogFragment. |
| @Override |
| public Dialog onCreateDialog(Bundle savedInstanceState) { |
| return mDialog; |
| } |
| } |
| ... |
| /* |
| * Handle results returned to the FragmentActivity |
| * by Google Play services |
| */ |
| @Override |
| protected void onActivityResult( |
| int requestCode, int resultCode, Intent data) { |
| // Decide what to do based on the original request code |
| switch (requestCode) { |
| ... |
| case CONNECTION_FAILURE_RESOLUTION_REQUEST : |
| /* |
| * If the result code is Activity.RESULT_OK, try |
| * to connect again |
| */ |
| switch (resultCode) { |
| case Activity.RESULT_OK : |
| /* |
| * Try the request again |
| */ |
| ... |
| break; |
| } |
| ... |
| } |
| } |
| ... |
| private boolean servicesConnected() { |
| // Check that Google Play services is available |
| int resultCode = |
| GooglePlayServicesUtil. |
| isGooglePlayServicesAvailable(this); |
| // If Google Play services is available |
| if (ConnectionResult.SUCCESS == resultCode) { |
| // In debug mode, log the status |
| Log.d("Location Updates", |
| "Google Play services is available."); |
| // Continue |
| return true; |
| // Google Play services was not available for some reason. |
| // resultCode holds the error code. |
| } else { |
| // Get the error dialog from Google Play services |
| Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog( |
| resultCode, |
| this, |
| CONNECTION_FAILURE_RESOLUTION_REQUEST); |
| |
| // If Google Play services can provide an error dialog |
| if (errorDialog != null) { |
| // Create a new DialogFragment for the error dialog |
| ErrorDialogFragment errorFragment = |
| new ErrorDialogFragment(); |
| // Set the dialog in the DialogFragment |
| errorFragment.setDialog(errorDialog); |
| // Show the error dialog in the DialogFragment |
| errorFragment.show(getSupportFragmentManager(), |
| "Location Updates"); |
| } |
| } |
| } |
| ... |
| } |
| </pre> |
| <p> |
| Snippets in the following sections call this method to verify that Google Play services is |
| available. |
| </p> |
| <!-- |
| Define Location Services Callbacks |
| --> |
| <h2 id="DefineCallbacks">Define Location Services Callbacks</h2> |
| <p> |
| To get the current location, create a location client, connect it |
| to Location Services, and then call its |
| <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#getLastLocation()">getLastLocation()</a></code> |
| method. The return value is the best, most recent location, based on the permissions your |
| app requested and the currently-enabled location sensors. |
| <p> |
| <p> |
| Before you create the location client, implement the interfaces that Location Services uses to |
| communicate with your app: |
| </p> |
| <dl> |
| <dt> |
| <code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.ConnectionCallbacks.html">ConnectionCallbacks</a></code> |
| </dt> |
| <dd> |
| Specifies methods that Location Services calls when a location client is connected or |
| disconnected. |
| </dd> |
| <dt> |
| <code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.OnConnectionFailedListener.html">OnConnectionFailedListener</a></code> |
| </dt> |
| <dd> |
| Specifies a method that Location Services calls if an error occurs while attempting to |
| connect the location client. This method uses the previously-defined {@code showErrorDialog} |
| method to display an error dialog that attempts to fix the problem using Google Play |
| services. |
| </dd> |
| </dl> |
| <p> |
| The following snippet shows how to specify the interfaces and define the methods: |
| </p> |
| <pre> |
| public class MainActivity extends FragmentActivity implements |
| GooglePlayServicesClient.ConnectionCallbacks, |
| GooglePlayServicesClient.OnConnectionFailedListener { |
| ... |
| /* |
| * Called by Location Services when the request to connect the |
| * client finishes successfully. At this point, you can |
| * request the current location or start periodic updates |
| */ |
| @Override |
| public void onConnected(Bundle dataBundle) { |
| // Display the connection status |
| Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show(); |
| |
| } |
| ... |
| /* |
| * Called by Location Services if the connection to the |
| * location client drops because of an error. |
| */ |
| @Override |
| public void onDisconnected() { |
| // Display the connection status |
| Toast.makeText(this, "Disconnected. Please re-connect.", |
| Toast.LENGTH_SHORT).show(); |
| } |
| ... |
| /* |
| * Called by Location Services if the attempt to |
| * Location Services fails. |
| */ |
| @Override |
| public void onConnectionFailed(ConnectionResult connectionResult) { |
| /* |
| * Google Play services can resolve some errors it detects. |
| * If the error has a resolution, try sending an Intent to |
| * start a Google Play services activity that can resolve |
| * error. |
| */ |
| if (connectionResult.hasResolution()) { |
| try { |
| // Start an Activity that tries to resolve the error |
| connectionResult.startResolutionForResult( |
| this, |
| CONNECTION_FAILURE_RESOLUTION_REQUEST); |
| /* |
| * Thrown if Google Play services canceled the original |
| * PendingIntent |
| */ |
| } catch (IntentSender.SendIntentException e) { |
| // Log the error |
| e.printStackTrace(); |
| } |
| } else { |
| /* |
| * If no resolution is available, display a dialog to the |
| * user with the error. |
| */ |
| showErrorDialog(connectionResult.getErrorCode()); |
| } |
| } |
| ... |
| } |
| </pre> |
| <!-- |
| Connect the Location Client |
| --> |
| <h2 id="ConnectClient">Connect the Location Client</h2> |
| <p> |
| Now that the callback methods are in place, create the location client and connect it to |
| Location Services. |
| </p> |
| <p> |
| You should create the location client in {@link android.support.v4.app.FragmentActivity#onCreate |
| onCreate()}, then connect it in |
| {@link android.support.v4.app.FragmentActivity#onStart onStart()}, so that Location Services |
| maintains the current location while your activity is fully visible. Disconnect the client in |
| {@link android.support.v4.app.FragmentActivity#onStop onStop()}, so that when your app is not |
| visible, Location Services is not maintaining the current location. Following this pattern of |
| connection and disconnection helps save battery power. For example: |
| </p> |
| <p class="note"> |
| <strong>Note:</strong> The current location is only maintained while a location client is |
| connected to Location Service. Assuming that no other apps are connected to Location Services, |
| if you disconnect the client and then sometime later call |
| <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#getLastLocation()">getLastLocation()</a></code>, |
| the result may be out of date. |
| </p> |
| <pre> |
| public class MainActivity extends FragmentActivity implements |
| GooglePlayServicesClient.ConnectionCallbacks, |
| GooglePlayServicesClient.OnConnectionFailedListener { |
| ... |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| ... |
| /* |
| * Create a new location client, using the enclosing class to |
| * handle callbacks. |
| */ |
| mLocationClient = new LocationClient(this, this, this); |
| ... |
| } |
| ... |
| /* |
| * Called when the Activity becomes visible. |
| */ |
| @Override |
| protected void onStart() { |
| super.onStart(); |
| // Connect the client. |
| mLocationClient.connect(); |
| } |
| ... |
| /* |
| * Called when the Activity is no longer visible. |
| */ |
| @Override |
| protected void onStop() { |
| // Disconnecting the client invalidates it. |
| mLocationClient.disconnect(); |
| super.onStop(); |
| } |
| ... |
| } |
| </pre> |
| <!-- |
| Get the Current Location |
| --> |
| <h2 id="GetLocation">Get the Current Location</h2> |
| <p> |
| To get the current location, call |
| <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#getLastLocation()">getLastLocation()</a></code>. |
| For example: |
| </p> |
| <pre> |
| public class MainActivity extends FragmentActivity implements |
| GooglePlayServicesClient.ConnectionCallbacks, |
| GooglePlayServicesClient.OnConnectionFailedListener { |
| ... |
| // Global variable to hold the current location |
| Location mCurrentLocation; |
| ... |
| mCurrentLocation = mLocationClient.getLastLocation(); |
| ... |
| } |
| </pre> |
| <p> |
| The next lesson, <a href="receive-location-updates.html">Receiving Location Updates</a>, shows |
| you how to receive periodic location updates from Location Services. |
| </p> |