/* * Copyright 2014 Artem Chikin * Copyright 2014 Artem Herasymchuk * Copyright 2014 Tom Krywitsky * Copyright 2014 Henry Pabst * Copyright 2014 Bradley Simons * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ca.ualberta.cmput301w14t08.geochan.helpers; import android.app.Activity; import android.content.Context; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; /** * Location Listener Service handles location updates from the Android framework * Used to update geoLocation objects and return the current location when asked * * @author Brad Simons */ public class LocationListenerService { private static Location location; private LocationListener locationListener; private LocationManager locationManager; // taken from Android Location Strategy private static final int TWO_MINUTES = 1000 * 60 * 2; /** * Constructs a new service object. Creates a locationListener object within * and implements its interface. * * @param activity The activity the LocationListenerService the app is running in. */ public LocationListenerService(Activity activity) { locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE); // Creates a LocationListener object and implements its interface. // If onLocationChanged is called, send the new location to // isBetterLocation to check before setting. locationListener = new LocationListener() { public void onLocationChanged(Location newLocation) { if (isBetterLocation(newLocation, location)) { location = newLocation; } } public void onStatusChanged(String provider, int status, Bundle extras) { } public void onProviderEnabled(String provider) { } public void onProviderDisabled(String provider) { } }; } /** * LocationManager tells the locationListener to start listening for * location changes */ public void startListening() { for (String provider : locationManager.getAllProviders()) { locationManager.requestLocationUpdates(provider, 0, 0, locationListener); } } /** * LocationManager tells the locationListener to stop listening for location * changes */ public void stopListening() { locationManager.removeUpdates(locationListener); } /** * Gets the current location. Checks if the latest location is better than * the location currently assigned * * @return location The user's current best location. */ public Location getCurrentLocation() { Location tempLocation = getLastKnownLocation(); if (isBetterLocation(tempLocation, location)) { location = tempLocation; } return location; } /** * asks the location manager for the last known location on the GPS Provider * * @return location The user's last known location */ public Location getLastKnownLocation() { Location loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); if (loc == null) { loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); } return loc; } /** * Checks to see if a new location is better than the currentBestLocation. * This code is from the Android Location Strategies guide, found here: * http://developer.android.com/guide/topics/location/strategies.html * * @param location The new location to be compared. * @param currentBestLocation The current best known position. * @return boolean Whether or not the new location is better than the current best location. */ public boolean isBetterLocation(Location location, 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 long timeDelta = location.getTime() - currentBestLocation.getTime(); boolean isSignificantlyNewer = timeDelta > TWO_MINUTES; boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES; 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 (isSignificantlyNewer) { return true; // If the new location is more than two minutes older, it must be // worse } else if (isSignificantlyOlder) { return false; } // Check whether the new location fix is more or less accurate int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy()); boolean isLessAccurate = accuracyDelta > 0; boolean isMoreAccurate = accuracyDelta < 0; boolean isSignificantlyLessAccurate = accuracyDelta > 200; // Check if the old and new location are from the same provider boolean isFromSameProvider = isSameProvider(location.getProvider(), currentBestLocation.getProvider()); // Determine location quality using a combination of timeliness and // accuracy if (isMoreAccurate) { 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. Used by isBetterLocation * method This code is from the Android Location Strategies Guide found * here: http://developer.android.com/guide/topics/location/strategies.html * * @param provider1 The first provider. * @param provider2 The second provider. * @return boolean Whether or not the providers are the same. */ public boolean isSameProvider(String provider1, String provider2) { if (provider1 == null) { return provider2 == null; } return provider1.equals(provider2); } }