<commit_before>/**
 * Appcelerator Titanium Mobile
 * Copyright (c) 2009-2010 by Appcelerator, Inc. All Rights Reserved.
 * Licensed under the terms of the Apache Public License
 * Please see the LICENSE included with this distribution for details.
 */
package ti.modules.titanium.geolocation;

import java.util.Iterator;
import java.util.List;

import org.appcelerator.titanium.TiDict;
import org.appcelerator.titanium.TiModule;
import org.appcelerator.titanium.kroll.KrollCallback;
import org.appcelerator.titanium.util.Log;
import org.appcelerator.titanium.util.TiConfig;
import org.appcelerator.titanium.util.TiConvert;

import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;

public class TiLocation
{
	private static final String LCAT = "TiLocation";
	private static final Boolean DBG = true; //TiConfig.LOGD;

	public static final int ERR_UNKNOWN_ERROR = 0;
	public static final int ERR_PERMISSION_DENIED = 1;
	public static final int ERR_POSITION_UNAVAILABLE = 2;
	public static final int ERR_TIMEOUT = 3;

	public static final int ACCURACY_BEST = 0;
	public static final int ACCURACY_NEAREST_TEN_METERS = 1;
	public static final int ACCURACY_HUNDRED_METERS = 2;
	public static final int ACCURACY_KILOMETER = 3;
	public static final int ACCURACY_THREE_KILOMETERS = 4;

	public static final long MAX_GEO_ANALYTICS_FREQUENCY = 60000L;

	public static final String EVENT_LOCATION = "location";

	protected static final String OPTION_HIGH_ACCURACY = "enableHighAccuracy";

	private TiModule proxy;

	protected LocationManager locationManager;
	protected LocationListener geoListener;
	protected boolean listeningForGeo;

	protected long lastEventTimestamp; // This counter is instance specific. The actually queuing code
	                                   // will arbitrate between other instances. Since only one activity
									   // at a time can be active, there shouldn't be any contention.

	public TiLocation(TiModule proxy)
	{
		this.proxy = proxy;
		final TiModule fproxy = proxy;
		listeningForGeo = false;

		geoListener = new LocationListener() {

			public void onLocationChanged(Location location) {
				if (locationManager != null) {
					LocationProvider provider = locationManager.getProvider(location.getProvider());
					fproxy.fireEvent(EVENT_LOCATION, locationToTiDict(location, provider));
					if (location.getTime() - lastEventTimestamp > MAX_GEO_ANALYTICS_FREQUENCY) {
						// Null is returned if it's too early to send another event.
						// TODO Analytics
	//						TitaniumAnalyticsEvent event = TitaniumAnalyticsEventFactory.createAppGeoEvent(location);
	//						if (event != null) {
	//							app.postAnalyticsEvent(event);
	//							lastEventTimestamp = location.getTime();
	//						}
					}
				} else {
					Log.i(LCAT, "onLocationChanged - Location Manager null");					
				}
			}

			public void onProviderDisabled(String provider) {
				Log.d(LCAT, "Provider disabled: " + provider);
				fproxy.fireEvent(EVENT_LOCATION, TiConvert.toErrorObject(ERR_POSITION_UNAVAILABLE, provider + " disabled."));
			}

			public void onProviderEnabled(String provider) {
				Log.d(LCAT, "Provider enabled: " + provider);
				//eventManager.invokeErrorListeners(EVENT_GEO, createJSONError(ERR_POSITION_UNAVAILABLE, provider + " enabled."));
			}

			public void onStatusChanged(String provider, int status, Bundle extras) {
				Log.d(LCAT, "Status changed, provider = " + provider + " status=" + status);
				switch (status) {
					case LocationProvider.OUT_OF_SERVICE :
						fproxy.fireEvent(EVENT_LOCATION, TiConvert.toErrorObject(ERR_POSITION_UNAVAILABLE, provider + " is out of service."));
					break;
					case LocationProvider.TEMPORARILY_UNAVAILABLE:
						fproxy.fireEvent(EVENT_LOCATION, TiConvert.toErrorObject(ERR_POSITION_UNAVAILABLE, provider + " is currently unavailable."));
					break;
					case LocationProvider.AVAILABLE :
						if (DBG) {
							Log.i(LCAT, provider + " is available.");
						}
					break;
					default:
						Log.w(LCAT, "Unknown status update from ["+provider+"] - passed code: "+status);
					break;
				}
			}
		};

		locationManager = (LocationManager) proxy.getTiContext().getActivity().getSystemService(Context.LOCATION_SERVICE);

	}

	public void getCurrentPosition(KrollCallback listener)
	{
		if (listener != null && locationManager != null) {
			// Prefer the user selected provider
			String provider = fetchProvider();
			
			if (provider != null) {
				// We should really query all active providers - one may have a more accurate fix
				Location location = locationManager.getLastKnownLocation(provider);
				if (location != null) {
					listener.callWithProperties(locationToTiDict(location, locationManager.getProvider(provider)));
				} else {
					Log.i(LCAT, "getCurrentPosition - location is null");
					listener.callWithProperties(TiConvert.toErrorObject(ERR_POSITION_UNAVAILABLE, "location is currently unavailable."));
				}
			} else {
				Log.i(LCAT, "getCurrentPosition - no providers are available");
			}
		} else {
			Log.i(LCAT, "getCurrentPosition - listener or locationManager null");
			listener.callWithProperties(TiConvert.toErrorObject(ERR_POSITION_UNAVAILABLE, "location is currently unavailable."));
		}
	}
	
	protected boolean isLocationProviderEnabled(String name) {
		if (null != locationManager){
			try {
				return locationManager.isProviderEnabled(name);				
			} catch (Exception e) {
				// Ignore - it's expected
				e = null;<commit_msg>[#1332 state:resolved] It helps if I report the lack of providers back to the app.<commit_after>/**
 * Appcelerator Titanium Mobile
 * Copyright (c) 2009-2010 by Appcelerator, Inc. All Rights Reserved.
 * Licensed under the terms of the Apache Public License
 * Please see the LICENSE included with this distribution for details.
 */
package ti.modules.titanium.geolocation;

import java.util.Iterator;
import java.util.List;

import org.appcelerator.titanium.TiDict;
import org.appcelerator.titanium.TiModule;
import org.appcelerator.titanium.kroll.KrollCallback;
import org.appcelerator.titanium.util.Log;
import org.appcelerator.titanium.util.TiConfig;
import org.appcelerator.titanium.util.TiConvert;

import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;

public class TiLocation
{
	private static final String LCAT = "TiLocation";
	private static final Boolean DBG = true; //TiConfig.LOGD;

	public static final int ERR_UNKNOWN_ERROR = 0;
	public static final int ERR_PERMISSION_DENIED = 1;
	public static final int ERR_POSITION_UNAVAILABLE = 2;
	public static final int ERR_TIMEOUT = 3;

	public static final int ACCURACY_BEST = 0;
	public static final int ACCURACY_NEAREST_TEN_METERS = 1;
	public static final int ACCURACY_HUNDRED_METERS = 2;
	public static final int ACCURACY_KILOMETER = 3;
	public static final int ACCURACY_THREE_KILOMETERS = 4;

	public static final long MAX_GEO_ANALYTICS_FREQUENCY = 60000L;

	public static final String EVENT_LOCATION = "location";

	protected static final String OPTION_HIGH_ACCURACY = "enableHighAccuracy";

	private TiModule proxy;

	protected LocationManager locationManager;
	protected LocationListener geoListener;
	protected boolean listeningForGeo;

	protected long lastEventTimestamp; // This counter is instance specific. The actually queuing code
	                                   // will arbitrate between other instances. Since only one activity
									   // at a time can be active, there shouldn't be any contention.

	public TiLocation(TiModule proxy)
	{
		this.proxy = proxy;
		final TiModule fproxy = proxy;
		listeningForGeo = false;

		geoListener = new LocationListener() {

			public void onLocationChanged(Location location) {
				if (locationManager != null) {
					LocationProvider provider = locationManager.getProvider(location.getProvider());
					fproxy.fireEvent(EVENT_LOCATION, locationToTiDict(location, provider));
					if (location.getTime() - lastEventTimestamp > MAX_GEO_ANALYTICS_FREQUENCY) {
						// Null is returned if it's too early to send another event.
						// TODO Analytics
	//						TitaniumAnalyticsEvent event = TitaniumAnalyticsEventFactory.createAppGeoEvent(location);
	//						if (event != null) {
	//							app.postAnalyticsEvent(event);
	//							lastEventTimestamp = location.getTime();
	//						}
					}
				} else {
					Log.i(LCAT, "onLocationChanged - Location Manager null");					
				}
			}

			public void onProviderDisabled(String provider) {
				Log.d(LCAT, "Provider disabled: " + provider);
				fproxy.fireEvent(EVENT_LOCATION, TiConvert.toErrorObject(ERR_POSITION_UNAVAILABLE, provider + " disabled."));
			}

			public void onProviderEnabled(String provider) {
				Log.d(LCAT, "Provider enabled: " + provider);
				//eventManager.invokeErrorListeners(EVENT_GEO, createJSONError(ERR_POSITION_UNAVAILABLE, provider + " enabled."));
			}

			public void onStatusChanged(String provider, int status, Bundle extras) {
				Log.d(LCAT, "Status changed, provider = " + provider + " status=" + status);
				switch (status) {
					case LocationProvider.OUT_OF_SERVICE :
						fproxy.fireEvent(EVENT_LOCATION, TiConvert.toErrorObject(ERR_POSITION_UNAVAILABLE, provider + " is out of service."));
					break;
					case LocationProvider.TEMPORARILY_UNAVAILABLE:
						fproxy.fireEvent(EVENT_LOCATION, TiConvert.toErrorObject(ERR_POSITION_UNAVAILABLE, provider + " is currently unavailable."));
					break;
					case LocationProvider.AVAILABLE :
						if (DBG) {
							Log.i(LCAT, provider + " is available.");
						}
					break;
					default:
						Log.w(LCAT, "Unknown status update from ["+provider+"] - passed code: "+status);
					break;
				}
			}
		};

		locationManager = (LocationManager) proxy.getTiContext().getActivity().getSystemService(Context.LOCATION_SERVICE);

	}

	public void getCurrentPosition(KrollCallback listener)
	{
		if (listener != null && locationManager != null) {
			// Prefer the user selected provider
			String provider = fetchProvider();
			
			if (provider != null) {
				// We should really query all active providers - one may have a more accurate fix
				Location location = locationManager.getLastKnownLocation(provider);
				if (location != null) {
					listener.callWithProperties(locationToTiDict(location, locationManager.getProvider(provider)));
				} else {
					Log.i(LCAT, "getCurrentPosition - location is null");
					listener.callWithProperties(TiConvert.toErrorObject(ERR_POSITION_UNAVAILABLE, "location is currently unavailable."));
				}
			} else {
				Log.i(LCAT, "getCurrentPosition - no providers are available");
				listener.callWithProperties(TiConvert.toErrorObject(ERR_POSITION_UNAVAILABLE, "no providers are available."));
			}
		} else {
			Log.i(LCAT, "getCurrentPosition - listener or locationManager null");
			listener.callWithProperties(TiConvert.toErrorObject(ERR_POSITION_UNAVAILABLE, "location is currently unavailable."));
		}
	}
	
	protected boolean isLocationProviderEnabled(String name) {
		if (null != locationManager){
			try {
				return locationManager.isProviderEnabled(name);				
			} catch (Exception e) {
				// Ignore - it's expected
				e = null;
{'fraction_non_alphanumeric': 0.0908774373259053, 'fraction_numerical': 0.004178272980501393, 'mean_word_length': 4.097160603371783, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4943249', 'n_tokens_mistral': 3961, 'n_tokens_neox': 3329, 'n_words': 874}