Question

I'm trying to write a Cordova plugin which interacts with the Radius Networks iBeacon library for Android. Now, I'm aware the library is designed for use with an Activity/Service but that isn't going to work in my situation, so I'm trying to adapt it as best I can with the documentation. At the moment, I'm just trying to get it to dump out the number of iBeacons it can see.

Here is my plugin code, I've omitted the package/imports for brevity:

public class IBeaconPlugin extends CordovaPlugin implements IBeaconConsumer {

    public static final String TAG = IBeaconPlugin.class.getName();

    public static final String ACTION_FIND = "findBeacons";

    private int count = -1;

    public Context context;

    private IBeaconManager iBeaconManager;

    /**
     * Constructor.
     */
    public IBeaconPlugin() {
    }

    /**
     * Sets the context of the Command. This can then be used to do things like
     * get file paths associated with the Activity.
     *
     * @param cordova The context of the main Activity.
     * @param webView The CordovaWebView Cordova is running in.
     */
    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
        super.initialize(cordova, webView);

        context = cordova.getActivity().getApplicationContext();

        iBeaconManager = IBeaconManager.getInstanceForApplication(context);
        Log.d(TAG, iBeaconManager.toString());

        iBeaconManager.bind(this);
    }

    @Override
    public Context getApplicationContext() {
        return context;
    }

    @Override
    public boolean bindService(Intent arg0, ServiceConnection arg1, int arg2) {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public void unbindService(ServiceConnection arg0) {
        // TODO Auto-generated method stub

    }

    /**
     * Executes the request and returns PluginResult.
     *
     * @param action            The action to execute.
     * @param args              JSONArry of arguments for the plugin.
     * @param callbackContext   The callback id used when calling back into JavaScript.
     * @return                  True if the action was valid, false if not.
     */
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        if (action.equals(ACTION_FIND)) {
            JSONObject r = new JSONObject();
            r.put("thebeacons", this.count);
            callbackContext.success(r);
        }
        else {
            return false;
        }
        return true;
    }

    @Override
    public void onIBeaconServiceConnect() {
        Log.d(TAG, "onIBeaconServiceConnect called");

        iBeaconManager.setRangeNotifier(new RangeNotifier() {
        @Override
        public void didRangeBeaconsInRegion(Collection<IBeacon> iBeacons, Region region) {
            IBeaconPlugin.this.count = iBeacons.size();
        }
        });

        try {
            iBeaconManager.startRangingBeaconsInRegion(new Region("allTheBeacons", null, null, null));
        } catch (RemoteException e) {   }
    }
}

As you can see, I've tried to input some logging so I've got an idea of flow. From this, I can determine that "onIBeaconServiceConnect" is never called. Looking in the logs, I have the following line which I think is the culprit:

D/IBeaconManager﹕ This consumer is not bound. binding: com.thenathanjones.cordova.ibeacon.IBeaconPlugin@52962c9c

Unfortunately, that's all the information I get.

Does anyone have any experience with the API to help me determine what the cause may be?

Cheers, Nathan

Was it helpful?

Solution

Your empty bindService and unbindService methods are causing you problems. If your class were an Activity, Service or Application, these would all be implemented for you. If you want to make a custom class you have to provide an implementation.

Without an implementation for the bindService method, the iBeaconManager.bind(this); line ends up accomplishing nothing, because it in turn has to call one of these methods. (Add log lines to those empty methods and you will see.) As a result, the IBeaconService never starts up and onIBeaconServiceConnect never gets called.

Enough boring explanation -- it's time for a solution! The easiest thing to do is to chain these methods. Try something like:

@Override
public boolean bindService(Intent intent, ServiceConnection conn, int mode) {
    return context.bindService(intent, conn, mode);
}

@Override
public void unbindService(ServiceConnection conn) {
    context.unbindService(conn);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top