1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.location; 18 19 import android.app.PendingIntent; 20 import android.content.Intent; 21 import android.os.Bundle; 22 import android.os.Looper; 23 import android.os.RemoteException; 24 import android.os.Handler; 25 import android.os.Message; 26 import android.util.Log; 27 28 import com.android.internal.location.DummyLocationProvider; 29 30 import java.util.ArrayList; 31 import java.util.HashMap; 32 import java.util.List; 33 34 /** 35 * This class provides access to the system location services. These 36 * services allow applications to obtain periodic updates of the 37 * device's geographical location, or to fire an application-specified 38 * {@link Intent} when the device enters the proximity of a given 39 * geographical location. 40 * 41 * <p>You do not 42 * instantiate this class directly; instead, retrieve it through 43 * {@link android.content.Context#getSystemService 44 * Context.getSystemService(Context.LOCATION_SERVICE)}. 45 * 46 * <div class="special reference"> 47 * <h3>Developer Guides</h3> 48 * <p>For more information about using location services, read the 49 * <a href="{@docRoot}guide/topics/location/index.html">Location and Maps</a> 50 * developer guide.</p> 51 * </div> 52 */ 53 public class LocationManager { 54 private static final String TAG = "LocationManager"; 55 private ILocationManager mService; 56 private final HashMap<GpsStatus.Listener, GpsStatusListenerTransport> mGpsStatusListeners = 57 new HashMap<GpsStatus.Listener, GpsStatusListenerTransport>(); 58 private final HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport> mNmeaListeners = 59 new HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport>(); 60 private final GpsStatus mGpsStatus = new GpsStatus(); 61 62 /** 63 * Name of the network location provider. This provider determines location based on 64 * availability of cell tower and WiFi access points. Results are retrieved 65 * by means of a network lookup. 66 * 67 * Requires either of the permissions android.permission.ACCESS_COARSE_LOCATION 68 * or android.permission.ACCESS_FINE_LOCATION. 69 */ 70 public static final String NETWORK_PROVIDER = "network"; 71 72 /** 73 * Name of the GPS location provider. This provider determines location using 74 * satellites. Depending on conditions, this provider may take a while to return 75 * a location fix. 76 * 77 * Requires the permission android.permission.ACCESS_FINE_LOCATION. 78 * 79 * <p> The extras Bundle for the GPS location provider can contain the 80 * following key/value pairs: 81 * 82 * <ul> 83 * <li> satellites - the number of satellites used to derive the fix 84 * </ul> 85 */ 86 public static final String GPS_PROVIDER = "gps"; 87 88 /** 89 * A special location provider for receiving locations without actually initiating 90 * a location fix. This provider can be used to passively receive location updates 91 * when other applications or services request them without actually requesting 92 * the locations yourself. This provider will return locations generated by other 93 * providers. You can query the {@link Location#getProvider()} method to determine 94 * the origin of the location update. 95 * 96 * Requires the permission android.permission.ACCESS_FINE_LOCATION, although if the GPS 97 * is not enabled this provider might only return coarse fixes. 98 */ 99 public static final String PASSIVE_PROVIDER = "passive"; 100 101 /** 102 * Key used for the Bundle extra holding a boolean indicating whether 103 * a proximity alert is entering (true) or exiting (false).. 104 */ 105 public static final String KEY_PROXIMITY_ENTERING = "entering"; 106 107 /** 108 * Key used for a Bundle extra holding an Integer status value 109 * when a status change is broadcast using a PendingIntent. 110 */ 111 public static final String KEY_STATUS_CHANGED = "status"; 112 113 /** 114 * Key used for a Bundle extra holding an Boolean status value 115 * when a provider enabled/disabled event is broadcast using a PendingIntent. 116 */ 117 public static final String KEY_PROVIDER_ENABLED = "providerEnabled"; 118 119 /** 120 * Key used for a Bundle extra holding a Location value 121 * when a location change is broadcast using a PendingIntent. 122 */ 123 public static final String KEY_LOCATION_CHANGED = "location"; 124 125 /** 126 * Broadcast intent action indicating that the GPS has either been 127 * enabled or disabled. An intent extra provides this state as a boolean, 128 * where {@code true} means enabled. 129 * @see #EXTRA_GPS_ENABLED 130 * 131 * {@hide} 132 */ 133 public static final String GPS_ENABLED_CHANGE_ACTION = 134 "android.location.GPS_ENABLED_CHANGE"; 135 136 /** 137 * Broadcast intent action when the configured location providers 138 * change. 139 */ 140 public static final String PROVIDERS_CHANGED_ACTION = 141 "android.location.PROVIDERS_CHANGED"; 142 143 /** 144 * Broadcast intent action indicating that the GPS has either started or 145 * stopped receiving GPS fixes. An intent extra provides this state as a 146 * boolean, where {@code true} means that the GPS is actively receiving fixes. 147 * @see #EXTRA_GPS_ENABLED 148 * 149 * {@hide} 150 */ 151 public static final String GPS_FIX_CHANGE_ACTION = 152 "android.location.GPS_FIX_CHANGE"; 153 154 /** 155 * The lookup key for a boolean that indicates whether GPS is enabled or 156 * disabled. {@code true} means GPS is enabled. Retrieve it with 157 * {@link android.content.Intent#getBooleanExtra(String,boolean)}. 158 * 159 * {@hide} 160 */ 161 public static final String EXTRA_GPS_ENABLED = "enabled"; 162 163 // Map from LocationListeners to their associated ListenerTransport objects 164 private HashMap<LocationListener,ListenerTransport> mListeners = 165 new HashMap<LocationListener,ListenerTransport>(); 166 167 private class ListenerTransport extends ILocationListener.Stub { 168 private static final int TYPE_LOCATION_CHANGED = 1; 169 private static final int TYPE_STATUS_CHANGED = 2; 170 private static final int TYPE_PROVIDER_ENABLED = 3; 171 private static final int TYPE_PROVIDER_DISABLED = 4; 172 173 private LocationListener mListener; 174 private final Handler mListenerHandler; 175 ListenerTransport(LocationListener listener, Looper looper)176 ListenerTransport(LocationListener listener, Looper looper) { 177 mListener = listener; 178 179 if (looper == null) { 180 mListenerHandler = new Handler() { 181 @Override 182 public void handleMessage(Message msg) { 183 _handleMessage(msg); 184 } 185 }; 186 } else { 187 mListenerHandler = new Handler(looper) { 188 @Override 189 public void handleMessage(Message msg) { 190 _handleMessage(msg); 191 } 192 }; 193 } 194 } 195 onLocationChanged(Location location)196 public void onLocationChanged(Location location) { 197 Message msg = Message.obtain(); 198 msg.what = TYPE_LOCATION_CHANGED; 199 msg.obj = location; 200 mListenerHandler.sendMessage(msg); 201 } 202 onStatusChanged(String provider, int status, Bundle extras)203 public void onStatusChanged(String provider, int status, Bundle extras) { 204 Message msg = Message.obtain(); 205 msg.what = TYPE_STATUS_CHANGED; 206 Bundle b = new Bundle(); 207 b.putString("provider", provider); 208 b.putInt("status", status); 209 if (extras != null) { 210 b.putBundle("extras", extras); 211 } 212 msg.obj = b; 213 mListenerHandler.sendMessage(msg); 214 } 215 onProviderEnabled(String provider)216 public void onProviderEnabled(String provider) { 217 Message msg = Message.obtain(); 218 msg.what = TYPE_PROVIDER_ENABLED; 219 msg.obj = provider; 220 mListenerHandler.sendMessage(msg); 221 } 222 onProviderDisabled(String provider)223 public void onProviderDisabled(String provider) { 224 Message msg = Message.obtain(); 225 msg.what = TYPE_PROVIDER_DISABLED; 226 msg.obj = provider; 227 mListenerHandler.sendMessage(msg); 228 } 229 _handleMessage(Message msg)230 private void _handleMessage(Message msg) { 231 switch (msg.what) { 232 case TYPE_LOCATION_CHANGED: 233 Location location = new Location((Location) msg.obj); 234 mListener.onLocationChanged(location); 235 break; 236 case TYPE_STATUS_CHANGED: 237 Bundle b = (Bundle) msg.obj; 238 String provider = b.getString("provider"); 239 int status = b.getInt("status"); 240 Bundle extras = b.getBundle("extras"); 241 mListener.onStatusChanged(provider, status, extras); 242 break; 243 case TYPE_PROVIDER_ENABLED: 244 mListener.onProviderEnabled((String) msg.obj); 245 break; 246 case TYPE_PROVIDER_DISABLED: 247 mListener.onProviderDisabled((String) msg.obj); 248 break; 249 } 250 try { 251 mService.locationCallbackFinished(this); 252 } catch (RemoteException e) { 253 Log.e(TAG, "locationCallbackFinished: RemoteException", e); 254 } 255 } 256 } 257 /** 258 * @hide - hide this constructor because it has a parameter 259 * of type ILocationManager, which is a system private class. The 260 * right way to create an instance of this class is using the 261 * factory Context.getSystemService. 262 */ LocationManager(ILocationManager service)263 public LocationManager(ILocationManager service) { 264 mService = service; 265 } 266 createProvider(String name, Bundle info)267 private LocationProvider createProvider(String name, Bundle info) { 268 DummyLocationProvider provider = 269 new DummyLocationProvider(name, mService); 270 provider.setRequiresNetwork(info.getBoolean("network")); 271 provider.setRequiresSatellite(info.getBoolean("satellite")); 272 provider.setRequiresCell(info.getBoolean("cell")); 273 provider.setHasMonetaryCost(info.getBoolean("cost")); 274 provider.setSupportsAltitude(info.getBoolean("altitude")); 275 provider.setSupportsSpeed(info.getBoolean("speed")); 276 provider.setSupportsBearing(info.getBoolean("bearing")); 277 provider.setPowerRequirement(info.getInt("power")); 278 provider.setAccuracy(info.getInt("accuracy")); 279 return provider; 280 } 281 282 /** 283 * Returns a list of the names of all known location providers. All 284 * providers are returned, including ones that are not permitted to be 285 * accessed by the calling activity or are currently disabled. 286 * 287 * @return list of Strings containing names of the providers 288 */ getAllProviders()289 public List<String> getAllProviders() { 290 if (false) { 291 Log.d(TAG, "getAllProviders"); 292 } 293 try { 294 return mService.getAllProviders(); 295 } catch (RemoteException ex) { 296 Log.e(TAG, "getAllProviders: RemoteException", ex); 297 } 298 return null; 299 } 300 301 /** 302 * Returns a list of the names of location providers. Only providers that 303 * are permitted to be accessed by the calling activity will be returned. 304 * 305 * @param enabledOnly if true then only the providers which are currently 306 * enabled are returned. 307 * @return list of Strings containing names of the providers 308 */ getProviders(boolean enabledOnly)309 public List<String> getProviders(boolean enabledOnly) { 310 try { 311 return mService.getProviders(null, enabledOnly); 312 } catch (RemoteException ex) { 313 Log.e(TAG, "getProviders: RemoteException", ex); 314 } 315 return null; 316 } 317 318 /** 319 * Returns the information associated with the location provider of the 320 * given name, or null if no provider exists by that name. 321 * 322 * @param name the provider name 323 * @return a LocationProvider, or null 324 * 325 * @throws IllegalArgumentException if name is null 326 * @throws SecurityException if the caller is not permitted to access the 327 * given provider. 328 */ getProvider(String name)329 public LocationProvider getProvider(String name) { 330 if (name == null) { 331 throw new IllegalArgumentException("name==null"); 332 } 333 try { 334 Bundle info = mService.getProviderInfo(name); 335 if (info == null) { 336 return null; 337 } 338 return createProvider(name, info); 339 } catch (RemoteException ex) { 340 Log.e(TAG, "getProvider: RemoteException", ex); 341 } 342 return null; 343 } 344 345 /** 346 * Returns a list of the names of LocationProviders that satisfy the given 347 * criteria, or null if none do. Only providers that are permitted to be 348 * accessed by the calling activity will be returned. 349 * 350 * @param criteria the criteria that the returned providers must match 351 * @param enabledOnly if true then only the providers which are currently 352 * enabled are returned. 353 * @return list of Strings containing names of the providers 354 */ getProviders(Criteria criteria, boolean enabledOnly)355 public List<String> getProviders(Criteria criteria, boolean enabledOnly) { 356 if (criteria == null) { 357 throw new IllegalArgumentException("criteria==null"); 358 } 359 try { 360 return mService.getProviders(criteria, enabledOnly); 361 } catch (RemoteException ex) { 362 Log.e(TAG, "getProviders: RemoteException", ex); 363 } 364 return null; 365 } 366 367 /** 368 * Returns the name of the provider that best meets the given criteria. Only providers 369 * that are permitted to be accessed by the calling activity will be 370 * returned. If several providers meet the criteria, the one with the best 371 * accuracy is returned. If no provider meets the criteria, 372 * the criteria are loosened in the following sequence: 373 * 374 * <ul> 375 * <li> power requirement 376 * <li> accuracy 377 * <li> bearing 378 * <li> speed 379 * <li> altitude 380 * </ul> 381 * 382 * <p> Note that the requirement on monetary cost is not removed 383 * in this process. 384 * 385 * @param criteria the criteria that need to be matched 386 * @param enabledOnly if true then only a provider that is currently enabled is returned 387 * @return name of the provider that best matches the requirements 388 */ getBestProvider(Criteria criteria, boolean enabledOnly)389 public String getBestProvider(Criteria criteria, boolean enabledOnly) { 390 if (criteria == null) { 391 throw new IllegalArgumentException("criteria==null"); 392 } 393 try { 394 return mService.getBestProvider(criteria, enabledOnly); 395 } catch (RemoteException ex) { 396 Log.e(TAG, "getBestProvider: RemoteException", ex); 397 } 398 return null; 399 } 400 401 /** 402 * Registers the current activity to be notified periodically by 403 * the named provider. Periodically, the supplied LocationListener will 404 * be called with the current Location or with status updates. 405 * 406 * <p> It may take a while to receive the first location update. If 407 * an immediate location is required, applications may use the 408 * {@link #getLastKnownLocation(String)} method. 409 * 410 * <p> In case the provider is disabled by the user, updates will stop, 411 * and the {@link LocationListener#onProviderDisabled(String)} 412 * method will be called. As soon as the provider is enabled again, 413 * the {@link LocationListener#onProviderEnabled(String)} method will 414 * be called and location updates will start again. 415 * 416 * <p> The update interval can be controlled using the minTime parameter. 417 * The elapsed time between location updates will never be less than 418 * minTime, although it can be more depending on the Location Provider 419 * implementation and the update interval requested by other applications. 420 * 421 * <p> Choosing a sensible value for minTime is important to conserve 422 * battery life. Each location update requires power from 423 * GPS, WIFI, Cell and other radios. Select a minTime value as high as 424 * possible while still providing a reasonable user experience. 425 * If your application is not in the foreground and showing 426 * location to the user then your application should avoid using an active 427 * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}), 428 * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes) 429 * or greater. If your application is in the foreground and showing 430 * location to the user then it is appropriate to select a faster 431 * update interval. 432 * 433 * <p> The minDistance parameter can also be used to control the 434 * frequency of location updates. If it is greater than 0 then the 435 * location provider will only send your application an update when 436 * the location has changed by at least minDistance meters, AND 437 * at least minTime milliseconds have passed. However it is more 438 * difficult for location providers to save power using the minDistance 439 * parameter, so minTime should be the primary tool to conserving battery 440 * life. 441 * 442 * <p> If your application wants to passively observe location 443 * updates triggered by other applications, but not consume 444 * any additional power otherwise, then use the {@link #PASSIVE_PROVIDER} 445 * This provider does not actively turn on or modify active location 446 * providers, so you do not need to be as careful about minTime and 447 * minDistance. However if your application performs heavy work 448 * on a location update (such as network activity) then you should 449 * select non-zero values for minTime and/or minDistance to rate-limit 450 * your update frequency in the case another application enables a 451 * location provider with extremely fast updates. 452 * 453 * <p> The calling thread must be a {@link android.os.Looper} thread such as 454 * the main thread of the calling Activity. 455 * 456 * <p class="note"> Prior to Jellybean, the minTime parameter was 457 * only a hint, and some location provider implementations ignored it. 458 * From Jellybean and onwards it is mandatory for Android compatible 459 * devices to observe both the minTime and minDistance parameters. 460 * 461 * @param provider the name of the provider with which to register 462 * @param minTime minimum time interval between location updates, in milliseconds 463 * @param minDistance minimum distance between location updates, in meters 464 * @param listener a {#link LocationListener} whose 465 * {@link LocationListener#onLocationChanged} method will be called for 466 * each location update 467 * 468 * @throws IllegalArgumentException if provider is null or doesn't exist 469 * on this device 470 * @throws IllegalArgumentException if listener is null 471 * @throws RuntimeException if the calling thread has no Looper 472 * @throws SecurityException if no suitable permission is present for the provider. 473 */ requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)474 public void requestLocationUpdates(String provider, 475 long minTime, float minDistance, LocationListener listener) { 476 if (provider == null) { 477 throw new IllegalArgumentException("provider==null"); 478 } 479 if (listener == null) { 480 throw new IllegalArgumentException("listener==null"); 481 } 482 _requestLocationUpdates(provider, null, minTime, minDistance, false, listener, null); 483 } 484 485 /** 486 * Registers the current activity to be notified periodically by 487 * the named provider. Periodically, the supplied LocationListener will 488 * be called with the current Location or with status updates. 489 * 490 * <p> It may take a while to receive the first location update. If 491 * an immediate location is required, applications may use the 492 * {@link #getLastKnownLocation(String)} method. 493 * 494 * <p> In case the provider is disabled by the user, updates will stop, 495 * and the {@link LocationListener#onProviderDisabled(String)} 496 * method will be called. As soon as the provider is enabled again, 497 * the {@link LocationListener#onProviderEnabled(String)} method will 498 * be called and location updates will start again. 499 * 500 * <p> The update interval can be controlled using the minTime parameter. 501 * The elapsed time between location updates will never be less than 502 * minTime, although it can be more depending on the Location Provider 503 * implementation and the update interval requested by other applications. 504 * 505 * <p> Choosing a sensible value for minTime is important to conserve 506 * battery life. Each location update requires power from 507 * GPS, WIFI, Cell and other radios. Select a minTime value as high as 508 * possible while still providing a reasonable user experience. 509 * If your application is not in the foreground and showing 510 * location to the user then your application should avoid using an active 511 * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}), 512 * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes) 513 * or greater. If your application is in the foreground and showing 514 * location to the user then it is appropriate to select a faster 515 * update interval. 516 * 517 * <p> The minDistance parameter can also be used to control the 518 * frequency of location updates. If it is greater than 0 then the 519 * location provider will only send your application an update when 520 * the location has changed by at least minDistance meters, AND 521 * at least minTime milliseconds have passed. However it is more 522 * difficult for location providers to save power using the minDistance 523 * parameter, so minTime should be the primary tool to conserving battery 524 * life. 525 * 526 * <p> If your application wants to passively observe location 527 * updates triggered by other applications, but not consume 528 * any additional power otherwise, then use the {@link #PASSIVE_PROVIDER} 529 * This provider does not actively turn on or modify active location 530 * providers, so you do not need to be as careful about minTime and 531 * minDistance. However if your application performs heavy work 532 * on a location update (such as network activity) then you should 533 * select non-zero values for minTime and/or minDistance to rate-limit 534 * your update frequency in the case another application enables a 535 * location provider with extremely fast updates. 536 * 537 * <p> The supplied Looper is used to implement the callback mechanism. 538 * 539 * <p class="note"> Prior to Jellybean, the minTime parameter was 540 * only a hint, and some location provider implementations ignored it. 541 * From Jellybean and onwards it is mandatory for Android compatible 542 * devices to observe both the minTime and minDistance parameters. 543 * 544 * @param provider the name of the provider with which to register 545 * @param minTime minimum time interval between location updates, in milliseconds 546 * @param minDistance minimum distance between location updates, in meters 547 * @param listener a {#link LocationListener} whose 548 * {@link LocationListener#onLocationChanged} method will be called for 549 * each location update 550 * @param looper a Looper object whose message queue will be used to 551 * implement the callback mechanism, or null to make callbacks on the 552 * main thread 553 * 554 * @throws IllegalArgumentException if provider is null or doesn't exist 555 * @throws IllegalArgumentException if listener is null 556 * @throws SecurityException if no suitable permission is present for the provider. 557 */ requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener, Looper looper)558 public void requestLocationUpdates(String provider, 559 long minTime, float minDistance, LocationListener listener, 560 Looper looper) { 561 if (provider == null) { 562 throw new IllegalArgumentException("provider==null"); 563 } 564 if (listener == null) { 565 throw new IllegalArgumentException("listener==null"); 566 } 567 _requestLocationUpdates(provider, null, minTime, minDistance, false, listener, looper); 568 } 569 570 /** 571 * Registers the current activity to be notified periodically based on 572 * the supplied criteria. Periodically, the supplied LocationListener will 573 * be called with the current Location or with status updates. 574 * 575 * <p> It may take a while to receive the first location update. If 576 * an immediate location is required, applications may use the 577 * {@link #getLastKnownLocation(String)} method. 578 * 579 * <p> In case the provider is disabled by the user, updates will stop, 580 * and the {@link LocationListener#onProviderDisabled(String)} 581 * method will be called. As soon as the provider is enabled again, 582 * the {@link LocationListener#onProviderEnabled(String)} method will 583 * be called and location updates will start again. 584 * 585 * <p> The update interval can be controlled using the minTime parameter. 586 * The elapsed time between location updates will never be less than 587 * minTime, although it can be more depending on the Location Provider 588 * implementation and the update interval requested by other applications. 589 * 590 * <p> Choosing a sensible value for minTime is important to conserve 591 * battery life. Each location update requires power from 592 * GPS, WIFI, Cell and other radios. Select a minTime value as high as 593 * possible while still providing a reasonable user experience. 594 * If your application is not in the foreground and showing 595 * location to the user then your application should avoid using an active 596 * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}), 597 * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes) 598 * or greater. If your application is in the foreground and showing 599 * location to the user then it is appropriate to select a faster 600 * update interval. 601 * 602 * <p> The minDistance parameter can also be used to control the 603 * frequency of location updates. If it is greater than 0 then the 604 * location provider will only send your application an update when 605 * the location has changed by at least minDistance meters, AND 606 * at least minTime milliseconds have passed. However it is more 607 * difficult for location providers to save power using the minDistance 608 * parameter, so minTime should be the primary tool to conserving battery 609 * life. 610 * 611 * <p> The supplied Looper is used to implement the callback mechanism. 612 * 613 * <p class="note"> Prior to Jellybean, the minTime parameter was 614 * only a hint, and some location provider implementations ignored it. 615 * From Jellybean and onwards it is mandatory for Android compatible 616 * devices to observe both the minTime and minDistance parameters. 617 * 618 * @param minTime minimum time interval between location updates, in milliseconds 619 * @param minDistance minimum distance between location updates, in meters 620 * @param criteria contains parameters for the location manager to choose the 621 * appropriate provider and parameters to compute the location 622 * @param listener a {#link LocationListener} whose 623 * {@link LocationListener#onLocationChanged} method will be called for 624 * each location update 625 * @param looper a Looper object whose message queue will be used to 626 * implement the callback mechanism, or null to make callbacks on the 627 * main thread. 628 * 629 * @throws IllegalArgumentException if criteria is null 630 * @throws IllegalArgumentException if listener is null 631 * @throws SecurityException if no suitable permission is present for the provider. 632 */ requestLocationUpdates(long minTime, float minDistance, Criteria criteria, LocationListener listener, Looper looper)633 public void requestLocationUpdates(long minTime, float minDistance, 634 Criteria criteria, LocationListener listener, Looper looper) { 635 if (criteria == null) { 636 throw new IllegalArgumentException("criteria==null"); 637 } 638 if (listener == null) { 639 throw new IllegalArgumentException("listener==null"); 640 } 641 _requestLocationUpdates(null, criteria, minTime, minDistance, false, listener, looper); 642 } 643 _requestLocationUpdates(String provider, Criteria criteria, long minTime, float minDistance, boolean singleShot, LocationListener listener, Looper looper)644 private void _requestLocationUpdates(String provider, Criteria criteria, long minTime, 645 float minDistance, boolean singleShot, LocationListener listener, Looper looper) { 646 if (minTime < 0L) { 647 minTime = 0L; 648 } 649 if (minDistance < 0.0f) { 650 minDistance = 0.0f; 651 } 652 653 try { 654 synchronized (mListeners) { 655 ListenerTransport transport = mListeners.get(listener); 656 if (transport == null) { 657 transport = new ListenerTransport(listener, looper); 658 } 659 mListeners.put(listener, transport); 660 mService.requestLocationUpdates(provider, criteria, minTime, minDistance, singleShot, transport); 661 } 662 } catch (RemoteException ex) { 663 Log.e(TAG, "requestLocationUpdates: DeadObjectException", ex); 664 } 665 } 666 667 /** 668 * Registers the current activity to be notified periodically by 669 * the named provider. Periodically, the supplied PendingIntent will 670 * be broadcast with the current Location or with status updates. 671 * 672 * <p> Location updates are sent with a key of 673 * {@link #KEY_LOCATION_CHANGED} and a {@link android.location.Location} value. 674 * 675 * <p> It may take a while to receive the first location update. If 676 * an immediate location is required, applications may use the 677 * {@link #getLastKnownLocation(String)} method. 678 * 679 * <p> The update interval can be controlled using the minTime parameter. 680 * The elapsed time between location updates will never be less than 681 * minTime, although it can be more depending on the Location Provider 682 * implementation and the update interval requested by other applications. 683 * 684 * <p> Choosing a sensible value for minTime is important to conserve 685 * battery life. Each location update requires power from 686 * GPS, WIFI, Cell and other radios. Select a minTime value as high as 687 * possible while still providing a reasonable user experience. 688 * If your application is not in the foreground and showing 689 * location to the user then your application should avoid using an active 690 * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}), 691 * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes) 692 * or greater. If your application is in the foreground and showing 693 * location to the user then it is appropriate to select a faster 694 * update interval. 695 * 696 * <p> The minDistance parameter can also be used to control the 697 * frequency of location updates. If it is greater than 0 then the 698 * location provider will only send your application an update when 699 * the location has changed by at least minDistance meters, AND 700 * at least minTime milliseconds have passed. However it is more 701 * difficult for location providers to save power using the minDistance 702 * parameter, so minTime should be the primary tool to conserving battery 703 * life. 704 * 705 * <p> If your application wants to passively observe location 706 * updates triggered by other applications, but not consume 707 * any additional power otherwise, then use the {@link #PASSIVE_PROVIDER} 708 * This provider does not actively turn on or modify active location 709 * providers, so you do not need to be as careful about minTime and 710 * minDistance. However if your application performs heavy work 711 * on a location update (such as network activity) then you should 712 * select non-zero values for minTime and/or minDistance to rate-limit 713 * your update frequency in the case another application enables a 714 * location provider with extremely fast updates. 715 * 716 * <p> If the provider is disabled by the user, updates will stop, 717 * and an intent will be sent with an extra with key 718 * {@link #KEY_PROVIDER_ENABLED} and a boolean value of false. 719 * If the provider is re-enabled, an intent will be sent with an 720 * extra with key {@link #KEY_PROVIDER_ENABLED} and a boolean value of 721 * true and location updates will start again. 722 * 723 * <p> If the provider's status changes, an intent will be sent with 724 * an extra with key {@link #KEY_STATUS_CHANGED} and an integer value 725 * indicating the new status. Any extras associated with the status 726 * update will be sent as well. 727 * 728 * <p class="note"> Prior to Jellybean, the minTime parameter was 729 * only a hint, and some location provider implementations ignored it. 730 * From Jellybean and onwards it is mandatory for Android compatible 731 * devices to observe both the minTime and minDistance parameters. 732 * 733 * @param provider the name of the provider with which to register 734 * @param minTime minimum time interval between location updates, in milliseconds 735 * @param minDistance minimum distance between location updates, in meters 736 * @param intent a {#link PendingIntent} to be sent for each location update 737 * 738 * @throws IllegalArgumentException if provider is null or doesn't exist 739 * on this device 740 * @throws IllegalArgumentException if intent is null 741 * @throws SecurityException if no suitable permission is present for the provider. 742 */ requestLocationUpdates(String provider, long minTime, float minDistance, PendingIntent intent)743 public void requestLocationUpdates(String provider, 744 long minTime, float minDistance, PendingIntent intent) { 745 if (provider == null) { 746 throw new IllegalArgumentException("provider==null"); 747 } 748 if (intent == null) { 749 throw new IllegalArgumentException("intent==null"); 750 } 751 _requestLocationUpdates(provider, null, minTime, minDistance, false, intent); 752 } 753 754 /** 755 * Registers the current activity to be notified periodically based on 756 * the supplied criteria. Periodically, the supplied PendingIntent will 757 * be broadcast with the current Location or with status updates. 758 * 759 * <p> Location updates are sent with a key of 760 * {@link #KEY_LOCATION_CHANGED} and a {@link android.location.Location} value. 761 * 762 * <p> It may take a while to receive the first location update. If 763 * an immediate location is required, applications may use the 764 * {@link #getLastKnownLocation(String)} method. 765 * 766 * <p> The update interval can be controlled using the minTime parameter. 767 * The elapsed time between location updates will never be less than 768 * minTime, although it can be more depending on the Location Provider 769 * implementation and the update interval requested by other applications. 770 * 771 * <p> Choosing a sensible value for minTime is important to conserve 772 * battery life. Each location update requires power from 773 * GPS, WIFI, Cell and other radios. Select a minTime value as high as 774 * possible while still providing a reasonable user experience. 775 * If your application is not in the foreground and showing 776 * location to the user then your application should avoid using an active 777 * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}), 778 * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes) 779 * or greater. If your application is in the foreground and showing 780 * location to the user then it is appropriate to select a faster 781 * update interval. 782 * 783 * <p> The minDistance parameter can also be used to control the 784 * frequency of location updates. If it is greater than 0 then the 785 * location provider will only send your application an update when 786 * the location has changed by at least minDistance meters, AND 787 * at least minTime milliseconds have passed. However it is more 788 * difficult for location providers to save power using the minDistance 789 * parameter, so minTime should be the primary tool to conserving battery 790 * life. 791 * 792 * <p> If the provider is disabled by the user, updates will stop, 793 * and an intent will be sent with an extra with key 794 * {@link #KEY_PROVIDER_ENABLED} and a boolean value of false. 795 * If the provider is re-enabled, an intent will be sent with an 796 * extra with key {@link #KEY_PROVIDER_ENABLED} and a boolean value of 797 * true and location updates will start again. 798 * 799 * <p> If the provider's status changes, an intent will be sent with 800 * an extra with key {@link #KEY_STATUS_CHANGED} and an integer value 801 * indicating the new status. Any extras associated with the status 802 * update will be sent as well. 803 * 804 * <p class="note"> Prior to Jellybean, the minTime parameter was 805 * only a hint, and some location provider implementations ignored it. 806 * From Jellybean and onwards it is mandatory for Android compatible 807 * devices to observe both the minTime and minDistance parameters. 808 * 809 * @param minTime minimum time interval between location updates, in milliseconds 810 * @param minDistance minimum distance between location updates, in meters 811 * @param criteria contains parameters for the location manager to choose the 812 * appropriate provider and parameters to compute the location 813 * @param intent a {#link PendingIntent} to be sent for each location update 814 * 815 * @throws IllegalArgumentException if criteria is null 816 * @throws IllegalArgumentException if intent is null 817 * @throws SecurityException if no suitable permission is present for the provider. 818 */ requestLocationUpdates(long minTime, float minDistance, Criteria criteria, PendingIntent intent)819 public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria, 820 PendingIntent intent) { 821 if (criteria == null) { 822 throw new IllegalArgumentException("criteria==null"); 823 } 824 if (intent == null) { 825 throw new IllegalArgumentException("intent==null"); 826 } 827 _requestLocationUpdates(null, criteria, minTime, minDistance, false, intent); 828 } 829 _requestLocationUpdates(String provider, Criteria criteria, long minTime, float minDistance, boolean singleShot, PendingIntent intent)830 private void _requestLocationUpdates(String provider, Criteria criteria, 831 long minTime, float minDistance, boolean singleShot, PendingIntent intent) { 832 if (minTime < 0L) { 833 minTime = 0L; 834 } 835 if (minDistance < 0.0f) { 836 minDistance = 0.0f; 837 } 838 839 try { 840 mService.requestLocationUpdatesPI(provider, criteria, minTime, minDistance, singleShot, intent); 841 } catch (RemoteException ex) { 842 Log.e(TAG, "requestLocationUpdates: RemoteException", ex); 843 } 844 } 845 846 /** 847 * Requests a single location update from the named provider. 848 * 849 * <p> It may take a while to receive the most recent location. If 850 * an immediate location is required, applications may use the 851 * {@link #getLastKnownLocation(String)} method. 852 * 853 * <p> In case the provider is disabled by the user, the update will not be received, 854 * and the {@link LocationListener#onProviderDisabled(String)} 855 * method will be called. As soon as the provider is enabled again, 856 * the {@link LocationListener#onProviderEnabled(String)} method will 857 * be called and location updates will start again. 858 * 859 * <p> The supplied Looper is used to implement the callback mechanism. 860 * 861 * @param provider the name of the provider with which to register 862 * @param listener a {#link LocationListener} whose 863 * {@link LocationListener#onLocationChanged} method will be called when 864 * the location update is available 865 * @param looper a Looper object whose message queue will be used to 866 * implement the callback mechanism, or null to make callbacks on the 867 * main thread 868 * 869 * @throws IllegalArgumentException if provider is null or doesn't exist 870 * @throws IllegalArgumentException if listener is null 871 * @throws SecurityException if no suitable permission is present for the provider 872 */ requestSingleUpdate(String provider, LocationListener listener, Looper looper)873 public void requestSingleUpdate(String provider, LocationListener listener, Looper looper) { 874 if (provider == null) { 875 throw new IllegalArgumentException("provider==null"); 876 } 877 if (listener == null) { 878 throw new IllegalArgumentException("listener==null"); 879 } 880 _requestLocationUpdates(provider, null, 0L, 0.0f, true, listener, looper); 881 } 882 883 /** 884 * Requests a single location update based on the specified criteria. 885 * 886 * <p> It may take a while to receive the most recent location. If 887 * an immediate location is required, applications may use the 888 * {@link #getLastKnownLocation(String)} method. 889 * 890 * <p> In case the provider is disabled by the user, the update will not be received, 891 * and the {@link LocationListener#onProviderDisabled(String)} 892 * method will be called. As soon as the provider is enabled again, 893 * the {@link LocationListener#onProviderEnabled(String)} method will 894 * be called and location updates will start again. 895 * 896 * <p> The supplied Looper is used to implement the callback mechanism. 897 * 898 * @param criteria contains parameters for the location manager to choose the 899 * appropriate provider and parameters to compute the location 900 * @param listener a {#link LocationListener} whose 901 * {@link LocationListener#onLocationChanged} method will be called when 902 * the location update is available 903 * @param looper a Looper object whose message queue will be used to 904 * implement the callback mechanism, or null to make callbacks on the 905 * main thread 906 * 907 * @throws IllegalArgumentException if criteria is null 908 * @throws IllegalArgumentException if listener is null 909 * @throws SecurityException if no suitable permission is present to access 910 * the location services 911 */ requestSingleUpdate(Criteria criteria, LocationListener listener, Looper looper)912 public void requestSingleUpdate(Criteria criteria, LocationListener listener, Looper looper) { 913 if (criteria == null) { 914 throw new IllegalArgumentException("criteria==null"); 915 } 916 if (listener == null) { 917 throw new IllegalArgumentException("listener==null"); 918 } 919 _requestLocationUpdates(null, criteria, 0L, 0.0f, true, listener, looper); 920 } 921 922 /** 923 * Requests a single location update from the named provider. 924 * 925 * <p> It may take a while to receive the most recent location. If 926 * an immediate location is required, applications may use the 927 * {@link #getLastKnownLocation(String)} method. 928 * 929 * <p> Location updates are sent with a key of 930 * {@link #KEY_LOCATION_CHANGED} and a {@link android.location.Location} value. 931 * 932 * <p> In case the provider is disabled by the user, the update will not be received, 933 * and the {@link LocationListener#onProviderDisabled(String)} 934 * method will be called. As soon as the provider is enabled again, 935 * the {@link LocationListener#onProviderEnabled(String)} method will 936 * be called and location updates will start again. 937 * 938 * @param provider the name of the provider with which to register 939 * @param intent a {#link PendingIntent} to be sent for the location update 940 * 941 * @throws IllegalArgumentException if provider is null or doesn't exist 942 * @throws IllegalArgumentException if intent is null 943 * @throws SecurityException if no suitable permission is present for the provider 944 */ requestSingleUpdate(String provider, PendingIntent intent)945 public void requestSingleUpdate(String provider, PendingIntent intent) { 946 if (provider == null) { 947 throw new IllegalArgumentException("provider==null"); 948 } 949 if (intent == null) { 950 throw new IllegalArgumentException("intent==null"); 951 } 952 _requestLocationUpdates(provider, null, 0L, 0.0f, true, intent); 953 } 954 955 /** 956 * Requests a single location update based on the specified criteria. 957 * 958 * <p> It may take a while to receive the most recent location. If 959 * an immediate location is required, applications may use the 960 * {@link #getLastKnownLocation(String)} method. 961 * 962 * <p> Location updates are sent with a key of 963 * {@link #KEY_LOCATION_CHANGED} and a {@link android.location.Location} value. 964 * 965 * <p> If the provider is disabled by the user, an update will not be 966 * received, and an intent will be sent with an extra with key 967 * {@link #KEY_PROVIDER_ENABLED} and a boolean value of false. 968 * If the provider is re-enabled, an intent will be sent with an 969 * extra with key {@link #KEY_PROVIDER_ENABLED} and a boolean value of 970 * true and the location update will occur. 971 * 972 * @param criteria contains parameters for the location manager to choose the 973 * appropriate provider and parameters to compute the location 974 * @param intent a {#link PendingIntent} to be sent for the location update 975 * 976 * @throws IllegalArgumentException if provider is null or doesn't exist 977 * @throws IllegalArgumentException if intent is null 978 * @throws SecurityException if no suitable permission is present for the provider 979 */ requestSingleUpdate(Criteria criteria, PendingIntent intent)980 public void requestSingleUpdate(Criteria criteria, PendingIntent intent) { 981 if (criteria == null) { 982 throw new IllegalArgumentException("criteria==null"); 983 } 984 if (intent == null) { 985 throw new IllegalArgumentException("intent==null"); 986 } 987 _requestLocationUpdates(null, criteria, 0L, 0.0f, true, intent); 988 } 989 990 /** 991 * Removes any current registration for location updates of the current activity 992 * with the given LocationListener. Following this call, updates will no longer 993 * occur for this listener. 994 * 995 * @param listener {#link LocationListener} object that no longer needs location updates 996 * @throws IllegalArgumentException if listener is null 997 */ removeUpdates(LocationListener listener)998 public void removeUpdates(LocationListener listener) { 999 if (listener == null) { 1000 throw new IllegalArgumentException("listener==null"); 1001 } 1002 if (false) { 1003 Log.d(TAG, "removeUpdates: listener = " + listener); 1004 } 1005 try { 1006 ListenerTransport transport = mListeners.remove(listener); 1007 if (transport != null) { 1008 mService.removeUpdates(transport); 1009 } 1010 } catch (RemoteException ex) { 1011 Log.e(TAG, "removeUpdates: DeadObjectException", ex); 1012 } 1013 } 1014 1015 /** 1016 * Removes any current registration for location updates of the current activity 1017 * with the given PendingIntent. Following this call, updates will no longer 1018 * occur for this intent. 1019 * 1020 * @param intent {#link PendingIntent} object that no longer needs location updates 1021 * @throws IllegalArgumentException if intent is null 1022 */ removeUpdates(PendingIntent intent)1023 public void removeUpdates(PendingIntent intent) { 1024 if (intent == null) { 1025 throw new IllegalArgumentException("intent==null"); 1026 } 1027 if (false) { 1028 Log.d(TAG, "removeUpdates: intent = " + intent); 1029 } 1030 try { 1031 mService.removeUpdatesPI(intent); 1032 } catch (RemoteException ex) { 1033 Log.e(TAG, "removeUpdates: RemoteException", ex); 1034 } 1035 } 1036 1037 /** 1038 * Sets a proximity alert for the location given by the position 1039 * (latitude, longitude) and the given radius. When the device 1040 * detects that it has entered or exited the area surrounding the 1041 * location, the given PendingIntent will be used to create an Intent 1042 * to be fired. 1043 * 1044 * <p> The fired Intent will have a boolean extra added with key 1045 * {@link #KEY_PROXIMITY_ENTERING}. If the value is true, the device is 1046 * entering the proximity region; if false, it is exiting. 1047 * 1048 * <p> Due to the approximate nature of position estimation, if the 1049 * device passes through the given area briefly, it is possible 1050 * that no Intent will be fired. Similarly, an Intent could be 1051 * fired if the device passes very close to the given area but 1052 * does not actually enter it. 1053 * 1054 * <p> After the number of milliseconds given by the expiration 1055 * parameter, the location manager will delete this proximity 1056 * alert and no longer monitor it. A value of -1 indicates that 1057 * there should be no expiration time. 1058 * 1059 * <p> In case the screen goes to sleep, checks for proximity alerts 1060 * happen only once every 4 minutes. This conserves battery life by 1061 * ensuring that the device isn't perpetually awake. 1062 * 1063 * <p> Internally, this method uses both {@link #NETWORK_PROVIDER} 1064 * and {@link #GPS_PROVIDER}. 1065 * 1066 * @param latitude the latitude of the central point of the 1067 * alert region 1068 * @param longitude the longitude of the central point of the 1069 * alert region 1070 * @param radius the radius of the central point of the 1071 * alert region, in meters 1072 * @param expiration time for this proximity alert, in milliseconds, 1073 * or -1 to indicate no expiration 1074 * @param intent a PendingIntent that will be used to generate an Intent to 1075 * fire when entry to or exit from the alert region is detected 1076 * 1077 * @throws SecurityException if no permission exists for the required 1078 * providers. 1079 */ addProximityAlert(double latitude, double longitude, float radius, long expiration, PendingIntent intent)1080 public void addProximityAlert(double latitude, double longitude, 1081 float radius, long expiration, PendingIntent intent) { 1082 if (false) { 1083 Log.d(TAG, "addProximityAlert: latitude = " + latitude + 1084 ", longitude = " + longitude + ", radius = " + radius + 1085 ", expiration = " + expiration + 1086 ", intent = " + intent); 1087 } 1088 try { 1089 mService.addProximityAlert(latitude, longitude, radius, 1090 expiration, intent); 1091 } catch (RemoteException ex) { 1092 Log.e(TAG, "addProximityAlert: RemoteException", ex); 1093 } 1094 } 1095 1096 /** 1097 * Removes the proximity alert with the given PendingIntent. 1098 * 1099 * @param intent the PendingIntent that no longer needs to be notified of 1100 * proximity alerts 1101 */ removeProximityAlert(PendingIntent intent)1102 public void removeProximityAlert(PendingIntent intent) { 1103 if (false) { 1104 Log.d(TAG, "removeProximityAlert: intent = " + intent); 1105 } 1106 try { 1107 mService.removeProximityAlert(intent); 1108 } catch (RemoteException ex) { 1109 Log.e(TAG, "removeProximityAlert: RemoteException", ex); 1110 } 1111 } 1112 1113 /** 1114 * Returns the current enabled/disabled status of the given provider. If the 1115 * user has enabled this provider in the Settings menu, true is returned 1116 * otherwise false is returned 1117 * 1118 * @param provider the name of the provider 1119 * @return true if the provider is enabled 1120 * 1121 * @throws SecurityException if no suitable permission is present for the provider. 1122 * @throws IllegalArgumentException if provider is null 1123 */ isProviderEnabled(String provider)1124 public boolean isProviderEnabled(String provider) { 1125 if (provider == null) { 1126 throw new IllegalArgumentException("provider==null"); 1127 } 1128 try { 1129 return mService.isProviderEnabled(provider); 1130 } catch (RemoteException ex) { 1131 Log.e(TAG, "isProviderEnabled: RemoteException", ex); 1132 return false; 1133 } 1134 } 1135 1136 /** 1137 * Returns a Location indicating the data from the last known 1138 * location fix obtained from the given provider. This can be done 1139 * without starting the provider. Note that this location could 1140 * be out-of-date, for example if the device was turned off and 1141 * moved to another location. 1142 * 1143 * <p> If the provider is currently disabled, null is returned. 1144 * 1145 * @param provider the name of the provider 1146 * @return the last known location for the provider, or null 1147 * 1148 * @throws SecurityException if no suitable permission is present for the provider. 1149 * @throws IllegalArgumentException if provider is null or doesn't exist 1150 */ getLastKnownLocation(String provider)1151 public Location getLastKnownLocation(String provider) { 1152 if (provider == null) { 1153 throw new IllegalArgumentException("provider==null"); 1154 } 1155 try { 1156 return mService.getLastKnownLocation(provider); 1157 } catch (RemoteException ex) { 1158 Log.e(TAG, "getLastKnowLocation: RemoteException", ex); 1159 return null; 1160 } 1161 } 1162 1163 // Mock provider support 1164 1165 /** 1166 * Creates a mock location provider and adds it to the set of active providers. 1167 * 1168 * @param name the provider name 1169 * @param requiresNetwork 1170 * @param requiresSatellite 1171 * @param requiresCell 1172 * @param hasMonetaryCost 1173 * @param supportsAltitude 1174 * @param supportsSpeed 1175 * @param supportsBearing 1176 * @param powerRequirement 1177 * @param accuracy 1178 * 1179 * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present 1180 * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION 1181 * Settings.Secure.ALLOW_MOCK_LOCATION} system setting is not enabled 1182 * @throws IllegalArgumentException if a provider with the given name already exists 1183 */ addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite, boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude, boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy)1184 public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite, 1185 boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude, 1186 boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) { 1187 try { 1188 mService.addTestProvider(name, requiresNetwork, requiresSatellite, requiresCell, 1189 hasMonetaryCost, supportsAltitude, supportsSpeed, supportsBearing, powerRequirement, 1190 accuracy); 1191 } catch (RemoteException ex) { 1192 Log.e(TAG, "addTestProvider: RemoteException", ex); 1193 } 1194 } 1195 1196 /** 1197 * Removes the mock location provider with the given name. 1198 * 1199 * @param provider the provider name 1200 * 1201 * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present 1202 * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION 1203 * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled 1204 * @throws IllegalArgumentException if no provider with the given name exists 1205 */ removeTestProvider(String provider)1206 public void removeTestProvider(String provider) { 1207 try { 1208 mService.removeTestProvider(provider); 1209 } catch (RemoteException ex) { 1210 Log.e(TAG, "removeTestProvider: RemoteException", ex); 1211 } 1212 } 1213 1214 /** 1215 * Sets a mock location for the given provider. This location will be used in place 1216 * of any actual location from the provider. 1217 * 1218 * @param provider the provider name 1219 * @param loc the mock location 1220 * 1221 * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present 1222 * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION 1223 * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled 1224 * @throws IllegalArgumentException if no provider with the given name exists 1225 */ setTestProviderLocation(String provider, Location loc)1226 public void setTestProviderLocation(String provider, Location loc) { 1227 try { 1228 mService.setTestProviderLocation(provider, loc); 1229 } catch (RemoteException ex) { 1230 Log.e(TAG, "setTestProviderLocation: RemoteException", ex); 1231 } 1232 } 1233 1234 /** 1235 * Removes any mock location associated with the given provider. 1236 * 1237 * @param provider the provider name 1238 * 1239 * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present 1240 * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION 1241 * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled 1242 * @throws IllegalArgumentException if no provider with the given name exists 1243 */ clearTestProviderLocation(String provider)1244 public void clearTestProviderLocation(String provider) { 1245 try { 1246 mService.clearTestProviderLocation(provider); 1247 } catch (RemoteException ex) { 1248 Log.e(TAG, "clearTestProviderLocation: RemoteException", ex); 1249 } 1250 } 1251 1252 /** 1253 * Sets a mock enabled value for the given provider. This value will be used in place 1254 * of any actual value from the provider. 1255 * 1256 * @param provider the provider name 1257 * @param enabled the mock enabled value 1258 * 1259 * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present 1260 * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION 1261 * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled 1262 * @throws IllegalArgumentException if no provider with the given name exists 1263 */ setTestProviderEnabled(String provider, boolean enabled)1264 public void setTestProviderEnabled(String provider, boolean enabled) { 1265 try { 1266 mService.setTestProviderEnabled(provider, enabled); 1267 } catch (RemoteException ex) { 1268 Log.e(TAG, "setTestProviderEnabled: RemoteException", ex); 1269 } 1270 } 1271 1272 /** 1273 * Removes any mock enabled value associated with the given provider. 1274 * 1275 * @param provider the provider name 1276 * 1277 * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present 1278 * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION 1279 * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled 1280 * @throws IllegalArgumentException if no provider with the given name exists 1281 */ clearTestProviderEnabled(String provider)1282 public void clearTestProviderEnabled(String provider) { 1283 try { 1284 mService.clearTestProviderEnabled(provider); 1285 } catch (RemoteException ex) { 1286 Log.e(TAG, "clearTestProviderEnabled: RemoteException", ex); 1287 } 1288 1289 } 1290 1291 /** 1292 * Sets mock status values for the given provider. These values will be used in place 1293 * of any actual values from the provider. 1294 * 1295 * @param provider the provider name 1296 * @param status the mock status 1297 * @param extras a Bundle containing mock extras 1298 * @param updateTime the mock update time 1299 * 1300 * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present 1301 * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION 1302 * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled 1303 * @throws IllegalArgumentException if no provider with the given name exists 1304 */ setTestProviderStatus(String provider, int status, Bundle extras, long updateTime)1305 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) { 1306 try { 1307 mService.setTestProviderStatus(provider, status, extras, updateTime); 1308 } catch (RemoteException ex) { 1309 Log.e(TAG, "setTestProviderStatus: RemoteException", ex); 1310 } 1311 } 1312 1313 /** 1314 * Removes any mock status values associated with the given provider. 1315 * 1316 * @param provider the provider name 1317 * 1318 * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present 1319 * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION 1320 * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled 1321 * @throws IllegalArgumentException if no provider with the given name exists 1322 */ clearTestProviderStatus(String provider)1323 public void clearTestProviderStatus(String provider) { 1324 try { 1325 mService.clearTestProviderStatus(provider); 1326 } catch (RemoteException ex) { 1327 Log.e(TAG, "clearTestProviderStatus: RemoteException", ex); 1328 } 1329 } 1330 1331 // GPS-specific support 1332 1333 // This class is used to send GPS status events to the client's main thread. 1334 private class GpsStatusListenerTransport extends IGpsStatusListener.Stub { 1335 1336 private final GpsStatus.Listener mListener; 1337 private final GpsStatus.NmeaListener mNmeaListener; 1338 1339 // This must not equal any of the GpsStatus event IDs 1340 private static final int NMEA_RECEIVED = 1000; 1341 1342 private class Nmea { 1343 long mTimestamp; 1344 String mNmea; 1345 Nmea(long timestamp, String nmea)1346 Nmea(long timestamp, String nmea) { 1347 mTimestamp = timestamp; 1348 mNmea = nmea; 1349 } 1350 } 1351 private ArrayList<Nmea> mNmeaBuffer; 1352 GpsStatusListenerTransport(GpsStatus.Listener listener)1353 GpsStatusListenerTransport(GpsStatus.Listener listener) { 1354 mListener = listener; 1355 mNmeaListener = null; 1356 } 1357 GpsStatusListenerTransport(GpsStatus.NmeaListener listener)1358 GpsStatusListenerTransport(GpsStatus.NmeaListener listener) { 1359 mNmeaListener = listener; 1360 mListener = null; 1361 mNmeaBuffer = new ArrayList<Nmea>(); 1362 } 1363 onGpsStarted()1364 public void onGpsStarted() { 1365 if (mListener != null) { 1366 Message msg = Message.obtain(); 1367 msg.what = GpsStatus.GPS_EVENT_STARTED; 1368 mGpsHandler.sendMessage(msg); 1369 } 1370 } 1371 onGpsStopped()1372 public void onGpsStopped() { 1373 if (mListener != null) { 1374 Message msg = Message.obtain(); 1375 msg.what = GpsStatus.GPS_EVENT_STOPPED; 1376 mGpsHandler.sendMessage(msg); 1377 } 1378 } 1379 onFirstFix(int ttff)1380 public void onFirstFix(int ttff) { 1381 if (mListener != null) { 1382 mGpsStatus.setTimeToFirstFix(ttff); 1383 Message msg = Message.obtain(); 1384 msg.what = GpsStatus.GPS_EVENT_FIRST_FIX; 1385 mGpsHandler.sendMessage(msg); 1386 } 1387 } 1388 onSvStatusChanged(int svCount, int[] prns, float[] snrs, float[] elevations, float[] azimuths, int ephemerisMask, int almanacMask, int usedInFixMask)1389 public void onSvStatusChanged(int svCount, int[] prns, float[] snrs, 1390 float[] elevations, float[] azimuths, int ephemerisMask, 1391 int almanacMask, int usedInFixMask) { 1392 if (mListener != null) { 1393 mGpsStatus.setStatus(svCount, prns, snrs, elevations, azimuths, 1394 ephemerisMask, almanacMask, usedInFixMask); 1395 1396 Message msg = Message.obtain(); 1397 msg.what = GpsStatus.GPS_EVENT_SATELLITE_STATUS; 1398 // remove any SV status messages already in the queue 1399 mGpsHandler.removeMessages(GpsStatus.GPS_EVENT_SATELLITE_STATUS); 1400 mGpsHandler.sendMessage(msg); 1401 } 1402 } 1403 onNmeaReceived(long timestamp, String nmea)1404 public void onNmeaReceived(long timestamp, String nmea) { 1405 if (mNmeaListener != null) { 1406 synchronized (mNmeaBuffer) { 1407 mNmeaBuffer.add(new Nmea(timestamp, nmea)); 1408 } 1409 Message msg = Message.obtain(); 1410 msg.what = NMEA_RECEIVED; 1411 // remove any NMEA_RECEIVED messages already in the queue 1412 mGpsHandler.removeMessages(NMEA_RECEIVED); 1413 mGpsHandler.sendMessage(msg); 1414 } 1415 } 1416 1417 private final Handler mGpsHandler = new Handler() { 1418 @Override 1419 public void handleMessage(Message msg) { 1420 if (msg.what == NMEA_RECEIVED) { 1421 synchronized (mNmeaBuffer) { 1422 int length = mNmeaBuffer.size(); 1423 for (int i = 0; i < length; i++) { 1424 Nmea nmea = mNmeaBuffer.get(i); 1425 mNmeaListener.onNmeaReceived(nmea.mTimestamp, nmea.mNmea); 1426 } 1427 mNmeaBuffer.clear(); 1428 } 1429 } else { 1430 // synchronize on mGpsStatus to ensure the data is copied atomically. 1431 synchronized(mGpsStatus) { 1432 mListener.onGpsStatusChanged(msg.what); 1433 } 1434 } 1435 } 1436 }; 1437 } 1438 1439 /** 1440 * Adds a GPS status listener. 1441 * 1442 * @param listener GPS status listener object to register 1443 * 1444 * @return true if the listener was successfully added 1445 * 1446 * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present 1447 */ addGpsStatusListener(GpsStatus.Listener listener)1448 public boolean addGpsStatusListener(GpsStatus.Listener listener) { 1449 boolean result; 1450 1451 if (mGpsStatusListeners.get(listener) != null) { 1452 // listener is already registered 1453 return true; 1454 } 1455 try { 1456 GpsStatusListenerTransport transport = new GpsStatusListenerTransport(listener); 1457 result = mService.addGpsStatusListener(transport); 1458 if (result) { 1459 mGpsStatusListeners.put(listener, transport); 1460 } 1461 } catch (RemoteException e) { 1462 Log.e(TAG, "RemoteException in registerGpsStatusListener: ", e); 1463 result = false; 1464 } 1465 1466 return result; 1467 } 1468 1469 /** 1470 * Removes a GPS status listener. 1471 * 1472 * @param listener GPS status listener object to remove 1473 */ removeGpsStatusListener(GpsStatus.Listener listener)1474 public void removeGpsStatusListener(GpsStatus.Listener listener) { 1475 try { 1476 GpsStatusListenerTransport transport = mGpsStatusListeners.remove(listener); 1477 if (transport != null) { 1478 mService.removeGpsStatusListener(transport); 1479 } 1480 } catch (RemoteException e) { 1481 Log.e(TAG, "RemoteException in unregisterGpsStatusListener: ", e); 1482 } 1483 } 1484 1485 /** 1486 * Adds an NMEA listener. 1487 * 1488 * @param listener a {#link GpsStatus.NmeaListener} object to register 1489 * 1490 * @return true if the listener was successfully added 1491 * 1492 * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present 1493 */ addNmeaListener(GpsStatus.NmeaListener listener)1494 public boolean addNmeaListener(GpsStatus.NmeaListener listener) { 1495 boolean result; 1496 1497 if (mNmeaListeners.get(listener) != null) { 1498 // listener is already registered 1499 return true; 1500 } 1501 try { 1502 GpsStatusListenerTransport transport = new GpsStatusListenerTransport(listener); 1503 result = mService.addGpsStatusListener(transport); 1504 if (result) { 1505 mNmeaListeners.put(listener, transport); 1506 } 1507 } catch (RemoteException e) { 1508 Log.e(TAG, "RemoteException in registerGpsStatusListener: ", e); 1509 result = false; 1510 } 1511 1512 return result; 1513 } 1514 1515 /** 1516 * Removes an NMEA listener. 1517 * 1518 * @param listener a {#link GpsStatus.NmeaListener} object to remove 1519 */ removeNmeaListener(GpsStatus.NmeaListener listener)1520 public void removeNmeaListener(GpsStatus.NmeaListener listener) { 1521 try { 1522 GpsStatusListenerTransport transport = mNmeaListeners.remove(listener); 1523 if (transport != null) { 1524 mService.removeGpsStatusListener(transport); 1525 } 1526 } catch (RemoteException e) { 1527 Log.e(TAG, "RemoteException in unregisterGpsStatusListener: ", e); 1528 } 1529 } 1530 1531 /** 1532 * Retrieves information about the current status of the GPS engine. 1533 * This should only be called from the {@link GpsStatus.Listener#onGpsStatusChanged} 1534 * callback to ensure that the data is copied atomically. 1535 * 1536 * The caller may either pass in a {@link GpsStatus} object to set with the latest 1537 * status information, or pass null to create a new {@link GpsStatus} object. 1538 * 1539 * @param status object containing GPS status details, or null. 1540 * @return status object containing updated GPS status. 1541 */ getGpsStatus(GpsStatus status)1542 public GpsStatus getGpsStatus(GpsStatus status) { 1543 if (status == null) { 1544 status = new GpsStatus(); 1545 } 1546 status.setStatus(mGpsStatus); 1547 return status; 1548 } 1549 1550 /** 1551 * Sends additional commands to a location provider. 1552 * Can be used to support provider specific extensions to the Location Manager API 1553 * 1554 * @param provider name of the location provider. 1555 * @param command name of the command to send to the provider. 1556 * @param extras optional arguments for the command (or null). 1557 * The provider may optionally fill the extras Bundle with results from the command. 1558 * 1559 * @return true if the command succeeds. 1560 */ sendExtraCommand(String provider, String command, Bundle extras)1561 public boolean sendExtraCommand(String provider, String command, Bundle extras) { 1562 try { 1563 return mService.sendExtraCommand(provider, command, extras); 1564 } catch (RemoteException e) { 1565 Log.e(TAG, "RemoteException in sendExtraCommand: ", e); 1566 return false; 1567 } 1568 } 1569 1570 /** 1571 * Used by NetInitiatedActivity to report user response 1572 * for network initiated GPS fix requests. 1573 * 1574 * {@hide} 1575 */ sendNiResponse(int notifId, int userResponse)1576 public boolean sendNiResponse(int notifId, int userResponse) { 1577 try { 1578 return mService.sendNiResponse(notifId, userResponse); 1579 } catch (RemoteException e) { 1580 Log.e(TAG, "RemoteException in sendNiResponse: ", e); 1581 return false; 1582 } 1583 } 1584 1585 } 1586