/*
* Copyright (C) 2013 Niall 'Rivernile' Scott
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors or contributors be held liable for
* any damages arising from the use of this software.
*
* The aforementioned copyright holder(s) hereby grant you a
* non-transferrable right to use this software for any purpose (including
* commercial applications), and to modify it and redistribute it, subject to
* the following conditions:
*
* 1. This notice may not be removed or altered from any file it appears in.
*
* 2. Any modifications made to this software, except those defined in
* clause 3 of this agreement, must be released under this license, and
* the source code of any modifications must be made available on a
* publically accessible (and locateable) website, or sent to the
* original author of this software.
*
* 3. Software modifications that do not alter the functionality of the
* software but are simply adaptations to a specific environment are
* exempt from clause 2.
*/
package uk.org.rivernile.android.utils;
import android.location.Location;
import android.location.LocationManager;
import java.util.List;
/**
* This class contains various methods which help with Location services. Some
* of the code is taken from the Android Developer website. Any bits of code
* which have been taken from elsewhere will be marked in their method Javadoc.
*
* @author Niall Scott
*/
public class LocationUtils {
private static final int TWO_MINUTES = 120000;
/**
* Prevent instantiation of this class.
*/
private LocationUtils() {
// Nothing to do here.
}
/**
* Get the best initial fix on a Location. It will loop through all known
* system location providers and get the location from each provider. They
* will all be compared to return the best Location.
*
* @param locMan An instance of the LocationManager, so that this method can
* obtain the last location for each provider.
* @return An instance of Location which contains the best Location, or null
* if a location could not be determined.
*/
public static Location getBestInitialLocation(
final LocationManager locMan) {
if (locMan == null) {
return null;
}
final List<String> matchingProviders = locMan.getAllProviders();
Location location, bestLocation = null;
for (String provder : matchingProviders) {
location = locMan.getLastKnownLocation(provder);
if (location != null && isBetterLocation(location, bestLocation)) {
bestLocation = location;
}
}
return bestLocation;
}
/**
* Determines whether one Location reading is better than the current
* Location fix.
*
* This was taken from
* http://d.android.com/training/basics/location/currentlocation.html
*
* @param location The new Location fix.
* @param currentBestLocation The currently held Location fix.
* @return true if the new Location is better than the old one, false if
* not.
*/
public static boolean isBetterLocation(final Location location,
final Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location.
return true;
}
// Check whether the new location fix is newer or older.
final long timeDelta = location.getTime()
- currentBestLocation.getTime();
final boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use
// the new location because the user has likely moved.
if (timeDelta > TWO_MINUTES) {
return true;
} else if (timeDelta < -TWO_MINUTES) {
// If the new location is more than two minutes older, it must be
// worse.
return false;
}
// Check whether the new location fix is more or less accurate.
final int accuracyDelta = (int) (location.getAccuracy()
- currentBestLocation.getAccuracy());
final boolean isLessAccurate = accuracyDelta > 0;
final boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider.
final boolean isFromSameProvider = isSameProvider(
location.getProvider(), currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and
// accuracy.
if (accuracyDelta < 0) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate
&& isFromSameProvider) {
return true;
}
return false;
}
/**
* Checks to see if two providers are the same.
*
* @param provider1 The first provider String to compare.
* @param provider2 The second provider String to compare.
* @return true if they are the same, false if not.
*/
public static boolean isSameProvider(final String provider1,
final String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
}