app/src/main/java/ch/epfl/sweng/zuluzulu/structure/GPS.java
package ch.epfl.sweng.zuluzulu.structure;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.widget.Toast;
import static android.content.Context.LOCATION_SERVICE;
/**
* Static class that represents the GPS
*/
public final class GPS {
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 1;
private static final long MIN_DISTANCE_TO_REQUEST_LOCATION = 5; // In meters
private static final long MIN_TIME_FOR_UPDATES = 3000; // 3 sec
private static final int TWO_MINUTES = 1000 * 60 * 2; // 2 min
private static Location location;
private static final LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location newLocation) {
if (newLocation != null && isBetterLocation(newLocation, location)) {
location = newLocation;
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
};
private static LocationManager locationManager;
private static boolean isActivated = false;
private GPS() {
}
/**
* Start requesting for location updates
*
* @return Whether the user has given permission or not
*/
public static boolean start(Context context) {
locationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);
if (locationManager != null) {
boolean isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (isGPSEnabled)
requestLocationWithProvider(LocationManager.GPS_PROVIDER, context);
if (isNetworkEnabled)
requestLocationWithProvider(LocationManager.NETWORK_PROVIDER, context);
if (!isGPSEnabled && !isNetworkEnabled)
Toast.makeText(context, "Active le GPS pour avoir accès à toutes les options", Toast.LENGTH_SHORT).show();
isActivated = isGPSEnabled || isNetworkEnabled;
} else
Log.e("Location manager", "Cannot get location manager");
return true;
}
/**
* Update the location using the given provider
* @param provider provide to use for location
* @param context context to use to show error message
*/
private static void requestLocationWithProvider(String provider, Context context){
if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(context, "Permission au GPS non donnée", Toast.LENGTH_SHORT).show();
return;
}
locationManager.requestLocationUpdates(provider, MIN_TIME_FOR_UPDATES, MIN_DISTANCE_TO_REQUEST_LOCATION, locationListener);
Location tempLocation = locationManager.getLastKnownLocation(provider);
if (tempLocation != null && isBetterLocation(tempLocation, location)) {
location = tempLocation;
}
}
/**
* Stop asking for location updates
*/
public static void stop() {
isActivated = false;
if (locationManager != null) {
locationManager.removeUpdates(locationListener);
}
}
/**
* Return whether the location tracker is activated or not
*
* @return whether the location tracker is activated or not
*/
public static boolean isActivated() {
return isActivated;
}
/**
* Return the last known location
*
* @return The last known location
*/
public static Location getLocation() {
return location;
}
/**
* Check whether a location is better than the current one
*
* @param location The new location to test
* @param currentBestLocation The current location
* @return whether the new location is better or not
*/
private static 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
return isMoreAccurate || (isNewer && !isLessAccurate) || (isNewer && !isSignificantlyLessAccurate && isFromSameProvider);
}
/**
* 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);
}
/**
* Return the location listener
*
* @return The location listener
*/
public static LocationListener getListener() {
return locationListener;
}
}