package carnero.cgeo;
import android.content.Context;
import android.content.SharedPreferences;
import android.location.GpsSatellite;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
public class cgGeo {
private Context context = null;
private cgeoapplication app = null;
private LocationManager geoManager = null;
private cgUpdateLoc geoUpdate = null;
private cgWarning warning = null;
private cgBase base = null;
private cgSettings settings = null;
private SharedPreferences prefs = null;
private cgeoGeoListener geoNetListener = null;
private cgeoGeoListener geoGpsListener = null;
private cgeoGpsStatusListener geoGpsStatusListener = null;
private Integer time = 0;
private Integer distance = 0;
private Location locGps = null;
private Location locNet = null;
private long locGpsLast = 0l;
private boolean g4cRunning = false;
private Double lastGo4cacheLat = null;
private Double lastGo4cacheLon = null;
public Location location = null;
public int gps = -1;
public Double latitudeNow = null;
public Double longitudeNow = null;
public Double latitudeBefore = null;
public Double longitudeBefore = null;
public Double altitudeNow = null;
public Double bearingNow = null;
public Float speedNow = null;
public Float accuracyNow = null;
public Integer satellitesVisible = null;
public Integer satellitesFixed = null;
public double distanceNow = 0d;
public cgGeo(Context contextIn, cgeoapplication appIn, cgUpdateLoc geoUpdateIn, cgBase baseIn, cgSettings settingsIn, cgWarning warningIn, int timeIn, int distanceIn) {
context = contextIn;
app = appIn;
geoUpdate = geoUpdateIn;
base = baseIn;
settings = settingsIn;
warning = warningIn;
time = timeIn;
distance = distanceIn;
if (prefs == null) {
prefs = context.getSharedPreferences(cgSettings.preferences, 0);
}
distanceNow = prefs.getFloat("dst", 0f);
if (Double.isNaN(distanceNow) == true) {
distanceNow = 0d;
}
if (distanceNow == 0f) {
final SharedPreferences.Editor prefsEdit = context.getSharedPreferences(cgSettings.preferences, 0).edit();
if (prefsEdit != null) {
prefsEdit.putLong("dst-since", System.currentTimeMillis());
prefsEdit.commit();
}
}
geoNetListener = new cgeoGeoListener();
geoNetListener.setProvider(LocationManager.NETWORK_PROVIDER);
geoGpsListener = new cgeoGeoListener();
geoGpsListener.setProvider(LocationManager.GPS_PROVIDER);
geoGpsStatusListener = new cgeoGpsStatusListener();
}
public void initGeo() {
location = null;
gps = -1;
latitudeNow = null;
longitudeNow = null;
altitudeNow = null;
bearingNow = null;
speedNow = null;
accuracyNow = null;
satellitesVisible = 0;
satellitesFixed = 0;
if (geoManager == null) {
geoManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
}
lastLoc();
geoNetListener.setProvider(LocationManager.NETWORK_PROVIDER);
geoGpsListener.setProvider(LocationManager.GPS_PROVIDER);
geoManager.addGpsStatusListener(geoGpsStatusListener);
try {
geoManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, time, distance, geoNetListener);
} catch (Exception e) {
Log.e(cgSettings.tag, "There is no NETWORK location provider");
}
try {
geoManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, time, distance, geoGpsListener);
} catch (Exception e) {
Log.e(cgSettings.tag, "There is no GPS location provider");
}
}
public void closeGeo() {
if (geoManager != null && geoNetListener != null) {
geoManager.removeUpdates(geoNetListener);
}
if (geoManager != null && geoGpsListener != null) {
geoManager.removeUpdates(geoGpsListener);
}
if (geoManager != null) {
geoManager.removeGpsStatusListener(geoGpsStatusListener);
}
final SharedPreferences.Editor prefsEdit = context.getSharedPreferences(cgSettings.preferences, 0).edit();
if (prefsEdit != null && Double.isNaN(distanceNow) == false) {
prefsEdit.putFloat("dst", (float) distanceNow);
prefsEdit.commit();
}
}
public void replaceUpdate(cgUpdateLoc geoUpdateIn) {
geoUpdate = geoUpdateIn;
if (geoUpdate != null) {
geoUpdate.updateLoc(this);
}
}
public class cgeoGeoListener implements LocationListener {
public String active = null;
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// nothing
}
@Override
public void onLocationChanged(Location location) {
if (location.getProvider().equals(LocationManager.GPS_PROVIDER) == true) {
locGps = location;
locGpsLast = System.currentTimeMillis();
} else if (location.getProvider().equals(LocationManager.NETWORK_PROVIDER) == true) {
locNet = location;
}
selectBest(location.getProvider());
}
@Override
public void onProviderDisabled(String provider) {
if (provider.equals(LocationManager.NETWORK_PROVIDER) == true) {
if (geoManager != null && geoNetListener != null) {
geoManager.removeUpdates(geoNetListener);
}
} else if (provider.equals(LocationManager.GPS_PROVIDER) == true) {
if (geoManager != null && geoGpsListener != null) {
geoManager.removeUpdates(geoGpsListener);
}
}
}
@Override
public void onProviderEnabled(String provider) {
if (provider.equals(LocationManager.NETWORK_PROVIDER) == true) {
if (geoNetListener == null) {
geoNetListener = new cgeoGeoListener();
}
geoNetListener.setProvider(LocationManager.NETWORK_PROVIDER);
} else if (provider.equals(LocationManager.GPS_PROVIDER) == true) {
if (geoGpsListener == null) {
geoGpsListener = new cgeoGeoListener();
}
geoGpsListener.setProvider(LocationManager.GPS_PROVIDER);
}
}
public void setProvider(String provider) {
if (provider.equals(LocationManager.GPS_PROVIDER) == true) {
if (geoManager != null && geoManager.isProviderEnabled(LocationManager.GPS_PROVIDER) == true) {
active = provider;
} else {
active = null;
}
} else if (provider.equals(LocationManager.NETWORK_PROVIDER) == true) {
if (geoManager != null && geoManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) == true) {
active = provider;
} else {
active = null;
}
}
}
}
public class cgeoGpsStatusListener implements GpsStatus.Listener {
@Override
public void onGpsStatusChanged(int event) {
if (event == GpsStatus.GPS_EVENT_SATELLITE_STATUS) {
GpsStatus status = geoManager.getGpsStatus(null);
Iterator<GpsSatellite> statusIterator = status.getSatellites().iterator();
int satellites = 0;
int fixed = 0;
while (statusIterator.hasNext()) {
GpsSatellite sat = statusIterator.next();
if (sat.usedInFix() == true) {
fixed++;
}
satellites++;
/* satellite signal strength
if (sat.usedInFix()) {
Log.d(cgSettings.tag, "Sat #" + satellites + ": " + sat.getSnr() + " FIX");
} else {
Log.d(cgSettings.tag, "Sat #" + satellites + ": " + sat.getSnr());
}
*/
}
boolean changed = false;
if (satellitesVisible == null || satellites != satellitesVisible) {
satellitesVisible = satellites;
changed = true;
}
if (satellitesFixed == null || fixed != satellitesFixed) {
satellitesFixed = fixed;
changed = true;
}
if (changed == true) {
selectBest(null);
}
}
}
}
private void selectBest(String initProvider) {
if (locNet == null && locGps != null) { // we have only GPS
assign(locGps);
return;
}
if (locNet != null && locGps == null) { // we have only NET
assign(locNet);
return;
}
if (satellitesFixed > 0) { // GPS seems to be fixed
assign(locGps);
return;
}
if (initProvider != null && initProvider.equals(LocationManager.GPS_PROVIDER) == true) { // we have new location from GPS
assign(locGps);
return;
}
if (locGpsLast > (System.currentTimeMillis() - 30 * 1000)) { // GPS was working in last 30 seconds
assign(locGps);
return;
}
assign(locNet); // nothing else, using NET
}
private void assign(Double lat, Double lon) {
if (lat == null || lon == null) {
return;
}
gps = -1;
latitudeNow = lat;
longitudeNow = lon;
altitudeNow = null;
bearingNow = new Double(0);
speedNow = 0f;
accuracyNow = 999f;
if (geoUpdate != null) {
geoUpdate.updateLoc(this);
}
}
private void assign(Location loc) {
if (loc == null) {
gps = -1;
return;
}
location = loc;
String provider = location.getProvider();
if (provider.equals(LocationManager.GPS_PROVIDER) == true) {
gps = 1;
} else if (provider.equals(LocationManager.NETWORK_PROVIDER) == true) {
gps = 0;
} else if (provider.equals("last") == true) {
gps = -1;
}
latitudeNow = location.getLatitude();
longitudeNow = location.getLongitude();
app.setLastLoc(latitudeNow, longitudeNow);
if (location.hasAltitude() && gps != -1) {
altitudeNow = location.getAltitude() + settings.altCorrection;
} else {
altitudeNow = null;
}
if (location.hasBearing() && gps != -1) {
bearingNow = new Double(location.getBearing());
} else {
bearingNow = new Double(0);
}
if (location.hasSpeed() && gps != -1) {
speedNow = location.getSpeed();
} else {
speedNow = 0f;
}
if (location.hasAccuracy() && gps != -1) {
accuracyNow = location.getAccuracy();
} else {
accuracyNow = 999f;
}
if (gps == 1) {
// save travelled distance only when location is from GPS
if (latitudeBefore != null && longitudeBefore != null && latitudeNow != null && longitudeNow != null) {
final double dst = cgBase.getDistance(latitudeBefore, longitudeBefore, latitudeNow, longitudeNow);
if (Double.isNaN(dst) == false && dst > 0.005) {
distanceNow += dst;
latitudeBefore = latitudeNow;
longitudeBefore = longitudeNow;
}
} else if (latitudeBefore == null || longitudeBefore == null) { // values aren't initialized
latitudeBefore = latitudeNow;
longitudeBefore = longitudeNow;
}
}
if (geoUpdate != null) {
geoUpdate.updateLoc(this);
}
if (gps > -1) {
(new publishLoc()).start();
}
}
private class publishLoc extends Thread {
private publishLoc() {
setPriority(Thread.MIN_PRIORITY);
}
@Override
public void run() {
if (g4cRunning == true) {
return;
}
if (settings.publicLoc == 1 && (lastGo4cacheLat == null || lastGo4cacheLon == null || cgBase.getDistance(latitudeNow, longitudeNow, lastGo4cacheLat, lastGo4cacheLon) > 0.75)) {
g4cRunning = true;
final String host = "api.go4cache.com";
final String path = "/";
final String method = "POST";
String action = null;
if (app != null) {
action = app.getAction();
} else {
action = "";
}
final String username = settings.getUsername();
if (username != null) {
final HashMap<String, String> params = new HashMap<String, String>();
final String latStr = String.format((Locale) null, "%.6f", latitudeNow);
final String lonStr = String.format((Locale) null, "%.6f", longitudeNow);
params.put("u", username);
params.put("lt", latStr);
params.put("ln", lonStr);
params.put("a", action);
params.put("s", (cgBase.sha1(username + "|" + latStr + "|" + lonStr + "|" + action + "|" + cgBase.md5("carnero: developing your dreams"))).toLowerCase());
if (base.version != null) {
params.put("v", base.version);
}
final String res = base.request(false, host, path, method, params, false, false, false).getData();
if (res != null && res.length() > 0) {
lastGo4cacheLat = latitudeNow;
lastGo4cacheLon = longitudeNow;
}
}
}
g4cRunning = false;
}
}
public void lastLoc() {
assign(app.getLastLat(), app.getLastLon());
Location lastGps = geoManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastGps != null) {
lastGps.setProvider("last");
assign(lastGps);
Log.i(cgSettings.tag, "Using last location from GPS");
return;
}
Location lastGsm = geoManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (lastGsm != null) {
lastGsm.setProvider("last");
assign(lastGsm);
Log.i(cgSettings.tag, "Using last location from NETWORK");
return;
}
}
}