/**
* galaxy inc.
* meetup client for android
*/
package com.galaxy.meetup.client.android;
import java.util.List;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import com.galaxy.meetup.client.android.api.LocationQuery;
import com.galaxy.meetup.client.android.api.SnapToPlaceOperation;
import com.galaxy.meetup.client.android.content.DbLocation;
import com.galaxy.meetup.client.android.content.EsAccount;
import com.galaxy.meetup.client.util.EsLog;
import com.galaxy.meetup.client.util.GoogleLocationSettingHelper;
import com.galaxy.meetup.client.util.Property;
/**
*
* @author sihai
*
*/
public class LocationController {
private final EsAccount mAccount;
private final Context mContext;
private final boolean mDisplayDebugToast;
private LocationListener mGpsListener;
private final Handler mHandler;
private Location mLastSentLocation;
private LocationListener mLastSuccessfulLocationListener;
private LocationListener mListener;
private Location mLocation;
private Runnable mLocationAcquisitionTimer;
private final LocationManager mLocationManager;
private LocationListener mNetworkListener;
private final boolean mReverseGeo;
private final long mTimeout;
public LocationController(Context context, EsAccount esaccount, boolean flag, long l, Location location, LocationListener locationlistener) {
mContext = context;
mAccount = esaccount;
mListener = locationlistener;
mHandler = new Handler();
mReverseGeo = true;
mLocation = location;
mTimeout = 3000L;
mLocationManager = (LocationManager)context.getSystemService("location");
List list = mLocationManager.getProviders(true);
int i = list.size();
for(int j = 0; j < i; j++) {
// FIXME only better one ?
if("network".equals(list.get(j))) {
mNetworkListener = new LocalLocationListener();
mLocationManager.requestLocationUpdates("network", 3000L, 0.0F, mNetworkListener);
}
if("gps".equals(list.get(j))) {
mGpsListener = new LocalLocationListener();
mLocationManager.requestLocationUpdates("gps", 3000L, 0.0F, mGpsListener);
}
}
mDisplayDebugToast = Property.LOCATION_DEBUGGING.get().equalsIgnoreCase("TRUE");
return;
}
public static boolean areSameLocations(Location location, Location location1)
{
boolean flag;
if(location.getLatitude() == location1.getLatitude() && location.getLongitude() == location1.getLongitude() && (float)(int)location.getAccuracy() - location1.getAccuracy() == 0.0F)
flag = true;
else
flag = false;
return flag;
}
private boolean canFindLocation()
{
boolean flag;
if(mLocationManager.isProviderEnabled("network") || mLocationManager.isProviderEnabled("gps"))
flag = true;
else
flag = false;
return flag;
}
private static boolean canFindLocation(Context context)
{
LocationManager locationmanager = (LocationManager)context.getSystemService("location");
boolean flag;
if(locationmanager.isProviderEnabled("network") || locationmanager.isProviderEnabled("gps"))
flag = true;
else
flag = false;
return flag;
}
public static DbLocation getCityLevelLocation(Location location)
{
return (DbLocation)getExtras(location).getParcelable("coarse_location");
}
private static Bundle getExtras(Location location)
{
Bundle bundle = location.getExtras();
if(bundle == null)
bundle = Bundle.EMPTY;
return bundle;
}
public static String getFormattedAddress(Location location)
{
Bundle bundle = getExtras(location);
bundle.setClassLoader(DbLocation.class.getClassLoader());
return bundle.getString("location_description");
}
public static DbLocation getStreetLevelLocation(Location location)
{
return (DbLocation)getExtras(location).getParcelable("finest_location");
}
public static boolean isProviderEnabled(Context context) {
boolean flag = false;
if(android.os.Build.VERSION.SDK_INT >= 11) {
switch(GoogleLocationSettingHelper.getUseLocationForServices(context))
{
default:
flag = canFindLocation(context);
break;
case 0: // '\0'
flag = false;
break;
}
} else {
flag = canFindLocation(context);
}
return flag;
}
public final void init()
{
if(mLocationAcquisitionTimer != null)
{
mHandler.removeCallbacks(mLocationAcquisitionTimer);
mLocationAcquisitionTimer = null;
}
mLastSentLocation = null;
if(mTimeout > 0L && mNetworkListener != null && mGpsListener != null)
{
mLocationAcquisitionTimer = new Runnable() {
public final void run()
{
if(mLocation != null)
{
if(EsLog.isLoggable("LocationController", 3))
Log.d("LocationController", "----> locationAcquisitionTimer: timeout, with location");
if(mLastSentLocation == null || !LocationController.areSameLocations(mLastSentLocation, mLocation))
{
if(mReverseGeo)
startSnapToPlace();
else
if(mListener != null)
mListener.onLocationChanged(mLocation);
mLastSentLocation = mLocation;
}
} else
{
if(EsLog.isLoggable("LocationController", 3))
Log.d("LocationController", "----> locationAcquisitionTimer: timeout, without location");
mHandler.postDelayed(this, mTimeout / 2L);
}
}
};
mHandler.postDelayed(mLocationAcquisitionTimer, mTimeout);
}
}
public final boolean isProviderEnabled() {
boolean flag = false;
if(android.os.Build.VERSION.SDK_INT >= 11) {
switch(GoogleLocationSettingHelper.getUseLocationForServices(mContext))
{
default:
flag = canFindLocation();
break;
case 0: // '\0'
flag = false;
break;
}
} else {
flag = canFindLocation();
}
return flag;
}
public final void release()
{
if(mLocationAcquisitionTimer != null)
{
mHandler.removeCallbacks(mLocationAcquisitionTimer);
mLocationAcquisitionTimer = null;
}
if(mNetworkListener != null)
mLocationManager.removeUpdates(mNetworkListener);
if(mGpsListener != null)
mLocationManager.removeUpdates(mGpsListener);
mListener = null;
}
private void startSnapToPlace() {
new SnapToPlaceThread().start();
}
private class SnapToPlaceThread extends Thread {
public final void run() {
SnapToPlaceOperation snaptoplaceoperation = new SnapToPlaceOperation(mContext, mAccount, null, null, new LocationQuery(mLocation, null), null, false);
snaptoplaceoperation.start();
Bundle bundle = new Bundle();
if(mDisplayDebugToast && mLocation.getExtras() != null)
bundle.putString("location_source", mLocation.getExtras().getString("location_source"));
String s;
DbLocation dblocation;
if(!snaptoplaceoperation.hasPreciseLocation()) {
if(snaptoplaceoperation.hasPlaceLocation())
{
dblocation = snaptoplaceoperation.getPlaceLocation();
s = "finest_location";
} else
{
boolean flag = snaptoplaceoperation.hasCoarseLocation();
s = null;
dblocation = null;
if(flag)
{
dblocation = snaptoplaceoperation.getCoarseLocation();
s = "coarse_location";
}
}
} else {
dblocation = snaptoplaceoperation.getPreciseLocation();
s = "finest_location";
}
if(dblocation != null)
{
bundle.putParcelable(s, dblocation);
String s1 = dblocation.getLocationName();
if(!TextUtils.isEmpty(s1))
bundle.putString("location_description", s1);
}
mLocation.setExtras(bundle);
mHandler.post(new Runnable() {
public final void run() {
if(mDisplayDebugToast)
Toast.makeText(mContext, (new StringBuilder()).append(mLocation.getExtras().getString("location_source")).append(LocationController.getFormattedAddress(mLocation)).toString(), 0).show();
if(mListener != null)
mListener.onLocationChanged(mLocation);
}
});
return;
}
}
private final class LocalLocationListener implements LocationListener {
private void triggerLocationListener()
{
if((mLastSuccessfulLocationListener == null || mLastSuccessfulLocationListener == this) && mLocationAcquisitionTimer != null || mLastSentLocation != null && LocationController.areSameLocations(mLastSentLocation, mLocation)) {
mLastSuccessfulLocationListener = this;
} else {
if(EsLog.isLoggable("LocationController", 3))
{
StringBuilder stringbuilder = new StringBuilder("----> onLocationChanged: triggering location change because ");
String s;
if(mLocationAcquisitionTimer == null)
s = "only this location listener was registered";
else
s = "a previous location listener was successful";
Log.d("LocationController", stringbuilder.append(s).toString());
}
if(!mReverseGeo) {
if(mListener != null)
mListener.onLocationChanged(mLocation);
} else {
startSnapToPlace();
}
mLastSentLocation = mLocation;
mLastSuccessfulLocationListener = this;
return;
}
}
public final void onLocationChanged(Location location)
{
if(EsLog.isLoggable("LocationController", 3))
Log.d("LocationController", (new StringBuilder("====> onLocationChanged: ")).append(location.getTime()).append(" from provider: ").append(location.getProvider()).toString());
if(mLocation != null)
{
triggerLocationListener();
} else
{
if(EsLog.isLoggable("LocationController", 3))
Log.d("LocationController", (new StringBuilder("----> onLocationChanged: new location: ")).append(location.getAccuracy()).toString());
mLocation = location;
if(mDisplayDebugToast)
{
String s;
if(this == mNetworkListener)
s = "net: ";
else
s = "gps: ";
mLocation.getExtras().putString("location_source", s);
}
triggerLocationListener();
}
}
public final void onProviderDisabled(String s)
{
if(mListener != null)
mListener.onProviderDisabled(s);
}
public final void onProviderEnabled(String s)
{
if(mListener != null)
mListener.onProviderEnabled(s);
}
public final void onStatusChanged(String s, int i, Bundle bundle)
{
if(mListener != null)
mListener.onStatusChanged(s, i, bundle);
}
}
}