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