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.os.Bundle; 20import android.os.Parcel; 21import android.os.Parcelable; 22import android.os.SystemClock; 23import android.util.Printer; 24import android.util.TimeUtils; 25 26import java.text.DecimalFormat; 27import java.util.StringTokenizer; 28 29/** 30 * A data class representing a geographic location. 31 * 32 * <p>A location can consist of a latitude, longitude, timestamp, 33 * and other information such as bearing, altitude and velocity. 34 * 35 * <p>All locations generated by the {@link LocationManager} are 36 * guaranteed to have a valid latitude, longitude, and timestamp 37 * (both UTC time and elapsed real-time since boot), all other 38 * parameters are optional. 39 */ 40public class Location implements Parcelable { 41 /** 42 * Constant used to specify formatting of a latitude or longitude 43 * in the form "[+-]DDD.DDDDD where D indicates degrees. 44 */ 45 public static final int FORMAT_DEGREES = 0; 46 47 /** 48 * Constant used to specify formatting of a latitude or longitude 49 * in the form "[+-]DDD:MM.MMMMM" where D indicates degrees and 50 * M indicates minutes of arc (1 minute = 1/60th of a degree). 51 */ 52 public static final int FORMAT_MINUTES = 1; 53 54 /** 55 * Constant used to specify formatting of a latitude or longitude 56 * in the form "DDD:MM:SS.SSSSS" where D indicates degrees, M 57 * indicates minutes of arc, and S indicates seconds of arc (1 58 * minute = 1/60th of a degree, 1 second = 1/3600th of a degree). 59 */ 60 public static final int FORMAT_SECONDS = 2; 61 62 /** 63 * Bundle key for a version of the location that has been fed through 64 * LocationFudger. Allows location providers to flag locations as being 65 * safe for use with ACCESS_COARSE_LOCATION permission. 66 * 67 * @hide 68 */ 69 public static final String EXTRA_COARSE_LOCATION = "coarseLocation"; 70 71 /** 72 * Bundle key for a version of the location containing no GPS data. 73 * Allows location providers to flag locations as being safe to 74 * feed to LocationFudger. 75 * 76 * @hide 77 */ 78 public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation"; 79 80 private String mProvider; 81 private long mTime = 0; 82 private long mElapsedRealtimeNanos = 0; 83 private double mLatitude = 0.0; 84 private double mLongitude = 0.0; 85 private boolean mHasAltitude = false; 86 private double mAltitude = 0.0f; 87 private boolean mHasSpeed = false; 88 private float mSpeed = 0.0f; 89 private boolean mHasBearing = false; 90 private float mBearing = 0.0f; 91 private boolean mHasAccuracy = false; 92 private float mAccuracy = 0.0f; 93 private Bundle mExtras = null; 94 95 // Cache the inputs and outputs of computeDistanceAndBearing 96 // so calls to distanceTo() and bearingTo() can share work 97 private double mLat1 = 0.0; 98 private double mLon1 = 0.0; 99 private double mLat2 = 0.0; 100 private double mLon2 = 0.0; 101 private float mDistance = 0.0f; 102 private float mInitialBearing = 0.0f; 103 // Scratchpad 104 private final float[] mResults = new float[2]; 105 106 /** 107 * Construct a new Location with a named provider. 108 * 109 * <p>By default time, latitude and longitude are 0, and the location 110 * has no bearing, altitude, speed, accuracy or extras. 111 * 112 * @param provider the name of the provider that generated this location 113 */ 114 public Location(String provider) { 115 mProvider = provider; 116 } 117 118 /** 119 * Construct a new Location object that is copied from an existing one. 120 */ 121 public Location(Location l) { 122 set(l); 123 } 124 125 /** 126 * Sets the contents of the location to the values from the given location. 127 */ 128 public void set(Location l) { 129 mProvider = l.mProvider; 130 mTime = l.mTime; 131 mElapsedRealtimeNanos = l.mElapsedRealtimeNanos; 132 mLatitude = l.mLatitude; 133 mLongitude = l.mLongitude; 134 mHasAltitude = l.mHasAltitude; 135 mAltitude = l.mAltitude; 136 mHasSpeed = l.mHasSpeed; 137 mSpeed = l.mSpeed; 138 mHasBearing = l.mHasBearing; 139 mBearing = l.mBearing; 140 mHasAccuracy = l.mHasAccuracy; 141 mAccuracy = l.mAccuracy; 142 mExtras = (l.mExtras == null) ? null : new Bundle(l.mExtras); 143 } 144 145 /** 146 * Clears the contents of the location. 147 */ 148 public void reset() { 149 mProvider = null; 150 mTime = 0; 151 mElapsedRealtimeNanos = 0; 152 mLatitude = 0; 153 mLongitude = 0; 154 mHasAltitude = false; 155 mAltitude = 0; 156 mHasSpeed = false; 157 mSpeed = 0; 158 mHasBearing = false; 159 mBearing = 0; 160 mHasAccuracy = false; 161 mAccuracy = 0; 162 mExtras = null; 163 } 164 165 /** 166 * Converts a coordinate to a String representation. The outputType 167 * may be one of FORMAT_DEGREES, FORMAT_MINUTES, or FORMAT_SECONDS. 168 * The coordinate must be a valid double between -180.0 and 180.0. 169 * 170 * @throws IllegalArgumentException if coordinate is less than 171 * -180.0, greater than 180.0, or is not a number. 172 * @throws IllegalArgumentException if outputType is not one of 173 * FORMAT_DEGREES, FORMAT_MINUTES, or FORMAT_SECONDS. 174 */ 175 public static String convert(double coordinate, int outputType) { 176 if (coordinate < -180.0 || coordinate > 180.0 || 177 Double.isNaN(coordinate)) { 178 throw new IllegalArgumentException("coordinate=" + coordinate); 179 } 180 if ((outputType != FORMAT_DEGREES) && 181 (outputType != FORMAT_MINUTES) && 182 (outputType != FORMAT_SECONDS)) { 183 throw new IllegalArgumentException("outputType=" + outputType); 184 } 185 186 StringBuilder sb = new StringBuilder(); 187 188 // Handle negative values 189 if (coordinate < 0) { 190 sb.append('-'); 191 coordinate = -coordinate; 192 } 193 194 DecimalFormat df = new DecimalFormat("###.#####"); 195 if (outputType == FORMAT_MINUTES || outputType == FORMAT_SECONDS) { 196 int degrees = (int) Math.floor(coordinate); 197 sb.append(degrees); 198 sb.append(':'); 199 coordinate -= degrees; 200 coordinate *= 60.0; 201 if (outputType == FORMAT_SECONDS) { 202 int minutes = (int) Math.floor(coordinate); 203 sb.append(minutes); 204 sb.append(':'); 205 coordinate -= minutes; 206 coordinate *= 60.0; 207 } 208 } 209 sb.append(df.format(coordinate)); 210 return sb.toString(); 211 } 212 213 /** 214 * Converts a String in one of the formats described by 215 * FORMAT_DEGREES, FORMAT_MINUTES, or FORMAT_SECONDS into a 216 * double. 217 * 218 * @throws NullPointerException if coordinate is null 219 * @throws IllegalArgumentException if the coordinate is not 220 * in one of the valid formats. 221 */ 222 public static double convert(String coordinate) { 223 // IllegalArgumentException if bad syntax 224 if (coordinate == null) { 225 throw new NullPointerException("coordinate"); 226 } 227 228 boolean negative = false; 229 if (coordinate.charAt(0) == '-') { 230 coordinate = coordinate.substring(1); 231 negative = true; 232 } 233 234 StringTokenizer st = new StringTokenizer(coordinate, ":"); 235 int tokens = st.countTokens(); 236 if (tokens < 1) { 237 throw new IllegalArgumentException("coordinate=" + coordinate); 238 } 239 try { 240 String degrees = st.nextToken(); 241 double val; 242 if (tokens == 1) { 243 val = Double.parseDouble(degrees); 244 return negative ? -val : val; 245 } 246 247 String minutes = st.nextToken(); 248 int deg = Integer.parseInt(degrees); 249 double min; 250 double sec = 0.0; 251 252 if (st.hasMoreTokens()) { 253 min = Integer.parseInt(minutes); 254 String seconds = st.nextToken(); 255 sec = Double.parseDouble(seconds); 256 } else { 257 min = Double.parseDouble(minutes); 258 } 259 260 boolean isNegative180 = negative && (deg == 180) && 261 (min == 0) && (sec == 0); 262 263 // deg must be in [0, 179] except for the case of -180 degrees 264 if ((deg < 0.0) || (deg > 179 && !isNegative180)) { 265 throw new IllegalArgumentException("coordinate=" + coordinate); 266 } 267 if (min < 0 || min > 59) { 268 throw new IllegalArgumentException("coordinate=" + 269 coordinate); 270 } 271 if (sec < 0 || sec > 59) { 272 throw new IllegalArgumentException("coordinate=" + 273 coordinate); 274 } 275 276 val = deg*3600.0 + min*60.0 + sec; 277 val /= 3600.0; 278 return negative ? -val : val; 279 } catch (NumberFormatException nfe) { 280 throw new IllegalArgumentException("coordinate=" + coordinate); 281 } 282 } 283 284 private static void computeDistanceAndBearing(double lat1, double lon1, 285 double lat2, double lon2, float[] results) { 286 // Based on http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf 287 // using the "Inverse Formula" (section 4) 288 289 int MAXITERS = 20; 290 // Convert lat/long to radians 291 lat1 *= Math.PI / 180.0; 292 lat2 *= Math.PI / 180.0; 293 lon1 *= Math.PI / 180.0; 294 lon2 *= Math.PI / 180.0; 295 296 double a = 6378137.0; // WGS84 major axis 297 double b = 6356752.3142; // WGS84 semi-major axis 298 double f = (a - b) / a; 299 double aSqMinusBSqOverBSq = (a * a - b * b) / (b * b); 300 301 double L = lon2 - lon1; 302 double A = 0.0; 303 double U1 = Math.atan((1.0 - f) * Math.tan(lat1)); 304 double U2 = Math.atan((1.0 - f) * Math.tan(lat2)); 305 306 double cosU1 = Math.cos(U1); 307 double cosU2 = Math.cos(U2); 308 double sinU1 = Math.sin(U1); 309 double sinU2 = Math.sin(U2); 310 double cosU1cosU2 = cosU1 * cosU2; 311 double sinU1sinU2 = sinU1 * sinU2; 312 313 double sigma = 0.0; 314 double deltaSigma = 0.0; 315 double cosSqAlpha = 0.0; 316 double cos2SM = 0.0; 317 double cosSigma = 0.0; 318 double sinSigma = 0.0; 319 double cosLambda = 0.0; 320 double sinLambda = 0.0; 321 322 double lambda = L; // initial guess 323 for (int iter = 0; iter < MAXITERS; iter++) { 324 double lambdaOrig = lambda; 325 cosLambda = Math.cos(lambda); 326 sinLambda = Math.sin(lambda); 327 double t1 = cosU2 * sinLambda; 328 double t2 = cosU1 * sinU2 - sinU1 * cosU2 * cosLambda; 329 double sinSqSigma = t1 * t1 + t2 * t2; // (14) 330 sinSigma = Math.sqrt(sinSqSigma); 331 cosSigma = sinU1sinU2 + cosU1cosU2 * cosLambda; // (15) 332 sigma = Math.atan2(sinSigma, cosSigma); // (16) 333 double sinAlpha = (sinSigma == 0) ? 0.0 : 334 cosU1cosU2 * sinLambda / sinSigma; // (17) 335 cosSqAlpha = 1.0 - sinAlpha * sinAlpha; 336 cos2SM = (cosSqAlpha == 0) ? 0.0 : 337 cosSigma - 2.0 * sinU1sinU2 / cosSqAlpha; // (18) 338 339 double uSquared = cosSqAlpha * aSqMinusBSqOverBSq; // defn 340 A = 1 + (uSquared / 16384.0) * // (3) 341 (4096.0 + uSquared * 342 (-768 + uSquared * (320.0 - 175.0 * uSquared))); 343 double B = (uSquared / 1024.0) * // (4) 344 (256.0 + uSquared * 345 (-128.0 + uSquared * (74.0 - 47.0 * uSquared))); 346 double C = (f / 16.0) * 347 cosSqAlpha * 348 (4.0 + f * (4.0 - 3.0 * cosSqAlpha)); // (10) 349 double cos2SMSq = cos2SM * cos2SM; 350 deltaSigma = B * sinSigma * // (6) 351 (cos2SM + (B / 4.0) * 352 (cosSigma * (-1.0 + 2.0 * cos2SMSq) - 353 (B / 6.0) * cos2SM * 354 (-3.0 + 4.0 * sinSigma * sinSigma) * 355 (-3.0 + 4.0 * cos2SMSq))); 356 357 lambda = L + 358 (1.0 - C) * f * sinAlpha * 359 (sigma + C * sinSigma * 360 (cos2SM + C * cosSigma * 361 (-1.0 + 2.0 * cos2SM * cos2SM))); // (11) 362 363 double delta = (lambda - lambdaOrig) / lambda; 364 if (Math.abs(delta) < 1.0e-12) { 365 break; 366 } 367 } 368 369 float distance = (float) (b * A * (sigma - deltaSigma)); 370 results[0] = distance; 371 if (results.length > 1) { 372 float initialBearing = (float) Math.atan2(cosU2 * sinLambda, 373 cosU1 * sinU2 - sinU1 * cosU2 * cosLambda); 374 initialBearing *= 180.0 / Math.PI; 375 results[1] = initialBearing; 376 if (results.length > 2) { 377 float finalBearing = (float) Math.atan2(cosU1 * sinLambda, 378 -sinU1 * cosU2 + cosU1 * sinU2 * cosLambda); 379 finalBearing *= 180.0 / Math.PI; 380 results[2] = finalBearing; 381 } 382 } 383 } 384 385 /** 386 * Computes the approximate distance in meters between two 387 * locations, and optionally the initial and final bearings of the 388 * shortest path between them. Distance and bearing are defined using the 389 * WGS84 ellipsoid. 390 * 391 * <p> The computed distance is stored in results[0]. If results has length 392 * 2 or greater, the initial bearing is stored in results[1]. If results has 393 * length 3 or greater, the final bearing is stored in results[2]. 394 * 395 * @param startLatitude the starting latitude 396 * @param startLongitude the starting longitude 397 * @param endLatitude the ending latitude 398 * @param endLongitude the ending longitude 399 * @param results an array of floats to hold the results 400 * 401 * @throws IllegalArgumentException if results is null or has length < 1 402 */ 403 public static void distanceBetween(double startLatitude, double startLongitude, 404 double endLatitude, double endLongitude, float[] results) { 405 if (results == null || results.length < 1) { 406 throw new IllegalArgumentException("results is null or has length < 1"); 407 } 408 computeDistanceAndBearing(startLatitude, startLongitude, 409 endLatitude, endLongitude, results); 410 } 411 412 /** 413 * Returns the approximate distance in meters between this 414 * location and the given location. Distance is defined using 415 * the WGS84 ellipsoid. 416 * 417 * @param dest the destination location 418 * @return the approximate distance in meters 419 */ 420 public float distanceTo(Location dest) { 421 // See if we already have the result 422 synchronized (mResults) { 423 if (mLatitude != mLat1 || mLongitude != mLon1 || 424 dest.mLatitude != mLat2 || dest.mLongitude != mLon2) { 425 computeDistanceAndBearing(mLatitude, mLongitude, 426 dest.mLatitude, dest.mLongitude, mResults); 427 mLat1 = mLatitude; 428 mLon1 = mLongitude; 429 mLat2 = dest.mLatitude; 430 mLon2 = dest.mLongitude; 431 mDistance = mResults[0]; 432 mInitialBearing = mResults[1]; 433 } 434 return mDistance; 435 } 436 } 437 438 /** 439 * Returns the approximate initial bearing in degrees East of true 440 * North when traveling along the shortest path between this 441 * location and the given location. The shortest path is defined 442 * using the WGS84 ellipsoid. Locations that are (nearly) 443 * antipodal may produce meaningless results. 444 * 445 * @param dest the destination location 446 * @return the initial bearing in degrees 447 */ 448 public float bearingTo(Location dest) { 449 synchronized (mResults) { 450 // See if we already have the result 451 if (mLatitude != mLat1 || mLongitude != mLon1 || 452 dest.mLatitude != mLat2 || dest.mLongitude != mLon2) { 453 computeDistanceAndBearing(mLatitude, mLongitude, 454 dest.mLatitude, dest.mLongitude, mResults); 455 mLat1 = mLatitude; 456 mLon1 = mLongitude; 457 mLat2 = dest.mLatitude; 458 mLon2 = dest.mLongitude; 459 mDistance = mResults[0]; 460 mInitialBearing = mResults[1]; 461 } 462 return mInitialBearing; 463 } 464 } 465 466 /** 467 * Returns the name of the provider that generated this fix. 468 * 469 * @return the provider, or null if it has not been set 470 */ 471 public String getProvider() { 472 return mProvider; 473 } 474 475 /** 476 * Sets the name of the provider that generated this fix. 477 */ 478 public void setProvider(String provider) { 479 mProvider = provider; 480 } 481 482 /** 483 * Return the UTC time of this fix, in milliseconds since January 1, 1970. 484 * 485 * <p>Note that the UTC time on a device is not monotonic: it 486 * can jump forwards or backwards unpredictably. So always use 487 * {@link #getElapsedRealtimeNanos} when calculating time deltas. 488 * 489 * <p>On the other hand, {@link #getTime} is useful for presenting 490 * a human readable time to the user, or for carefully comparing 491 * location fixes across reboot or across devices. 492 * 493 * <p>All locations generated by the {@link LocationManager} 494 * are guaranteed to have a valid UTC time, however remember that 495 * the system time may have changed since the location was generated. 496 * 497 * @return time of fix, in milliseconds since January 1, 1970. 498 */ 499 public long getTime() { 500 return mTime; 501 } 502 503 /** 504 * Set the UTC time of this fix, in milliseconds since January 1, 505 * 1970. 506 * 507 * @param time UTC time of this fix, in milliseconds since January 1, 1970 508 */ 509 public void setTime(long time) { 510 mTime = time; 511 } 512 513 /** 514 * Return the time of this fix, in elapsed real-time since system boot. 515 * 516 * <p>This value can be reliably compared to 517 * {@link android.os.SystemClock#elapsedRealtimeNanos}, 518 * to calculate the age of a fix and to compare Location fixes. This 519 * is reliable because elapsed real-time is guaranteed monotonic for 520 * each system boot and continues to increment even when the system 521 * is in deep sleep (unlike {@link #getTime}. 522 * 523 * <p>All locations generated by the {@link LocationManager} 524 * are guaranteed to have a valid elapsed real-time. 525 * 526 * @return elapsed real-time of fix, in nanoseconds since system boot. 527 */ 528 public long getElapsedRealtimeNanos() { 529 return mElapsedRealtimeNanos; 530 } 531 532 /** 533 * Set the time of this fix, in elapsed real-time since system boot. 534 * 535 * @param time elapsed real-time of fix, in nanoseconds since system boot. 536 */ 537 public void setElapsedRealtimeNanos(long time) { 538 mElapsedRealtimeNanos = time; 539 } 540 541 /** 542 * Get the latitude, in degrees. 543 * 544 * <p>All locations generated by the {@link LocationManager} 545 * will have a valid latitude. 546 */ 547 public double getLatitude() { 548 return mLatitude; 549 } 550 551 /** 552 * Set the latitude, in degrees. 553 */ 554 public void setLatitude(double latitude) { 555 mLatitude = latitude; 556 } 557 558 /** 559 * Get the longitude, in degrees. 560 * 561 * <p>All locations generated by the {@link LocationManager} 562 * will have a valid longitude. 563 */ 564 public double getLongitude() { 565 return mLongitude; 566 } 567 568 /** 569 * Set the longitude, in degrees. 570 */ 571 public void setLongitude(double longitude) { 572 mLongitude = longitude; 573 } 574 575 /** 576 * True if this location has an altitude. 577 */ 578 public boolean hasAltitude() { 579 return mHasAltitude; 580 } 581 582 /** 583 * Get the altitude if available, in meters above sea level. 584 * 585 * <p>If this location does not have an altitude then 0.0 is returned. 586 */ 587 public double getAltitude() { 588 return mAltitude; 589 } 590 591 /** 592 * Set the altitude, in meters above sea level. 593 * 594 * <p>Following this call {@link #hasAltitude} will return true. 595 */ 596 public void setAltitude(double altitude) { 597 mAltitude = altitude; 598 mHasAltitude = true; 599 } 600 601 /** 602 * Remove the altitude from this location. 603 * 604 * <p>Following this call {@link #hasAltitude} will return false, 605 * and {@link #getAltitude} will return 0.0. 606 */ 607 public void removeAltitude() { 608 mAltitude = 0.0f; 609 mHasAltitude = false; 610 } 611 612 /** 613 * True if this location has a speed. 614 */ 615 public boolean hasSpeed() { 616 return mHasSpeed; 617 } 618 619 /** 620 * Get the speed if it is available, in meters/second over ground. 621 * 622 * <p>If this location does not have a speed then 0.0 is returned. 623 */ 624 public float getSpeed() { 625 return mSpeed; 626 } 627 628 /** 629 * Set the speed, in meters/second over ground. 630 * 631 * <p>Following this call {@link #hasSpeed} will return true. 632 */ 633 public void setSpeed(float speed) { 634 mSpeed = speed; 635 mHasSpeed = true; 636 } 637 638 /** 639 * Remove the speed from this location. 640 * 641 * <p>Following this call {@link #hasSpeed} will return false, 642 * and {@link #getSpeed} will return 0.0. 643 */ 644 public void removeSpeed() { 645 mSpeed = 0.0f; 646 mHasSpeed = false; 647 } 648 649 /** 650 * True if this location has a bearing. 651 */ 652 public boolean hasBearing() { 653 return mHasBearing; 654 } 655 656 /** 657 * Get the bearing, in degrees. 658 * 659 * <p>Bearing is the horizontal direction of travel of this device, 660 * and is not related to the device orientation. It is guaranteed to 661 * be in the range (0.0, 360.0] if the device has a bearing. 662 * 663 * <p>If this location does not have a bearing then 0.0 is returned. 664 */ 665 public float getBearing() { 666 return mBearing; 667 } 668 669 /** 670 * Set the bearing, in degrees. 671 * 672 * <p>Bearing is the horizontal direction of travel of this device, 673 * and is not related to the device orientation. 674 * 675 * <p>The input will be wrapped into the range (0.0, 360.0]. 676 */ 677 public void setBearing(float bearing) { 678 while (bearing < 0.0f) { 679 bearing += 360.0f; 680 } 681 while (bearing >= 360.0f) { 682 bearing -= 360.0f; 683 } 684 mBearing = bearing; 685 mHasBearing = true; 686 } 687 688 /** 689 * Remove the bearing from this location. 690 * 691 * <p>Following this call {@link #hasBearing} will return false, 692 * and {@link #getBearing} will return 0.0. 693 */ 694 public void removeBearing() { 695 mBearing = 0.0f; 696 mHasBearing = false; 697 } 698 699 /** 700 * True if this location has an accuracy. 701 * 702 * <p>All locations generated by the {@link LocationManager} have an 703 * accuracy. 704 */ 705 public boolean hasAccuracy() { 706 return mHasAccuracy; 707 } 708 709 /** 710 * Get the estimated accuracy of this location, in meters. 711 * 712 * <p>We define accuracy as the radius of 68% confidence. In other 713 * words, if you draw a circle centered at this location's 714 * latitude and longitude, and with a radius equal to the accuracy, 715 * then there is a 68% probability that the true location is inside 716 * the circle. 717 * 718 * <p>In statistical terms, it is assumed that location errors 719 * are random with a normal distribution, so the 68% confidence circle 720 * represents one standard deviation. Note that in practice, location 721 * errors do not always follow such a simple distribution. 722 * 723 * <p>This accuracy estimation is only concerned with horizontal 724 * accuracy, and does not indicate the accuracy of bearing, 725 * velocity or altitude if those are included in this Location. 726 * 727 * <p>If this location does not have an accuracy, then 0.0 is returned. 728 * All locations generated by the {@link LocationManager} include 729 * an accuracy. 730 */ 731 public float getAccuracy() { 732 return mAccuracy; 733 } 734 735 /** 736 * Set the estimated accuracy of this location, meters. 737 * 738 * <p>See {@link #getAccuracy} for the definition of accuracy. 739 * 740 * <p>Following this call {@link #hasAccuracy} will return true. 741 */ 742 public void setAccuracy(float accuracy) { 743 mAccuracy = accuracy; 744 mHasAccuracy = true; 745 } 746 747 /** 748 * Remove the accuracy from this location. 749 * 750 * <p>Following this call {@link #hasAccuracy} will return false, and 751 * {@link #getAccuracy} will return 0.0. 752 */ 753 public void removeAccuracy() { 754 mAccuracy = 0.0f; 755 mHasAccuracy = false; 756 } 757 758 /** 759 * Return true if this Location object is complete. 760 * 761 * <p>A location object is currently considered complete if it has 762 * a valid provider, accuracy, wall-clock time and elapsed real-time. 763 * 764 * <p>All locations supplied by the {@link LocationManager} to 765 * applications must be complete. 766 * 767 * @see #makeComplete 768 * @hide 769 */ 770 public boolean isComplete() { 771 if (mProvider == null) return false; 772 if (!mHasAccuracy) return false; 773 if (mTime == 0) return false; 774 if (mElapsedRealtimeNanos == 0) return false; 775 return true; 776 } 777 778 /** 779 * Helper to fill incomplete fields. 780 * 781 * <p>Used to assist in backwards compatibility with 782 * Location objects received from applications. 783 * 784 * @see #isComplete 785 * @hide 786 */ 787 public void makeComplete() { 788 if (mProvider == null) mProvider = "?"; 789 if (!mHasAccuracy) { 790 mHasAccuracy = true; 791 mAccuracy = 100.0f; 792 } 793 if (mTime == 0) mTime = System.currentTimeMillis(); 794 if (mElapsedRealtimeNanos == 0) mElapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos(); 795 } 796 797 /** 798 * Returns additional provider-specific information about the 799 * location fix as a Bundle. The keys and values are determined 800 * by the provider. If no additional information is available, 801 * null is returned. 802 * 803 * <p> A number of common key/value pairs are listed 804 * below. Providers that use any of the keys on this list must 805 * provide the corresponding value as described below. 806 * 807 * <ul> 808 * <li> satellites - the number of satellites used to derive the fix 809 * </ul> 810 */ 811 public Bundle getExtras() { 812 return mExtras; 813 } 814 815 /** 816 * Sets the extra information associated with this fix to the 817 * given Bundle. 818 */ 819 public void setExtras(Bundle extras) { 820 mExtras = (extras == null) ? null : new Bundle(extras); 821 } 822 823 @Override 824 public String toString() { 825 StringBuilder s = new StringBuilder(); 826 s.append("Location["); 827 s.append(mProvider); 828 s.append(String.format(" %.6f,%.6f", mLatitude, mLongitude)); 829 if (mHasAccuracy) s.append(String.format(" acc=%.0f", mAccuracy)); 830 else s.append(" acc=???"); 831 if (mTime == 0) { 832 s.append(" t=?!?"); 833 } 834 if (mElapsedRealtimeNanos == 0) { 835 s.append(" et=?!?"); 836 } else { 837 s.append(" et="); 838 TimeUtils.formatDuration(mElapsedRealtimeNanos / 1000000L, s); 839 } 840 if (mHasAltitude) s.append(" alt=").append(mAltitude); 841 if (mHasSpeed) s.append(" vel=").append(mSpeed); 842 if (mHasBearing) s.append(" bear=").append(mBearing); 843 844 if (mExtras != null) { 845 s.append(" {").append(mExtras).append('}'); 846 } 847 s.append(']'); 848 return s.toString(); 849 } 850 851 public void dump(Printer pw, String prefix) { 852 pw.println(prefix + toString()); 853 } 854 855 public static final Parcelable.Creator<Location> CREATOR = 856 new Parcelable.Creator<Location>() { 857 @Override 858 public Location createFromParcel(Parcel in) { 859 String provider = in.readString(); 860 Location l = new Location(provider); 861 l.mTime = in.readLong(); 862 l.mElapsedRealtimeNanos = in.readLong(); 863 l.mLatitude = in.readDouble(); 864 l.mLongitude = in.readDouble(); 865 l.mHasAltitude = in.readInt() != 0; 866 l.mAltitude = in.readDouble(); 867 l.mHasSpeed = in.readInt() != 0; 868 l.mSpeed = in.readFloat(); 869 l.mHasBearing = in.readInt() != 0; 870 l.mBearing = in.readFloat(); 871 l.mHasAccuracy = in.readInt() != 0; 872 l.mAccuracy = in.readFloat(); 873 l.mExtras = in.readBundle(); 874 return l; 875 } 876 877 @Override 878 public Location[] newArray(int size) { 879 return new Location[size]; 880 } 881 }; 882 883 @Override 884 public int describeContents() { 885 return 0; 886 } 887 888 @Override 889 public void writeToParcel(Parcel parcel, int flags) { 890 parcel.writeString(mProvider); 891 parcel.writeLong(mTime); 892 parcel.writeLong(mElapsedRealtimeNanos); 893 parcel.writeDouble(mLatitude); 894 parcel.writeDouble(mLongitude); 895 parcel.writeInt(mHasAltitude ? 1 : 0); 896 parcel.writeDouble(mAltitude); 897 parcel.writeInt(mHasSpeed ? 1 : 0); 898 parcel.writeFloat(mSpeed); 899 parcel.writeInt(mHasBearing ? 1 : 0); 900 parcel.writeFloat(mBearing); 901 parcel.writeInt(mHasAccuracy ? 1 : 0); 902 parcel.writeFloat(mAccuracy); 903 parcel.writeBundle(mExtras); 904 } 905 906 /** 907 * Returns one of the optional extra {@link Location}s that can be attached 908 * to this Location. 909 * 910 * @param key the key associated with the desired extra Location 911 * @return the extra Location, or null if unavailable 912 * @hide 913 */ 914 public Location getExtraLocation(String key) { 915 if (mExtras != null) { 916 Parcelable value = mExtras.getParcelable(key); 917 if (value instanceof Location) { 918 return (Location) value; 919 } 920 } 921 return null; 922 } 923 924 /** 925 * Attaches an extra {@link Location} to this Location. 926 * 927 * @param key the key associated with the Location extra 928 * @param location the Location to attach 929 * @hide 930 */ 931 public void setExtraLocation(String key, Location value) { 932 if (mExtras == null) { 933 mExtras = new Bundle(); 934 } 935 mExtras.putParcelable(key, value); 936 } 937} 938