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