package eu.tpmusielak.securephoto.verification.geo;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
import eu.tpmusielak.securephoto.verification.VerifierBinder;
import eu.tpmusielak.securephoto.verification.VerifierWrapper;
/**
* Created by IntelliJ IDEA.
* User: Tomasz P. Musielak
* Date: 27/03/12
* Time: 23:56
*/
public class GeolocationVerifierWrapper extends VerifierWrapper implements GeolocationProvider, LocationListener {
private LocationManager locationManager;
private Location currentLocation;
@Override
public void register(VerifierBinder m) {
super.register(m);
locationManager = (LocationManager) verifierManager.getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
@Override
public void onCameraStart() {
super.onCameraStart();
if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
notifyNoGPS();
currentLocation = null; // Invalidate location
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
startFlashingIcon();
}
@Override
public void onCameraExit() {
stopFlashingIcon();
locationManager.removeUpdates(this);
super.onCameraExit();
}
public GeolocationVerifierWrapper() {
verifier = new GeolocationVerifier(this);
}
@Override
public Drawable getDrawable() {
return context.getResources().getDrawable(R.drawable.ic_stat_location);
}
@Override
public int getPreferenceID() {
return R.xml.geo_prefs;
}
@Override
public String getName() {
return context.getResources().getString(R.string.geolocation_verifier);
}
@Override
public GeolocationData getLocation() {
if (currentLocation == null) {
//TODO: ensure to get location if locking settings is on
//TODO: create a civilised way of giving stubbed-out verifier data
return new GeolocationData(0, 0, 0, 0, 0);
}
return new GeolocationData(currentLocation.getTime(), currentLocation.getLatitude(), currentLocation.getLongitude(), currentLocation.getAccuracy());
}
/**
* GUI methods *
*/
public void notifyNoGPS() {
final AlertDialog.Builder builder = new AlertDialog.Builder(guiReceiver.getContext());
final String dialogMessage = context.getResources().getString(R.string.gps_disabled_message);
final String yes = context.getResources().getString(R.string.yes);
final String no = context.getResources().getString(R.string.no);
builder.setMessage(dialogMessage)
.setCancelable(true)
.setPositiveButton(yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
Intent openGPSSettingsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
guiReceiver.getContext().startActivity(openGPSSettingsIntent);
}
})
.setNegativeButton(no, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
dialog.cancel();
}
});
final AlertDialog alertDialog = builder.create();
alertDialog.show();
}
/* Location listener methods */
@Override
public void onLocationChanged(Location location) {
if (isBetterLocation(location, currentLocation))
if (currentLocation == null)
stopFlashingIcon();
currentLocation = location;
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
}
/**
* *************************************
* <p/>
* Code from http://developer.android.com/guide/topics/location/obtaining-user-location.html
* <p/>
* *************************************
*/
private static final int TWO_MINUTES = 1000 * 60 * 2;
/**
* Determines whether one Location reading is better than the current Location fix
*
* @param location The new Location that you want to evaluate
* @param currentBestLocation The current Location fix, to which you want to compare the new one
*/
protected 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 whether two providers are the same
*/
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
/*****
*
* End of external code
*
*/
}