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