Fixes for Android code - It actually works now! No monitoring yet, no advertising yet

#############################
BeaconUtils.java
#############################
package com.thinketg.plugin.ibeacongap;

import java.util.ArrayList;

import com.radiusnetworks.ibeacon.*;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;

public class BeaconUtils implements IBeaconConsumer {

	protected static final String TAG = "BeaconUtils";

	private Context context;

	private IBeaconManager iBeaconManager;
	private RangingManager rangingManager;
	private MonitoringManager monitoringManager;

	public ArrayList<IBeacon> myBeacons = new ArrayList<IBeacon>();

	private InitializedListener initializedListener;
	private boolean initialized = false;

	public BeaconUtils(Context context) {
		this.context = context;

		this.iBeaconManager = IBeaconManager
				.getInstanceForApplication(this.context.getApplicationContext());
		this.iBeaconManager.bind(this);

		this.monitoringManager = new MonitoringManager(this.iBeaconManager);
		this.rangingManager = new RangingManager(this.iBeaconManager);

		// verifyBluetooth((Activity) context);
	}

	public void setInitializedListener(InitializedListener listener) {
		this.initializedListener = listener;
		if (initialized) {
			this.initializedListener.initialized();
		}
	}

	public RangingManager getRangingManager() {
		return this.rangingManager;
	}

	public MonitoringManager getMonitoringManager() {
		return this.monitoringManager;
	}

	// @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
	public static void verifyBluetooth(final Activity activity) {

		try {
			if (!IBeaconManager.getInstanceForApplication(activity)
					.checkAvailability()) {
				final AlertDialog.Builder builder = new AlertDialog.Builder(
						activity);
				builder.setTitle("Bluetooth not enabled");
				builder.setMessage("Please enable bluetooth in settings and restart this application.");
				builder.setPositiveButton(android.R.string.ok, null);
				builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
					@Override
					public void onDismiss(DialogInterface dialog) {
						activity.finish();
						// System.exit(0);
					}
				});
				builder.show();
			}
		} catch (RuntimeException e) {
			final AlertDialog.Builder builder = new AlertDialog.Builder(
					activity);
			builder.setTitle("Bluetooth LE not available");
			builder.setMessage("Sorry, this device does not support Bluetooth LE.");
			builder.setPositiveButton(android.R.string.ok, null);
			builder.setOnDismissListener(new DialogInterface.OnDismissListener() {

				@Override
				public void onDismiss(DialogInterface dialog) {
					activity.finish();
					// System.exit(0);
				}

			});
			builder.show();

		}
	}

	@Override
	public void onIBeaconServiceConnect() {
		this.iBeaconManager.setRangeNotifier(this.rangingManager);
		this.iBeaconManager.setMonitorNotifier(this.monitoringManager);
	}

	@Override
	public Context getApplicationContext() {
		return this.context;
	}

	@Override
	public void unbindService(ServiceConnection serviceConnection) {
		this.context.unbindService(serviceConnection);
		// this.iBeaconManager.unBind(this);
	}

	@Override
	public boolean bindService(Intent intent,
			ServiceConnection serviceConnection, int i) {
		// this.iBeaconManager.bind(this);
		boolean result = this.context.bindService(intent, serviceConnection, i);
		this.initialized = true;
		if (result && this.initializedListener != null) {
			this.initializedListener.initialized();
		}

		return result;
	}
}

#############################
iBeaconGap.java
#############################
package com.thinketg.plugin.ibeacongap;

import java.util.concurrent.CountDownLatch;

import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;

import android.os.RemoteException;
import android.util.Log;

import com.radiusnetworks.ibeacon.*;

import android.app.Activity;

public class iBeaconGap extends CordovaPlugin {

	protected static final String TAG = "iBeaconGap";
	private BeaconUtils util;

	@Override
	public void initialize(CordovaInterface cordova, CordovaWebView webView) {
		super.initialize(cordova, webView);

		IBeaconManager.LOG_DEBUG = true;
		
		final CountDownLatch countDownLatch = new CountDownLatch(1);
		final Activity appActivity = this.cordova.getActivity();
		cordova.getThreadPool().execute(new Runnable() {
			public void run() {
				util = new BeaconUtils(appActivity);
				util.setInitializedListener(new InitializedListener()
				{
					@Override
					public void initialized() {
						countDownLatch.countDown();
					}
				});
			}
		});
		
		try {
			countDownLatch.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Override
	public boolean execute(String action, JSONArray args,
			CallbackContext callbackContext) throws JSONException {
		Log.d(TAG, action + "(" + args.toString() + ")");

		if ("isAdvertising".equalsIgnoreCase(action)) {
			// TODO
			return false;
		}

		if ("stopAdvertising".equalsIgnoreCase(action)) {
			// TODO
			return false;
		}

		// All other methods have a region as first parameter.
		Region region = JsonHelper.jsonToBeaconRegion(args.getJSONObject(0));

		if ("startAdvertising".equalsIgnoreCase(action)) {
			Integer measuredPower = null;
			if (!args.isNull(0)) {
				// "MeasuredPower" param was passed
				measuredPower = args.getInt(0);
			}
			
			// TODO: Call ......startAdvertising(region, measuredPower);
			return false;
		}
		
		if ("startRangingBeaconsInRegion".equalsIgnoreCase(action)) {
			try {
				this.util.getRangingManager().start(region, callbackContext);
			} catch (RemoteException e) {
				callbackContext.error(e.getMessage());
			}
			return true;
		}

		if ("stopRangingBeaconsInRegion".equalsIgnoreCase(action)) {
			try {
				this.util.getRangingManager().stop(region);
				callbackContext.success();
			} catch (RemoteException e) {
				callbackContext.error(e.getMessage());
			}
			return true;
		}

		if ("startMonitoringForRegion".equalsIgnoreCase(action)) {
			try {
				this.util.getMonitoringManager().start(region, callbackContext);
			} catch (RemoteException e) {
				callbackContext.error(e.getMessage());
			}
		}

		if ("stopMonitoringForRegion".equalsIgnoreCase(action)) {
			try {
				this.util.getMonitoringManager().stop(region);
				callbackContext.success();
			} catch (RemoteException e) {
				callbackContext.error(e.getMessage());
			}
			return true;
		}

		return false;
	}
}

#############################
InitializedListener.java
#############################
package com.thinketg.plugin.ibeacongap;

public interface InitializedListener {
	void initialized();
}

#############################
JsonHelper.java
#############################
package com.thinketg.plugin.ibeacongap;

import java.util.Collection;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.radiusnetworks.ibeacon.IBeacon;
import com.radiusnetworks.ibeacon.Region;

public class JsonHelper {

	public static JSONArray listToJSONArray(Collection<IBeacon> beacons)
			throws JSONException {
		JSONArray jArray = new JSONArray();
		for (IBeacon beacon : beacons) {
			jArray.put(beaconToJSONObject(beacon));
		}
		return jArray;
	}

	public static Region jsonToBeaconRegion(JSONObject obj)
			throws JSONException {
		String uuid = obj.getString("uuid");
		Integer major = obj.isNull("major") ? null : obj.getInt("major");
		Integer minor = obj.isNull("minor") ? null : obj.getInt("minor");
		String identifier = obj.getString("identifier");

		return new Region(identifier, uuid, major, minor);
	}

	public static JSONObject beaconToJSONObject(IBeacon beacon) throws JSONException {
		JSONObject object = new JSONObject();
		object.put("proximityUUID", beacon.getProximityUuid());
		object.put("major", beacon.getMajor());
		object.put("minor", beacon.getMinor());
		object.put("rssi", beacon.getRssi());
		object.put("macAddress", beacon.getBluetoothAddress());
		object.put("measuredPower", beacon.getTxPower());
		object.put("distance", beacon.getAccuracy());
		return object;
	}
}

#############################
MonitoringManager.java
#############################
package com.thinketg.plugin.ibeacongap;

import java.util.HashMap;

import org.apache.cordova.CallbackContext;

import android.os.RemoteException;

import com.radiusnetworks.ibeacon.IBeaconManager;
import com.radiusnetworks.ibeacon.MonitorNotifier;
import com.radiusnetworks.ibeacon.Region;

public class MonitoringManager implements MonitorNotifier
{
	private HashMap<String, CallbackContext> regions = new HashMap<String, CallbackContext>();
	
	private IBeaconManager manager;
	
	public MonitoringManager(IBeaconManager manager)
	{
		this.manager = manager;
	}
	
	public void start(Region region, CallbackContext callbackContext) throws RemoteException
	{
		this.manager.startMonitoringBeaconsInRegion(region);
		this.regions.put(region.getUniqueId(), callbackContext);
	}
	
	public void stop(Region region) throws RemoteException
	{
		this.manager.stopMonitoringBeaconsInRegion(region);
		this.regions.remove(region.getUniqueId());
	}

	@Override
	public void didDetermineStateForRegion(int state, Region region) {
		// TODO Auto-generated method stub
	}

	@Override
	public void didEnterRegion(Region region) {
		// TODO Auto-generated method stub
	}

	@Override
	public void didExitRegion(Region region) {
		// TODO Auto-generated method stub
	}
}

#############################
RangingManager.java
#############################
package com.thinketg.plugin.ibeacongap;

import java.util.Collection;
import java.util.HashMap;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.PluginResult;
import org.json.JSONException;

import android.os.RemoteException;

import com.radiusnetworks.ibeacon.IBeacon;
import com.radiusnetworks.ibeacon.IBeaconData;
import com.radiusnetworks.ibeacon.IBeaconDataNotifier;
import com.radiusnetworks.ibeacon.IBeaconManager;
import com.radiusnetworks.ibeacon.RangeNotifier;
import com.radiusnetworks.ibeacon.Region;
import com.radiusnetworks.ibeacon.client.DataProviderException;

public class RangingManager implements RangeNotifier, IBeaconDataNotifier {
	private HashMap<String, CallbackContext> regions = new HashMap<String, CallbackContext>();

	private IBeaconManager manager;

	public RangingManager(IBeaconManager manager) {
		this.manager = manager;
	}

	public void start(Region region, CallbackContext callbackContext)
			throws RemoteException {
		this.manager.startRangingBeaconsInRegion(region);
		this.regions.put(region.getUniqueId(), callbackContext);
	}

	public void stop(Region region) throws RemoteException {
		this.manager.stopRangingBeaconsInRegion(region);
		this.regions.remove(region.getUniqueId());
	}

	@Override
	public void didRangeBeaconsInRegion(Collection<IBeacon> beacons,
			Region region) {
		CallbackContext callbackContext = this.regions
				.get(region.getUniqueId());
		if (callbackContext == null) {
			return;
		}

		// TODO: Implement data: beacon.requestData(this);
		try {
			// TODO: Refactor, we shouldn't create JSON responses and/or use PluginResult here. In fact, we shouldn't even be using CallbackContext here
			PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, JsonHelper.listToJSONArray(beacons));
			pluginResult.setKeepCallback(true);
			callbackContext.sendPluginResult(pluginResult);
		} catch (JSONException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void iBeaconDataUpdate(IBeacon iBeacon, IBeaconData iBeaconData,
			DataProviderException e) {
		if (e != null) {
			// Exception occurred
			return;
		}
		
		if (iBeaconData != null) {
			// Perform action on iBeaconData (for example get() or set() or sync())
		}
	}
}