petermetz/cordova-plugin-ibeacon — pull request #9 by hkuiyo (2014-05-20 08:55:15+00:00)
Title: 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 myBeacons = new ArrayList();

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 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 regions = new HashMap();

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 regions = new HashMap();

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 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())
}
}
}