LocationManager.java revision f1be6861daea57ba0a1595739a899d05229d6d15
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 17package android.location; 18 19import android.app.PendingIntent; 20import android.content.Intent; 21import android.os.Bundle; 22import android.os.Looper; 23import android.os.RemoteException; 24import android.os.Handler; 25import android.os.Message; 26import android.util.Log; 27 28import com.android.internal.location.DummyLocationProvider; 29 30import java.util.ArrayList; 31import java.util.HashMap; 32import 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 */ 53public 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 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 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 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 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 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 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 */ 263 public LocationManager(ILocationManager service) { 264 mService = service; 265 } 266 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 1346 Nmea(long timestamp, String nmea) { 1347 mTimestamp = timestamp; 1348 mNmea = nmea; 1349 } 1350 } 1351 private ArrayList<Nmea> mNmeaBuffer; 1352 1353 GpsStatusListenerTransport(GpsStatus.Listener listener) { 1354 mListener = listener; 1355 mNmeaListener = null; 1356 } 1357 1358 GpsStatusListenerTransport(GpsStatus.NmeaListener listener) { 1359 mNmeaListener = listener; 1360 mListener = null; 1361 mNmeaBuffer = new ArrayList<Nmea>(); 1362 } 1363 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 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 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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