Port AccelListener to CordovaPlugin.

Also using the MessageQueue to handle the sensor start timeout, instead
of a Thread.sleep() loop. This allows the listener to run synchronously.
This commit is contained in:
Braden Shepherdson 2012-10-11 10:02:46 -04:00
parent 891f8d00cf
commit e1dea5b4d3

View File

@ -20,8 +20,9 @@ package org.apache.cordova;
import java.util.List; import java.util.List;
import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaInterface; import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.Plugin; import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.PluginResult; import org.apache.cordova.api.PluginResult;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
@ -33,11 +34,14 @@ import android.hardware.SensorEvent;
import android.hardware.SensorEventListener; import android.hardware.SensorEventListener;
import android.hardware.SensorManager; import android.hardware.SensorManager;
import android.os.Handler;
import android.os.Looper;
/** /**
* This class listens to the accelerometer sensor and stores the latest * This class listens to the accelerometer sensor and stores the latest
* acceleration values x,y,z. * acceleration values x,y,z.
*/ */
public class AccelListener extends Plugin implements SensorEventListener { public class AccelListener extends CordovaPlugin implements SensorEventListener {
public static int STOPPED = 0; public static int STOPPED = 0;
public static int STARTING = 1; public static int STARTING = 1;
@ -52,7 +56,7 @@ public class AccelListener extends Plugin implements SensorEventListener {
private SensorManager sensorManager; // Sensor manager private SensorManager sensorManager; // Sensor manager
private Sensor mSensor; // Acceleration sensor returned by sensor manager private Sensor mSensor; // Acceleration sensor returned by sensor manager
private String callbackId; // Keeps track of the single "start" callback ID passed in from JS private CallbackContext callbackContext; // Keeps track of the JS callback context.
/** /**
* Create an accelerometer listener. * Create an accelerometer listener.
@ -70,29 +74,25 @@ public class AccelListener extends Plugin implements SensorEventListener {
* get file paths associated with the Activity. * get file paths associated with the Activity.
* *
* @param cordova The context of the main Activity. * @param cordova The context of the main Activity.
* @param webView The associated CordovaWebView.
*/ */
@Override
public void setContext(CordovaInterface cordova) { public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.setContext(cordova); super.initialize(cordova, webView);
this.sensorManager = (SensorManager) cordova.getActivity().getSystemService(Context.SENSOR_SERVICE); this.sensorManager = (SensorManager) cordova.getActivity().getSystemService(Context.SENSOR_SERVICE);
} }
/** /**
* Executes the request and returns PluginResult. * Executes the request.
* *
* @param action The action to execute. * @param action The action to execute.
* @param args JSONArry of arguments for the plugin. * @param args The exec() arguments.
* @param callbackId The callback id used when calling back into JavaScript. * @param callbackId The callback id used when calling back into JavaScript.
* @return A PluginResult object with a status and message. * @return Whether the action was valid.
*/ */
public PluginResult execute(String action, JSONArray args, String callbackId) { public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
PluginResult.Status status = PluginResult.Status.NO_RESULT;
String message = "";
PluginResult result = new PluginResult(status, message);
result.setKeepCallback(true);
if (action.equals("start")) { if (action.equals("start")) {
this.callbackId = callbackId; this.callbackContext = callbackContext;
if (this.status != AccelListener.RUNNING) { if (this.status != AccelListener.RUNNING) {
// If not running, then this is an async call, so don't worry about waiting // If not running, then this is an async call, so don't worry about waiting
// We drop the callback onto our stack, call start, and let start and the sensor callback fire off the callback down the road // We drop the callback onto our stack, call start, and let start and the sensor callback fire off the callback down the road
@ -105,9 +105,13 @@ public class AccelListener extends Plugin implements SensorEventListener {
} }
} else { } else {
// Unsupported action // Unsupported action
return new PluginResult(PluginResult.Status.INVALID_ACTION); return false;
} }
return result;
PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT, "");
result.setKeepCallback(true);
callbackContext.sendPluginResult(result);
return true;
} }
/** /**
@ -148,21 +152,16 @@ public class AccelListener extends Plugin implements SensorEventListener {
this.fail(AccelListener.ERROR_FAILED_TO_START, "No sensors found to register accelerometer listening to."); this.fail(AccelListener.ERROR_FAILED_TO_START, "No sensors found to register accelerometer listening to.");
return this.status; return this.status;
} }
// Wait until running // Set a timeout callback on the main thread.
long timeout = 2000; Handler handler = new Handler(Looper.getMainLooper());
while ((this.status == STARTING) && (timeout > 0)) { handler.postDelayed(new Runnable() {
timeout = timeout - 100; @Override
try { public void run() {
Thread.sleep(100); AccelListener.this.timeout();
} catch (InterruptedException e) { }
e.printStackTrace(); }, 2000);
}
}
if (timeout == 0) {
this.setStatus(AccelListener.ERROR_FAILED_TO_START);
this.fail(AccelListener.ERROR_FAILED_TO_START, "Accelerometer could not be started.");
}
return this.status; return this.status;
} }
@ -177,6 +176,18 @@ public class AccelListener extends Plugin implements SensorEventListener {
this.accuracy = SensorManager.SENSOR_STATUS_UNRELIABLE; this.accuracy = SensorManager.SENSOR_STATUS_UNRELIABLE;
} }
/**
* Returns an error if the sensor hasn't started.
*
* Called two seconds after starting the listener.
*/
private void timeout() {
if (this.status == AccelListener.STARTING) {
this.setStatus(AccelListener.ERROR_FAILED_TO_START);
this.fail(AccelListener.ERROR_FAILED_TO_START, "Accelerometer could not be started.");
}
}
/** /**
* Called when the accuracy of the sensor has changed. * Called when the accuracy of the sensor has changed.
* *
@ -247,16 +258,14 @@ public class AccelListener extends Plugin implements SensorEventListener {
} }
PluginResult err = new PluginResult(PluginResult.Status.ERROR, errorObj); PluginResult err = new PluginResult(PluginResult.Status.ERROR, errorObj);
err.setKeepCallback(true); err.setKeepCallback(true);
callbackContext.sendPluginResult(err);
this.error(err, this.callbackId);
} }
private void win() { private void win() {
// Success return object // Success return object
PluginResult result = new PluginResult(PluginResult.Status.OK, this.getAccelerationJSON()); PluginResult result = new PluginResult(PluginResult.Status.OK, this.getAccelerationJSON());
result.setKeepCallback(true); result.setKeepCallback(true);
callbackContext.sendPluginResult(result);
this.success(result, this.callbackId);
} }
private void setStatus(int status) { private void setStatus(int status) {