You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by fi...@apache.org on 2012/05/18 23:12:43 UTC

[5/9] android commit: [CB-463] rewrite of accel plugin

[CB-463] rewrite of accel plugin


Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/commit/4b97af08
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/tree/4b97af08
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/diff/4b97af08

Branch: refs/heads/463
Commit: 4b97af08471752f93ecc762c2dfd0ded0b081528
Parents: 0850229
Author: Fil Maj <ma...@gmail.com>
Authored: Mon May 14 13:00:11 2012 -0700
Committer: Fil Maj <ma...@gmail.com>
Committed: Thu May 17 11:38:14 2012 -0700

----------------------------------------------------------------------
 .../src/org/apache/cordova/AccelListener.java      |  392 ++++++++-------
 1 files changed, 203 insertions(+), 189 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/4b97af08/framework/src/org/apache/cordova/AccelListener.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/AccelListener.java b/framework/src/org/apache/cordova/AccelListener.java
index f751e4e..40ddec4 100755
--- a/framework/src/org/apache/cordova/AccelListener.java
+++ b/framework/src/org/apache/cordova/AccelListener.java
@@ -18,7 +18,11 @@
 */
 package org.apache.cordova;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.cordova.api.CordovaInterface;
 import org.apache.cordova.api.Plugin;
@@ -32,6 +36,8 @@ import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
+import android.location.Location;
+import android.util.Log;
 import android.content.Context;
 
 /**
@@ -40,20 +46,20 @@ import android.content.Context;
  */
 public class AccelListener extends Plugin implements SensorEventListener {
 
-	public static int STOPPED = 0;
-	public static int STARTING = 1;
+    public static int STOPPED = 0;
+    public static int STARTING = 1;
     public static int RUNNING = 2;
     public static int ERROR_FAILED_TO_START = 3;
     
-    public float TIMEOUT = 30000;		// Timeout in msec to shut off listener
-    
-    float x,y,z;						// most recent acceleration values
-    long timestamp;						// time of most recent value
-    int status;							// status of listener
-    long lastAccessTime;				// time the value was last retrieved
+    private float x,y,z;						        // most recent acceleration values
+    private long timestamp;					        // time of most recent value
+    private int status;							        // status of listener
 
-    private SensorManager sensorManager;// Sensor manager
-    Sensor mSensor;						// Acceleration sensor returned by sensor manager
+    private SensorManager sensorManager;    // Sensor manager
+    private Sensor mSensor;						      // Acceleration sensor returned by sensor manager
+    
+    private HashMap<String, String> watches = new HashMap<String, String>();
+    private List<String> callbacks = new ArrayList<String>();
 
     /**
      * Create an accelerometer listener.
@@ -66,169 +72,149 @@ public class AccelListener extends Plugin implements SensorEventListener {
         this.setStatus(AccelListener.STOPPED);
      }
     
-	/**
-	 * Sets the context of the Command. This can then be used to do things like
-	 * get file paths associated with the Activity.
-	 * 
-	 * @param ctx The context of the main Activity.
-	 */
-	public void setContext(CordovaInterface ctx) {
-		super.setContext(ctx);
+    /**
+     * Sets the context of the Command. This can then be used to do things like
+     * get file paths associated with the Activity.
+     * 
+     * @param ctx The context of the main Activity.
+     */
+    public void setContext(CordovaInterface ctx) {
+        super.setContext(ctx);
         this.sensorManager = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE);
-	}
+    }
 
-	/**
-	 * Executes the request and returns PluginResult.
-	 * 
-	 * @param action 		The action to execute.
-	 * @param args 			JSONArry of arguments for the plugin.
-	 * @param callbackId	The callback id used when calling back into JavaScript.
-	 * @return 				A PluginResult object with a status and message.
-	 */
-	public PluginResult execute(String action, JSONArray args, String callbackId) {
-		PluginResult.Status status = PluginResult.Status.OK;
-		String result = "";		
-		
-		try {
-			if (action.equals("getStatus")) {
-				int i = this.getStatus();
-				return new PluginResult(status, i);
-			}
-			else if (action.equals("start")) {
-				int i = this.start();
-				return new PluginResult(status, i);
-			}
-			else if (action.equals("stop")) {
-				this.stop();
-				return new PluginResult(status, 0);
-			}
-			else if (action.equals("getAcceleration")) {
-				// If not running, then this is an async call, so don't worry about waiting
-				if (this.status != AccelListener.RUNNING) {
-					int r = this.start();
-					if (r == AccelListener.ERROR_FAILED_TO_START) {
-						return new PluginResult(PluginResult.Status.IO_EXCEPTION, AccelListener.ERROR_FAILED_TO_START);
-					}
-					// Wait until running
-					long timeout = 2000;
-					while ((this.status == STARTING) && (timeout > 0)) {
-						timeout = timeout - 100;
-						try {
-							Thread.sleep(100);
-						} catch (InterruptedException e) {
-							e.printStackTrace();
-						}
-					}
-					if (timeout == 0) {
-						return new PluginResult(PluginResult.Status.IO_EXCEPTION, AccelListener.ERROR_FAILED_TO_START);						
-					}
-				}
-	            this.lastAccessTime = System.currentTimeMillis();
-				JSONObject r = new JSONObject();
-				r.put("x", this.x);
-				r.put("y", this.y);
-				r.put("z", this.z);
-				// TODO: Should timestamp be sent?
-				r.put("timestamp", this.timestamp);
-				return new PluginResult(status, r);
-			}
-			else if (action.equals("setTimeout")) {
-				try {
-					float timeout = Float.parseFloat(args.getString(0));
-					this.setTimeout(timeout);
-					return new PluginResult(status, 0);
-				} catch (NumberFormatException e) {
-					status = PluginResult.Status.INVALID_ACTION;
-					e.printStackTrace();
-				} catch (JSONException e) {
-					status = PluginResult.Status.JSON_EXCEPTION;
-					e.printStackTrace();
-				}
-			}
-			else if (action.equals("getTimeout")) {
-				float f = this.getTimeout();
-				return new PluginResult(status, f);
-			} else {
-        // Unsupported action
-        return new PluginResult(PluginResult.Status.INVALID_ACTION);
-      }
-			return new PluginResult(status, result);
-		} catch (JSONException e) {
-			return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
-		}
-	}
+    /**
+     * Executes the request and returns PluginResult.
+     * 
+     * @param action 		The action to execute.
+     * @param args 			JSONArry of arguments for the plugin.
+     * @param callbackId	The callback id used when calling back into JavaScript.
+     * @return 				A PluginResult object with a status and message.
+     */
+    public PluginResult execute(String action, JSONArray args, String callbackId) {
+    	PluginResult.Status status = PluginResult.Status.NO_RESULT;
+    	String message = "";
+    	PluginResult result = new PluginResult(status, message);
+    	result.setKeepCallback(true);	
+    	try {
+    		if (action.equals("getAcceleration")) {
+    			if (this.status != AccelListener.RUNNING) {
+    				// 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
+    				this.callbacks.add(callbackId);
+    				this.start();
+    			} else {
+    				return new PluginResult(PluginResult.Status.OK, this.getAccelerationJSON());
+    			}
+    		}
+    		else if (action.equals("addWatch")) {
+    			String watchId = args.getString(0);
+    			this.watches.put(watchId, callbackId);
+    			if (this.status != AccelListener.RUNNING) {
+    				this.start();
+    			}
+    		}
+    		else if (action.equals("clearWatch")) {
+    			String watchId = args.getString(0);
+    			if (this.watches.containsKey(watchId)) {
+    				this.watches.remove(watchId);
+    				if (this.size() == 0) {
+    					this.stop();
+    				}
+    			}
+    			return new PluginResult(PluginResult.Status.OK);
+    		} else {
+    			// Unsupported action
+    			return new PluginResult(PluginResult.Status.INVALID_ACTION);
+    		}
+    	} catch (JSONException e) {
+    		return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
+    	}
+    	return result;
+    }
 
-	/**
-	 * Identifies if action to be executed returns a value and should be run synchronously.
-	 * 
-	 * @param action	The action to execute
-	 * @return			T=returns value
-	 */
-	public boolean isSynch(String action) {
-		if (action.equals("getStatus")) {
-			return true;
-		}
-		else if (action.equals("getAcceleration")) {
-			// Can only return value if RUNNING
-			if (this.status == AccelListener.RUNNING) {
-				return true;
-			}
-		}
-		else if (action.equals("getTimeout")) {
-			return true;
-		}
-		return false;
-	}
+    /**
+     * Identifies if action to be executed returns a value and should be run synchronously.
+     * 
+     * @param action	The action to execute
+     * @return			T=returns value
+     */
+    public boolean isSynch(String action) {
+    	if (action.equals("getAcceleration") && this.status == AccelListener.RUNNING) {
+    		return true;
+    	} else if (action.equals("addWatch") && this.status == AccelListener.RUNNING) {
+        	return true;
+        } else if (action.equals("clearWatch")) {
+            return true;
+        }
+        return false;
+    }
     
     /**
      * Called by AccelBroker when listener is to be shut down.
      * Stop listener.
      */
     public void onDestroy() {
-    	this.stop();    	
+        this.stop();
     }
 
     //--------------------------------------------------------------------------
     // LOCAL METHODS
     //--------------------------------------------------------------------------
 
+    private int size() {
+    	return this.watches.size() + this.callbacks.size();
+    }
     /**
      * Start listening for acceleration sensor.
      * 
      * @return 			status of listener
      */
-    public int start() {
-
-		// If already starting or running, then just return
-        if ((this.status == AccelListener.RUNNING) || (this.status == AccelListener.STARTING)) {
-        	return this.status;
-        }
+    private int start() {
+    	// If already starting or running, then just return
+    	if ((this.status == AccelListener.RUNNING) || (this.status == AccelListener.STARTING)) {
+    		return this.status;
+    	}
+    	
+    	this.setStatus(AccelListener.STARTING);
+    	
+    	// Get accelerometer from sensor manager
+    	List<Sensor> list = this.sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
 
-        // Get accelerometer from sensor manager
-        List<Sensor> list = this.sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
-        
-        // If found, then register as listener
-        if ((list != null) && (list.size() > 0)) {
-            this.mSensor = list.get(0);
-            this.sensorManager.registerListener(this, this.mSensor, SensorManager.SENSOR_DELAY_FASTEST);
-            this.setStatus(AccelListener.STARTING);
-            this.lastAccessTime = System.currentTimeMillis();
-        }
-        
-        // If error, then set status to error
-        else {
-            this.setStatus(AccelListener.ERROR_FAILED_TO_START);
-        }
-        
-        return this.status;
+    	// If found, then register as listener
+    	if ((list != null) && (list.size() > 0)) {
+    		this.mSensor = list.get(0);
+    		this.sensorManager.registerListener(this, this.mSensor, SensorManager.SENSOR_DELAY_FASTEST);
+    		this.setStatus(AccelListener.STARTING);
+    	} else {
+    		this.setStatus(AccelListener.ERROR_FAILED_TO_START);
+    		this.fail(AccelListener.ERROR_FAILED_TO_START, "No sensors found to register accelerometer listening to.");
+    		return this.status;
+    	}
+    	
+    	// Wait until running
+    	long timeout = 2000;
+    	while ((this.status == STARTING) && (timeout > 0)) {
+    		timeout = timeout - 100;
+    		try {
+    			Thread.sleep(100);
+    		} catch (InterruptedException e) {
+    			e.printStackTrace();
+    		}
+    	}
+    	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;
     }
 
     /**
      * Stop listening to acceleration sensor.
      */
-    public void stop() {
+    private void stop() {
         if (this.status != AccelListener.STOPPED) {
-        	this.sensorManager.unregisterListener(this);
+            this.sensorManager.unregisterListener(this);
         }
         this.setStatus(AccelListener.STOPPED);
     }
@@ -248,64 +234,92 @@ public class AccelListener extends Plugin implements SensorEventListener {
      * @param SensorEvent event
      */
     public void onSensorChanged(SensorEvent event) {
-    	
-    	// Only look at accelerometer events
+        // Only look at accelerometer events
         if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) {
             return;
         }
         
         // If not running, then just return
         if (this.status == AccelListener.STOPPED) {
-        	return;
+            return;
         }
         
+        this.setStatus(AccelListener.RUNNING);
+        
         // Save time that event was received
         this.timestamp = System.currentTimeMillis();
         this.x = event.values[0];
         this.y = event.values[1];
-        this.z = event.values[2];            
+        this.z = event.values[2];
 
-        this.setStatus(AccelListener.RUNNING);
+        this.win();
+        
+        if (this.size() == 0) {
+        	this.stop();
+        }
+    }
 
-        // If values haven't been read for TIMEOUT time, then turn off accelerometer sensor to save power
-		if ((this.timestamp - this.lastAccessTime) > this.TIMEOUT) {
-			this.stop();
-		}		
+    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 (String callbackId: this.callbacks)
+        {
+        	this.error(err, callbackId);
+        }
+        this.callbacks.clear();
+        
+        err.setKeepCallback(true);
+        
+        Iterator it = this.watches.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry pairs = (Map.Entry)it.next();
+            this.error(err, (String)pairs.getValue());
+        }
+    }
+    
+    private void win() {
+    	// Success return object
+    	PluginResult result = new PluginResult(PluginResult.Status.OK, this.getAccelerationJSON());
+    	
+    	for (String callbackId: this.callbacks)
+        {
+        	this.success(result, callbackId);
+        }
+        this.callbacks.clear();
+        
+        result.setKeepCallback(true);
+        
+        Iterator it = this.watches.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry pairs = (Map.Entry)it.next();
+            this.success(result, (String)pairs.getValue());
+        }
     }
 
-    /**
-     * Get status of accelerometer sensor.
-     * 
-     * @return			status
-     */
-	public int getStatus() {
-		return this.status;
-	}
-		
-	/**
-	 * Set the timeout to turn off accelerometer sensor if getX() hasn't been called.
-	 * 
-	 * @param timeout		Timeout in msec.
-	 */
-	public void setTimeout(float timeout) {
-		this.TIMEOUT = timeout;
-	}
-	
-	/**
-	 * Get the timeout to turn off accelerometer sensor if getX() hasn't been called.
-	 * 
-	 * @return timeout in msec
-	 */
-	public float getTimeout() {
-		return this.TIMEOUT;
-	}
-	
-	/**
-	 * Set the status and send it to JavaScript.
-	 * @param status
-	 */
 	private void setStatus(int status) {
-		this.status = status;
+        this.status = status;
+    }
+	
+	private JSONObject getAccelerationJSON() {
+		JSONObject r = new JSONObject();
+		try {
+			r.put("x", this.x);
+			r.put("y", this.y);
+			r.put("z", this.z);
+			r.put("timestamp", this.timestamp);
+		} catch (JSONException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		return r;
 	}
-    
-}
+}
\ No newline at end of file