1page.title=Retrieving the Current Location 2trainingnavtop=true 3@jd:body 4<div id="tb-wrapper"> 5<div id="tb"> 6 7<h2>This lesson teaches you to</h2> 8<ol> 9 <li><a href="#AppPermissions">Specify App Permissions</a></li> 10 <li><a href="#CheckServices">Check for Google Play services</a></li> 11 <li><a href="#DefineCallbacks">Define Location Services Callbacks</a></li> 12 <li><a href="#ConnectClient">Connect the Location Client</a></li> 13 <li><a href="#GetLocation">Get the Current Location</a></li> 14</ol> 15 16<h2>You should also read</h2> 17<ul> 18 <li> 19 <a href="{@docRoot}google/play-services/setup.html">Setup Google Play Services SDK</a> 20 </li> 21</ul> 22 23<h2>Try it out</h2> 24 25<div class="download-box"> 26 <a href="http://developer.android.com/shareables/training/LocationUpdates.zip" class="button">Download the sample</a> 27 <p class="filename">LocationUpdates.zip</p> 28</div> 29 30</div> 31</div> 32 33<p> 34 Location Services automatically maintains the user's current location, so all your app has to do 35 is retrieve it as needed. The location's accuracy is based on the location permissions you've 36 requested and location sensors that are currently active for the device. 37<p> 38 Location Services sends the current location to your app through a location client, which is 39 an instance of the Location Services class 40<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html">LocationClient</a></code>. 41 All requests for location information go through this client. 42</p> 43<p class="note"> 44 <strong>Note:</strong> Before you start the lesson, be sure that your development environment 45 and test device are set up correctly. To learn more about this, read the 46 <a href="{@docRoot}google/play-services/setup.html">Setup</a> section in the Google Play 47 services guide. 48</p> 49<!-- 50 Specify App Permissions 51 --> 52<h2 id="AppPermissions">Specify App Permissions</h2> 53<p> 54 Apps that use Location Services must request location permissions. Android has two location 55 permissions: {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} 56 and {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION}. The 57 permission you choose controls the accuracy of the current location. If you request only coarse 58 location permission, Location Services obfuscates the returned location to an accuracy 59 that's roughly equivalent to a city block. 60</p> 61<p> 62 Requesting {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} implies 63 a request for {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION}. 64</p> 65<p> 66 For example, to add {@link android.Manifest.permission#ACCESS_COARSE_LOCATION 67 ACCESS_COARSE_LOCATION}, insert the following as a child element of the 68 <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html"><manifest></a></code> 69 element: 70</p> 71<pre> 72<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 73</pre> 74<!-- 75 Check for Google Play Services 76 --> 77<h2 id="CheckServices">Check for Google Play Services</h2> 78<p> 79 Location Services is part of the Google Play services APK. Since it's hard to anticipate the 80 state of the user's device, you should always check that the APK is installed before you attempt 81 to connect to Location Services. To check that the APK is installed, call 82<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesUtil.html#isGooglePlayServicesAvailable(android.content.Context)">GooglePlayServicesUtil.isGooglePlayServicesAvailable()</a></code>, 83 which returns one of the 84 integer result codes listed in the reference documentation for 85<code><a href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html">ConnectionResult</a></code>. 86 If you encounter an error, call 87<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesUtil.html#getErrorDialog(int, android.app.Activity, int)">GooglePlayServicesUtil.getErrorDialog()</a></code> 88 to retrieve localized dialog that prompts users to take the correct action, then display 89 the dialog in a {@link android.support.v4.app.DialogFragment}. The dialog may allow the 90 user to correct the problem, in which case Google Play services may send a result back to your 91 activity. To handle this result, override the method 92 {@link android.support.v4.app.FragmentActivity#onActivityResult onActivityResult()}. 93</p> 94<p> 95 Since you usually need to check for Google Play services in more than one place in your code, 96 define a method that encapsulates the check, then call the method before each connection 97 attempt. The following snippet contains all of the code required to check for Google 98 Play services: 99</p> 100<pre> 101public class MainActivity extends FragmentActivity { 102 ... 103 // Global constants 104 /* 105 * Define a request code to send to Google Play services 106 * This code is returned in Activity.onActivityResult 107 */ 108 private final static int 109 CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000; 110 ... 111 // Define a DialogFragment that displays the error dialog 112 public static class ErrorDialogFragment extends DialogFragment { 113 // Global field to contain the error dialog 114 private Dialog mDialog; 115 // Default constructor. Sets the dialog field to null 116 public ErrorDialogFragment() { 117 super(); 118 mDialog = null; 119 } 120 // Set the dialog to display 121 public void setDialog(Dialog dialog) { 122 mDialog = dialog; 123 } 124 // Return a Dialog to the DialogFragment. 125 @Override 126 public Dialog onCreateDialog(Bundle savedInstanceState) { 127 return mDialog; 128 } 129 } 130 ... 131 /* 132 * Handle results returned to the FragmentActivity 133 * by Google Play services 134 */ 135 @Override 136 protected void onActivityResult( 137 int requestCode, int resultCode, Intent data) { 138 // Decide what to do based on the original request code 139 switch (requestCode) { 140 ... 141 case CONNECTION_FAILURE_RESOLUTION_REQUEST : 142 /* 143 * If the result code is Activity.RESULT_OK, try 144 * to connect again 145 */ 146 switch (resultCode) { 147 case Activity.RESULT_OK : 148 /* 149 * Try the request again 150 */ 151 ... 152 break; 153 } 154 ... 155 } 156 } 157 ... 158 private boolean servicesConnected() { 159 // Check that Google Play services is available 160 int resultCode = 161 GooglePlayServicesUtil. 162 isGooglePlayServicesAvailable(this); 163 // If Google Play services is available 164 if (ConnectionResult.SUCCESS == resultCode) { 165 // In debug mode, log the status 166 Log.d("Location Updates", 167 "Google Play services is available."); 168 // Continue 169 return true; 170 // Google Play services was not available for some reason. 171 // resultCode holds the error code. 172 } else { 173 // Get the error dialog from Google Play services 174 Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog( 175 resultCode, 176 this, 177 CONNECTION_FAILURE_RESOLUTION_REQUEST); 178 179 // If Google Play services can provide an error dialog 180 if (errorDialog != null) { 181 // Create a new DialogFragment for the error dialog 182 ErrorDialogFragment errorFragment = 183 new ErrorDialogFragment(); 184 // Set the dialog in the DialogFragment 185 errorFragment.setDialog(errorDialog); 186 // Show the error dialog in the DialogFragment 187 errorFragment.show(getSupportFragmentManager(), 188 "Location Updates"); 189 } 190 } 191 } 192 ... 193} 194</pre> 195<p> 196 Snippets in the following sections call this method to verify that Google Play services is 197 available. 198</p> 199<!-- 200 Define Location Services Callbacks 201 --> 202<h2 id="DefineCallbacks">Define Location Services Callbacks</h2> 203<p> 204 To get the current location, create a location client, connect it 205 to Location Services, and then call its 206<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#getLastLocation()">getLastLocation()</a></code> 207 method. The return value is the best, most recent location, based on the permissions your 208 app requested and the currently-enabled location sensors. 209<p> 210<p> 211 Before you create the location client, implement the interfaces that Location Services uses to 212 communicate with your app: 213</p> 214<dl> 215 <dt> 216<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.ConnectionCallbacks.html">ConnectionCallbacks</a></code> 217 </dt> 218 <dd> 219 Specifies methods that Location Services calls when a location client is connected or 220 disconnected. 221 </dd> 222 <dt> 223<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.OnConnectionFailedListener.html">OnConnectionFailedListener</a></code> 224 </dt> 225 <dd> 226 Specifies a method that Location Services calls if an error occurs while attempting to 227 connect the location client. This method uses the previously-defined {@code showErrorDialog} 228 method to display an error dialog that attempts to fix the problem using Google Play 229 services. 230 </dd> 231</dl> 232<p> 233 The following snippet shows how to specify the interfaces and define the methods: 234</p> 235<pre> 236public class MainActivity extends FragmentActivity implements 237 GooglePlayServicesClient.ConnectionCallbacks, 238 GooglePlayServicesClient.OnConnectionFailedListener { 239 ... 240 /* 241 * Called by Location Services when the request to connect the 242 * client finishes successfully. At this point, you can 243 * request the current location or start periodic updates 244 */ 245 @Override 246 public void onConnected(Bundle dataBundle) { 247 // Display the connection status 248 Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show(); 249 250 } 251 ... 252 /* 253 * Called by Location Services if the connection to the 254 * location client drops because of an error. 255 */ 256 @Override 257 public void onDisconnected() { 258 // Display the connection status 259 Toast.makeText(this, "Disconnected. Please re-connect.", 260 Toast.LENGTH_SHORT).show(); 261 } 262 ... 263 /* 264 * Called by Location Services if the attempt to 265 * Location Services fails. 266 */ 267 @Override 268 public void onConnectionFailed(ConnectionResult connectionResult) { 269 /* 270 * Google Play services can resolve some errors it detects. 271 * If the error has a resolution, try sending an Intent to 272 * start a Google Play services activity that can resolve 273 * error. 274 */ 275 if (connectionResult.hasResolution()) { 276 try { 277 // Start an Activity that tries to resolve the error 278 connectionResult.startResolutionForResult( 279 this, 280 CONNECTION_FAILURE_RESOLUTION_REQUEST); 281 /* 282 * Thrown if Google Play services canceled the original 283 * PendingIntent 284 */ 285 } catch (IntentSender.SendIntentException e) { 286 // Log the error 287 e.printStackTrace(); 288 } 289 } else { 290 /* 291 * If no resolution is available, display a dialog to the 292 * user with the error. 293 */ 294 showErrorDialog(connectionResult.getErrorCode()); 295 } 296 } 297 ... 298} 299</pre> 300<!-- 301 Connect the Location Client 302 --> 303<h2 id="ConnectClient">Connect the Location Client</h2> 304<p> 305 Now that the callback methods are in place, create the location client and connect it to 306 Location Services. 307</p> 308<p> 309 You should create the location client in {@link android.support.v4.app.FragmentActivity#onCreate 310 onCreate()}, then connect it in 311 {@link android.support.v4.app.FragmentActivity#onStart onStart()}, so that Location Services 312 maintains the current location while your activity is fully visible. Disconnect the client in 313 {@link android.support.v4.app.FragmentActivity#onStop onStop()}, so that when your app is not 314 visible, Location Services is not maintaining the current location. Following this pattern of 315 connection and disconnection helps save battery power. For example: 316</p> 317<p class="note"> 318 <strong>Note:</strong> The current location is only maintained while a location client is 319 connected to Location Service. Assuming that no other apps are connected to Location Services, 320 if you disconnect the client and then sometime later call 321<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#getLastLocation()">getLastLocation()</a></code>, 322 the result may be out of date. 323</p> 324<pre> 325public class MainActivity extends FragmentActivity implements 326 GooglePlayServicesClient.ConnectionCallbacks, 327 GooglePlayServicesClient.OnConnectionFailedListener { 328 ... 329 @Override 330 protected void onCreate(Bundle savedInstanceState) { 331 ... 332 /* 333 * Create a new location client, using the enclosing class to 334 * handle callbacks. 335 */ 336 mLocationClient = new LocationClient(this, this, this); 337 ... 338 } 339 ... 340 /* 341 * Called when the Activity becomes visible. 342 */ 343 @Override 344 protected void onStart() { 345 super.onStart(); 346 // Connect the client. 347 mLocationClient.connect(); 348 } 349 ... 350 /* 351 * Called when the Activity is no longer visible. 352 */ 353 @Override 354 protected void onStop() { 355 // Disconnecting the client invalidates it. 356 mLocationClient.disconnect(); 357 super.onStop(); 358 } 359 ... 360} 361</pre> 362<!-- 363 Get the Current Location 364 --> 365<h2 id="GetLocation">Get the Current Location</h2> 366<p> 367 To get the current location, call 368<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#getLastLocation()">getLastLocation()</a></code>. 369 For example: 370</p> 371<pre> 372public class MainActivity extends FragmentActivity implements 373 GooglePlayServicesClient.ConnectionCallbacks, 374 GooglePlayServicesClient.OnConnectionFailedListener { 375 ... 376 // Global variable to hold the current location 377 Location mCurrentLocation; 378 ... 379 mCurrentLocation = mLocationClient.getLastLocation(); 380 ... 381} 382</pre> 383<p> 384 The next lesson, <a href="receive-location-updates.html">Receiving Location Updates</a>, shows 385 you how to receive periodic location updates from Location Services. 386</p> 387