You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by de...@apache.org on 2012/05/16 22:31:44 UTC
webworks commit: [CB-465] Refactor Accelerometer code for addWatch /
clearWatch.
Updated Branches:
refs/heads/465 3255ae8b1 -> b28459c1a
[CB-465] Refactor Accelerometer code for addWatch / clearWatch.
Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/commit/b28459c1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/tree/b28459c1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/diff/b28459c1
Branch: refs/heads/465
Commit: b28459c1a552b38b9f1027b6c7e6735a482fd082
Parents: 3255ae8
Author: Drew Walters <de...@apache.org>
Authored: Wed May 16 15:31:09 2012 -0500
Committer: Drew Walters <de...@apache.org>
Committed: Wed May 16 15:31:09 2012 -0500
----------------------------------------------------------------------
.../cordova/accelerometer/Accelerometer.java | 387 ++++++++-------
1 files changed, 210 insertions(+), 177 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/b28459c1/framework/ext/src/org/apache/cordova/accelerometer/Accelerometer.java
----------------------------------------------------------------------
diff --git a/framework/ext/src/org/apache/cordova/accelerometer/Accelerometer.java b/framework/ext/src/org/apache/cordova/accelerometer/Accelerometer.java
index 18de371..09e6aef 100644
--- a/framework/ext/src/org/apache/cordova/accelerometer/Accelerometer.java
+++ b/framework/ext/src/org/apache/cordova/accelerometer/Accelerometer.java
@@ -18,23 +18,24 @@
*/
package org.apache.cordova.accelerometer;
-import org.apache.cordova.api.Plugin;
-import org.apache.cordova.api.PluginResult;
-import org.apache.cordova.json4j.JSONArray;
-import org.apache.cordova.json4j.JSONException;
-import org.apache.cordova.json4j.JSONObject;
-import org.apache.cordova.util.Logger;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
import net.rim.device.api.system.AccelerometerData;
import net.rim.device.api.system.AccelerometerListener;
import net.rim.device.api.system.AccelerometerSensor;
import net.rim.device.api.system.Application;
-import java.util.Enumeration;
-import java.util.Vector;
-import java.util.Hashtable;
+import org.apache.cordova.api.Plugin;
+import org.apache.cordova.api.PluginResult;
+import org.apache.cordova.json4j.JSONArray;
+import org.apache.cordova.json4j.JSONException;
+import org.apache.cordova.json4j.JSONObject;
+import org.apache.cordova.util.Logger;
public class Accelerometer extends Plugin implements AccelerometerListener {
+ private static final String LOG_TAG = "Accelerometer: ";
private static final String ACTION_GET_ACCELERATION = "getAcceleration";
private static final String ACTION_ADD_WATCH = "addWatch";
@@ -53,57 +54,37 @@ public class Accelerometer extends Plugin implements AccelerometerListener {
// the single channel to the device sensor
private static AccelerometerSensor.Channel _rawDataChannel = null;
- private int status = STOPPED; // status of this listener
-
- private Hashtable watches = new Hashtable();
- private Vector callbacks = new Vector();
+ private int state = STOPPED; // state of this listener
+ private long initTime = 0;
- private short x, y, z;
- private long timestamp;
+ /**
+ * Hash of all the listeners created, keyed on callback ids.
+ */
+ private final Vector callbackIds = new Vector();
+ private final Hashtable watchIds = new Hashtable();
public PluginResult execute(String action, JSONArray args, String callbackId) {
-
- PluginResult result = null;
-
+ PluginResult result;
try {
if (!AccelerometerSensor.isSupported()) {
result = new PluginResult(
- PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION,
- "Accelerometer sensor not supported");
+ PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION,
+ "Accelerometer sensor not supported");
} else if (ACTION_GET_ACCELERATION.equals(action)) {
- if (this.status != RUNNING) {
- result = new PluginResult(PluginResult.Status.NO_RESULT);
- result.setKeepCallback(true);
- this.callbacks.addElement(callbackId);
- this.start();
- } else {
- result = new PluginResult(
- PluginResult.Status.OK,
- this.getAccelerationJSON());
- }
+ result = getAcceleration(callbackId);
} else if (ACTION_ADD_WATCH.equals(action)) {
String watchId = args.getString(0);
- this.watches.put(watchId, callbackId);
- if (this.status != RUNNING) {
- this.start();
- }
- result = new PluginResult(PluginResult.Status.NO_RESULT);
- result.setKeepCallback(true);
+ result = addWatch(watchId, callbackId);
} else if (ACTION_CLEAR_WATCH.equals(action)) {
String watchId = args.getString(0);
- if (this.watches.containsKey(watchId)) {
- this.watches.remove(watchId);
- if (this.size() == 0) {
- this.stop();
- }
- }
- result = new PluginResult(PluginResult.Status.OK);
+ result = clearWatch(watchId);
} else {
result = new PluginResult(PluginResult.Status.INVALID_ACTION,
"Accelerometer: Invalid action:" + action);
}
- } catch(JSONException e) {
- result = new PluginResult(PluginResult.Status.JSON_EXCEPTION);
+ } catch (JSONException e) {
+ result = new PluginResult(PluginResult.Status.JSON_EXCEPTION,
+ e.getMessage());
}
return result;
@@ -118,164 +99,158 @@ public class Accelerometer extends Plugin implements AccelerometerListener {
* @return T=returns value
*/
public boolean isSynch(String action) {
- if (action.equals("getAcceleration") && this.status == RUNNING) {
+ if (ACTION_GET_ACCELERATION.equals(action) && state == RUNNING) {
return true;
- } else if (action.equals("addWatch") && this.status == RUNNING) {
+ } else if (ACTION_ADD_WATCH.equals(action) && state == RUNNING) {
return true;
- } else if (action.equals("clearWatch")) {
+ } else if (ACTION_CLEAR_WATCH.equals(action)) {
return true;
}
return false;
}
/**
- * Opens a raw data channel to the accelerometer sensor.
- *
- * @return the AccelerometerSensor.Channel for the application
- */
- private static AccelerometerSensor.Channel getChannel() {
- // an application can only have one open channel
- if (_rawDataChannel == null || !_rawDataChannel.isOpen()) {
- _rawDataChannel = AccelerometerSensor
- .openRawDataChannel(Application.getApplication());
- Logger.log(Accelerometer.class.getName()
- + ": sensor channel opened");
- }
- return _rawDataChannel;
- }
-
- /**
- * Implements the AccelerometerListener method.
- *
+ * Implements the AccelerometerListener method. We listen for the purpose of
+ * closing the application's accelerometer sensor channel after timeout has
+ * been exceeded.
*/
-
public void onData(AccelerometerData accelData) {
- if (this.status == STOPPED) return;
-
- this.timestamp = accelData.getLastTimestamp();
- this.x = accelData.getLastXAcceleration();
- this.y = accelData.getLastYAcceleration();
- this.z = accelData.getLastZAcceleration();
-
- this.win();
+ short x = accelData.getLastXAcceleration();
+ short y = accelData.getLastYAcceleration();
+ short z = accelData.getLastZAcceleration();
- if (this.size() == 0) {
- this.stop();
+ // If any value is not zero, assume sensor is now active and set state.
+ if (state == STARTING && (x != 0 || y != 0 || z != 0)) {
+ state = RUNNING;
}
- }
- /**
- * Adds this listener to sensor channel.
- */
- private void start() {
- // If already started or starting, return.
- if (this.status == RUNNING || this.status == STARTING) return;
-
- this.status = STARTING;
-
- // open the sensor channel and register listener
- getChannel().setAccelerometerListener(this);
- Logger.log(this.getClass().getName() + ": sensor listener added");
-
- // Need to wait until sensor is active. Otherwise, first query will
- // return zeros for all values. Wait up to 2 seconds.
- int waittime = 2000;
- AccelerometerData accelData = null;
- while (waittime > 0) {
- accelData = getChannel().getAccelerometerData();
- // If any value is not zero, assume sensor is active and break out.
- if (accelData.getLastXAcceleration() != 0
- || accelData.getLastYAcceleration() != 0
- || accelData.getLastZAcceleration() != 0) {
- break;
- }
-
- // Sleep and give sensor more time to warm up.
- waittime -= 100;
+ if (state == RUNNING) {
+ // Send the new accelerometer data.
+ JSONObject accel = new JSONObject();
try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
+ accel.put("x", normalize(x));
+ accel.put("y", normalize(y));
+ accel.put("z", normalize(z));
+ accel.put("timestamp", accelData.getLastTimestamp());
+ sendResult(true,
+ new PluginResult(PluginResult.Status.OK, accel), true);
+ } catch (JSONException e) {
+ sendResult(false, new PluginResult(
+ PluginResult.Status.JSON_EXCEPTION, "JSONException:"
+ + e.getMessage()), false);
}
- }
-
- // Sensor failed to start.
- if (waittime == 0) {
+ } else if ((System.currentTimeMillis() - initTime) > 2000) {
+ // If the sensor does not become active within 2 seconds of
+ // the request to start it, fail out.
stop();
- this.status = ERROR_FAILED_TO_START;
- this.fail(this.status, "Accelerometer could not be started.");
- return;
+ state = ERROR_FAILED_TO_START;
+ JSONObject errorObj = new JSONObject();
+ try {
+ errorObj.put("code", ERROR_FAILED_TO_START);
+ errorObj.put("message", "Accelerometer could not be started.");
+ } catch (JSONException e) {
+ Logger.log(LOG_TAG
+ + "Failed to build JSON object for ERROR_FAILED_TO_START.");
+ }
+ sendResult(false, new PluginResult(PluginResult.Status.ERROR,
+ errorObj), false);
}
+ }
- this.status = RUNNING;
+ /**
+ * Called when Plugin is destroyed.
+ */
+ public void onDestroy() {
+ // Close out the call back IDs and stop.
+ sendResult(true, new PluginResult(PluginResult.Status.NO_RESULT), false);
}
/**
- * Stops accelerometer listener and closes the sensor channel.
+ * Adds a SystemListener to listen for changes to the battery state. The
+ * listener is only registered if one has not already been added.
*/
- private void stop() {
- // close the sensor channel
- if (_rawDataChannel != null && _rawDataChannel.isOpen()) {
- _rawDataChannel.close();
- Logger.log(this.getClass().getName() + ": sensor channel closed");
+ private int addListener() {
+ if (_rawDataChannel == null || !_rawDataChannel.isOpen()) {
+ _rawDataChannel = AccelerometerSensor
+ .openRawDataChannel(Application.getApplication());
+ Logger.log(LOG_TAG + "sensor channel opened");
+
+ initTime = System.currentTimeMillis();
+ state = STARTING;
+ _rawDataChannel.setAccelerometerListener(this);
+ Logger.log(LOG_TAG + "sensor listener added");
}
- this.status = STOPPED;
+ return state;
}
- private void fail(int code, String message) {
- // Error object
- JSONObject errorObj = new JSONObject();
- try {
- errorObj.put("code", code);
- errorObj.put("message", message);
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- PluginResult err = new PluginResult(PluginResult.Status.ERROR, errorObj);
-
- for (Enumeration e = this.callbacks.elements(); e.hasMoreElements();)
- {
- this.error(err, (String)e.nextElement());
- }
- this.callbacks.removeAllElements();
-
- err.setKeepCallback(true);
+ /**
+ * Track the specified watch ID and start the accelerometer channel if it
+ * hasn't been started.
+ *
+ * @param watchId
+ * @param callbackId
+ * @return
+ */
+ private synchronized PluginResult addWatch(String watchId, String callbackId) {
+ watchIds.put(watchId, callbackId);
+ addListener();
+ PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT,
+ "");
+ result.setKeepCallback(true);
- for (Enumeration e = this.watches.keys(); e.hasMoreElements();)
- {
- this.error(err, (String)this.watches.get((String)e.nextElement()));
- }
+ return result;
}
-
- private void win() {
- // Success return object
- PluginResult result = new PluginResult(PluginResult.Status.OK, this.getAccelerationJSON());
-
- for (Enumeration e = this.callbacks.elements(); e.hasMoreElements();)
- {
- this.success(result, (String)e.nextElement());
- }
- this.callbacks.removeAllElements();
- result.setKeepCallback(true);
-
- for (Enumeration e = this.watches.keys(); e.hasMoreElements();)
- {
- this.success(result, (String)this.watches.get((String)e.nextElement()));
+ /**
+ * Removes the specified watch ID and stops the accelerometer channel if
+ * this it was the last active listener.
+ *
+ * @param watchId
+ * @return
+ */
+ private synchronized PluginResult clearWatch(String watchId) {
+ if (watchIds.containsKey(watchId)) {
+ watchIds.remove(watchId);
+ if (watchIds.size() == 0 && callbackIds.size() == 0) {
+ stop();
+ }
}
+ return new PluginResult(PluginResult.Status.OK, "");
}
/**
- * Called when Plugin is destroyed.
+ * If the sensor is active, return the last acquired accelerometer data,
+ * otherwise start the sensor and listen for data.
+ *
+ * @return AccelerometerData with last acceleration data
*/
- public void onDestroy() {
- stop();
- }
+ private synchronized PluginResult getAcceleration(String callbackId) {
+ PluginResult result;
+
+ if (state != RUNNING) {
+ callbackIds.addElement(callbackId);
+ addListener();
+ result = new PluginResult(PluginResult.Status.NO_RESULT, "");
+ result.setKeepCallback(true);
+ } else {
+ // get the last acceleration
+ AccelerometerData accelData = _rawDataChannel
+ .getAccelerometerData();
+ JSONObject accel = new JSONObject();
+ try {
+ accel.put("x", normalize(accelData.getLastXAcceleration()));
+ accel.put("y", normalize(accelData.getLastYAcceleration()));
+ accel.put("z", normalize(accelData.getLastZAcceleration()));
+ accel.put("timestamp", accelData.getLastTimestamp());
+ result = new PluginResult(PluginResult.Status.OK, accel);
+ } catch (JSONException e) {
+ result = new PluginResult(PluginResult.Status.JSON_EXCEPTION,
+ "JSONException:" + e.getMessage());
+ }
+ }
- private int size() {
- return this.watches.size() + this.callbacks.size();
+ return result;
}
/**
@@ -303,15 +278,73 @@ public class Accelerometer extends Plugin implements AccelerometerListener {
return Double.parseDouble(buf.toString());
}
- private JSONObject getAccelerationJSON() {
- JSONObject accel = new JSONObject();
- try {
- accel.put("x", normalize(this.x));
- accel.put("y", normalize(this.y));
- accel.put("z", normalize(this.z));
- accel.put("timestamp", this.timestamp);
- } catch (JSONException e) {
+ /**
+ * Helper function to send a PluginResult to the saved call back IDs.
+ *
+ * @param issuccess
+ * true if this is a successful result, false otherwise.
+ * @param result
+ * the PluginResult to return
+ * @param keepCallback
+ * Boolean value indicating whether to keep the call back id
+ * active.
+ */
+ private synchronized void sendResult(boolean issuccess,
+ PluginResult result, boolean keepCallback) {
+
+ if (result != null) {
+ // Must keep the call back active for future watch events.
+ result.setKeepCallback(keepCallback);
+
+ // Iterate through the saved watch IDs.
+ for (Enumeration watches = watchIds.elements(); watches
+ .hasMoreElements();) {
+ if (issuccess) {
+ success(result, (String) watches.nextElement());
+ } else {
+ error(result, (String) watches.nextElement());
+ }
+ }
+
+ // callbackIds are from getAcceleration() requests so they are
+ // one time and should not keep callback.
+ result.setKeepCallback(false);
+
+ // Iterate through the saved call back IDs.
+ for (Enumeration callbacks = callbackIds.elements(); callbacks
+ .hasMoreElements();) {
+ if (issuccess) {
+ success(result, (String) callbacks.nextElement());
+ } else {
+ error(result, (String) callbacks.nextElement());
+ }
+ }
+ }
+
+ if (!keepCallback) {
+ watchIds.clear();
}
- return accel;
+ callbackIds.removeAllElements();
+
+ if (watchIds.size() == 0) {
+ stop();
+ }
+ }
+
+ /**
+ * Stops accelerometer listener and closes the sensor channel.
+ */
+ private synchronized void stop() {
+ if (_rawDataChannel != null && _rawDataChannel.isOpen()) {
+
+ // Remove the battery listener.
+ _rawDataChannel.removeAccelerometerListener();
+ _rawDataChannel.close();
+ _rawDataChannel = null;
+
+ Logger.log(LOG_TAG + "sensor channel closed");
+ }
+
+ state = STOPPED;
}
}