Android Open Source - polaris Location Utils






From Project

Back to project page polaris.

License

The source code is released under:

GNU Lesser General Public License

If you think the Android project polaris listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*******************************************************************************
 * Copyleft 2013 Massimiliano Leone - massimiliano.leone@iubris.net .
 * /*from   w  w w.j a v  a  2s .  c o m*/
 * LocationUtils.java is part of 'Polaris'.
 * 
 * 'Polaris' is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 * 
 * 'Polaris' is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with 'Polaris'; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 ******************************************************************************/
package net.iubris.polaris.locator.utils;

import net.iubris.polaris.locator.utils.exceptions.LocationNotSoCarefulException;
import net.iubris.polaris.locator.utils.exceptions.LocationNotSoFarException;
import net.iubris.polaris.locator.utils.exceptions.LocationNotSoNewerException;
import android.annotation.SuppressLint;
import android.location.Location;
import android.os.Build;
import android.util.Log;

/**
 * using tips from: <a href="http://developer.android.com/guide/topics/location/strategies.html">http://developer.android.com/guide/topics/location/strategies.html</a>
 */

public class LocationUtils {
  
  /**
   * Compares locations by distance, within weighted threshold.
   * 
   * <p>
   * <ul>
   *   <li>if distance >  distanceMaximumThreshold => really farer, return true</li>
   *   <li>if threshold/3 < distance < threshold =>  not so farer, throw exception</li>
   *   <li>if 0 < distance < threshold/3 => almost near, return false</li>
   * </ul>
   * 
   * we use "threshold/3" as value for weighted threshold:
   * <pre>
   * <code>
   * | -- false -- |   -- throw exception --   | true <br/>
   * 0            TS/3          ts*2/3              TS
   * </code>
   * </pre>
   * 
   * @param newLocation
   * @param currentLocation
   * @param distanceMaximumThreshold
   * @return true if newLocation is significantly far than currentLocation, false elsewhere
   * @throws LocationNotSoFarException if newLocation is not so far than currentLocation, that is within distanceMaximumThreshold
   */
  public static boolean isLocationFar(Location newLocation, Location currentLocation, float distanceMaximumThreshold) throws LocationNotSoFarException {
    float deltaDistance = newLocation.distanceTo(currentLocation);
Log.d("LocationUtils:62,","newLocation: "+newLocation);
Log.d("LocationUtils:63,","currentLocation: "+currentLocation);
Log.d("LocationUtils:64","deltaDistance = "+deltaDistance);    
    float sensibleThreshold = distanceMaximumThreshold/3;
    if (deltaDistance > distanceMaximumThreshold) return true; // distance >  threshold
    if (deltaDistance < sensibleThreshold) return false; // 0 < distance < threshold/3
    throw new LocationNotSoFarException("newLocation ["+newLocation+"] is not so far from ["+currentLocation+"]: just "+deltaDistance+" m"); // distance > threshold/3 
  }
  
  /**
   *   Compare currentLocation with newLocation by time
   * @param currentLocation
   * @param newLocation
   * @param timeMinimumThreshold - in milliseconds
   * @return true if newLocation is newer than currentLocation, according to timeMinimumThreshold - false otherwise 
   * @throws LocationNotSoNewerException when newLocation is newer than currentLocation, but retrieved within threshold defined by timeMinimumThreshold parameter
   */  
//  @SuppressLint("NewApi")
  public static boolean isLocationNewer(Location newLocation, Location currentLocation, float timeMinimumThreshold ) throws LocationNotSoNewerException {     
/*Log.d("LocationUtils.isLocationOlder","current time: "+System.currentTimeMillis());
Log.d("LocationUtils.isLocationOlder","location time: "+location.getTime());
Log.d("LocationUtils.isLocationOlder","timeMinimumThreshold: "+timeMinimumThreshold);
Log.d("LocationUtils.isLocationOlder","difference: "+ (System.currentTimeMillis() - location.getTime()) );*/
//    old way
//    if(System.currentTimeMillis() - location.getTime() > timeMinimumThreshold) return true;
    
    if (currentLocation == null) {
//      A new location is always better than no location
      return true;
    }
    
    // es. currentLocation = 180s; newLocation = 10s; timeDelta = 170s
    final long timeDelta = getTimeDelta(newLocation, currentLocation);    
    // with timeMinimumThreshold = 60s => currentLocation is older than newLocation
    if (timeDelta > timeMinimumThreshold) { // isSignificantlyNewer
      return true;
    } else if (timeDelta < -timeMinimumThreshold) // isSignificantlyOlder
      return false;
//    -timeMinimumThreshold < timeDelta < timeMinimumThreshold <=> timeDelta > 0 // isNewer
    throw new LocationNotSoNewerException("newLocation is newer than currentLocation, but both are retrieved in last "+timeMinimumThreshold/1000+" seconds");
  }
  
  
  /**
   * Compare currentLocation with newLocation by accuracy (distance error)
   * @param newLocation
   * @param currentLocation
   * @param accuracyDistanceMaximumThreshold - in meters
   * @return true is newLocation has higher accuracy than currentLocation, false otherwise
   * @throws LocationNotSoCarefulException if newLocation is retrieved in same admitted area, according to accuracyDistanceMaximumThreshold parameter
   */
  public static boolean isLocationCareful(Location newLocation, Location currentLocation, float accuracyDistanceMaximumThreshold) throws LocationNotSoCarefulException{
    
//    old way
//    if (actualLocation.distanceTo(oldLocation) > distanceMinimumThreshold) return true;
    
    // lower value from getAccuraty => better accuracy  
    final float accuracyDelta = newLocation.getAccuracy() - currentLocation.getAccuracy();
    
    if (accuracyDelta < 0.0)   // ok, delta < 0, so is careful: isMoreAccurate
      return true;
    if (accuracyDelta > accuracyDistanceMaximumThreshold) { // significantly lower accuracy: isSignificantlyLessAccurate !
      return false;
    }
    // accuracyDelta > 0.0 // newLocation has higher accuracy, but within threshold: isLessAccurate
    // delta is low, and under threshold <=> 0 < accuracyDelta < accuracyDistanceMaximumThreshold
    throw new LocationNotSoCarefulException("newLocation has higher accuracy than currentLocation, but both are retrieved in admitted area, according to declared accuracyDistanceMaximumThreshold="+accuracyDistanceMaximumThreshold +"m");
  }
  
  
  /** Determines whether one Location reading is better than the current Location fix (better = combination of "newer" and "higher accuracy" and etc)
    * @param newLocation  The new Location that you want to evaluate
    * @param currentLocation  The current Location fix, to which you want to compare the new one
    * @param timeMinimumThreshold threshold for evaluating if newLocation is newer (and how) than currentLocation  
    * @param accuracyDistanceMaximumThreshold threshold for evaluating if newLocation has more accuracy (and how) than currentLocation
    * @see <a href="http://developer.android.com/guide/topics/location/strategies.html">tips used for implementation strategy</a>
    */
  public static boolean isLocationBetter(Location newLocation, Location currentLocation, long timeMinimumThreshold, int accuracyDistanceMaximumThreshold) {
    /* tips way
      if (currentLocation == null) {
          // A new location is always better than no location
          return true;
      }

      // Check whether the new location fix is newer or older
      long timeDelta = getTimeDelta(newLocation, currentLocation);
      boolean isSignificantlyNewer = timeDelta > timeMinimumThreshold;
      boolean isSignificantlyOlder = timeDelta < -timeMinimumThreshold;
      boolean isNewer = timeDelta > 0;
      */
      
//      boolean isSignificantlyNewer = false; 
//      boolean isNewer = false;
      
      try {
        
          // return true If it's been more than "timeMinimumThreshold" (2?) minutes since the current location, 
        // so use the new location because the user has likely moved
        // else return false - really "false" means newLocation time is older than currentLocation ones => it must be worse, so return false 
        //
        return isLocationNewer(newLocation, currentLocation, timeMinimumThreshold);
                  
    } catch (LocationNotSoNewerException e) { // we arrive if true nor false are returned, however the catch do nothing and go straitght
//      isNewer = true;
    }
      

      /* old way, by tips
      // improvement ?
//      int accuracyThreshold = (accuracyDistanceMaximumThreshold < 200) ? accuracyDistanceMaximumThreshold : 200;
      int accuracyThreshold = accuracyDistanceMaximumThreshold;
      
      // Check whether the new location fix is more or less accurate
      int accuracyDelta = (int) (newLocation.getAccuracy() - currentLocation.getAccuracy());
      boolean isLessAccurate = accuracyDelta > 0;
      boolean isSignificantlyLessAccurate = accuracyDelta > accuracyThreshold;
      boolean isMoreAccurate = accuracyDelta < 0;
      */
      
      // if we are here, newLocation is newer than currentLocation, but retrieved within threshold, so we check for any accuracy
      boolean isLessAccurate = false;
//      boolean isSignificantlyLessAccurate = false;
//      boolean isMoreAccurate = false;
      
      // Determine location quality using a combination of timeliness and accuracy
      try {
//        isMoreAccurate = 
      if (isLocationCareful(newLocation, currentLocation, accuracyDistanceMaximumThreshold));
//        if (isMoreAccurate) {
            return true;
//        }
        // if we are here, isLessAccurate is false;
//        isSignificantlyLessAccurate = true; // = !isMoreAccurate
    } catch (LocationNotSoCarefulException e) {
      // if we are here, we have higher accuracy, but under threshold that is 0 < accuracyDelta < accuracyThreshold
      // we try check by providers
      
//      boolean isFromSameProvider = 
      if (isSameProvider(newLocation.getProvider(), currentLocation.getProvider()))
      // isSignificantlyLessAccurate is false
//        if (isFromSameProvider) { // really is: (isNewer && !isSignificantlyLessAccurate && isFromSameProvider)
            return true;
//        }
      
      isLessAccurate = true;
    }
      
      // isMoreAccurate (= isLocationCareful=true) is still false (but not returned) AND isLessAccurate is still false (not throwed LocationNotSoCarefulException)
      if (!isLessAccurate) { // really is (isNewer=[catched LocationNotSoNewer from isLocationNewer] && !isLessAccurate) 
        return true;
      }
      
      return false;
  }
  
  /*public static boolean is() {
    return false;  
  }*/
  
//  public static boolean is
  /*
  public static boolean isNewerAndAccurate(boolean isNewer, boolean isLessAccurate) {
    if (isNewer && !isLessAccurate)
          return true;
    return false;
  }
  public static boolean isNewerAndAccurateAndSameProvider(boolean isNewer, boolean isSignificantlyLessAccurate, boolean isFromSameProvider) {
    if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider)
          return true;
    return false;
  }*/

  /** Checks whether two providers are the same */
  private static boolean isSameProvider(String provider1, String provider2) {
      if (provider1 == null) {
        return provider2 == null;
      }
      return provider1.equals(provider2);
  }
  
  @SuppressLint("NewApi")
  private static long getTimeDelta(Location a, Location b) {
    if ( Build.VERSION.SDK_INT >= 17 )
      return Math.abs( a.getElapsedRealtimeNanos() - b.getElapsedRealtimeNanos() );
    return Math.abs( a.getTime() - b.getTime() );
  }
  
  /*public static boolean isBetter(Location newLocation, Location currentLocation, long timeMinimumThreshold, int accuracyDistanceMaximumThreshold) {
    return false;
  }*/
}




Java Source Code List

net.iubris.polaris.locator.Locator.java
net.iubris.polaris.locator.provider.LocationProvider.java
net.iubris.polaris.locator.updater.LocationUpdater.java
net.iubris.polaris.locator.utils.LocationUtils.java
net.iubris.polaris.locator.utils.exceptions.LocationException.java
net.iubris.polaris.locator.utils.exceptions.LocationNotSoCarefulException.java
net.iubris.polaris.locator.utils.exceptions.LocationNotSoFarException.java
net.iubris.polaris.locator.utils.exceptions.LocationNotSoNewerException.java
net.iubris.polaris.observatory.action.LocationNotificationAction.java
net.iubris.polaris.observatory.observable.LocationObservable.java
net.iubris.polaris.observatory.observable.LocatorObservableSyncDelegate.java
net.iubris.polaris.observatory.observer.LocationObserver.java
net.iubris.polaris._roboguice.module.PolarisModule.java