mirror of
https://github.com/apache/cordova-android.git
synced 2025-02-26 20:33:07 +08:00
Fix for Issue #228: Align Compass support with iOS
This commit is contained in:
parent
336a58ca5a
commit
821eb24a54
@ -9,6 +9,21 @@
|
|||||||
if (!PhoneGap.hasResource("compass")) {
|
if (!PhoneGap.hasResource("compass")) {
|
||||||
PhoneGap.addResource("compass");
|
PhoneGap.addResource("compass");
|
||||||
|
|
||||||
|
CompassError = function(){
|
||||||
|
this.code = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Capture error codes
|
||||||
|
CompassError.COMPASS_INTERNAL_ERR = 0;
|
||||||
|
CompassError.COMPASS_NOT_SUPPORTED = 20;
|
||||||
|
|
||||||
|
CompassHeading = function() {
|
||||||
|
this.magneticHeading = null;
|
||||||
|
this.trueHeading = null;
|
||||||
|
this.headingAccuracy = null;
|
||||||
|
this.timestamp = null;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class provides access to device Compass data.
|
* This class provides access to device Compass data.
|
||||||
* @constructor
|
* @constructor
|
||||||
@ -111,6 +126,14 @@ Compass.prototype.clearWatch = function(id) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Compass.prototype._castDate = function(pluginResult) {
|
||||||
|
if (pluginResult.message.timestamp) {
|
||||||
|
var timestamp = new Date(pluginResult.message.timestamp);
|
||||||
|
pluginResult.message.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
return pluginResult;
|
||||||
|
};
|
||||||
|
|
||||||
PhoneGap.addConstructor(function() {
|
PhoneGap.addConstructor(function() {
|
||||||
if (typeof navigator.compass === "undefined") {
|
if (typeof navigator.compass === "undefined") {
|
||||||
navigator.compass = new Compass();
|
navigator.compass = new Compass();
|
||||||
|
@ -11,6 +11,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import com.phonegap.api.PhonegapActivity;
|
import com.phonegap.api.PhonegapActivity;
|
||||||
import com.phonegap.api.Plugin;
|
import com.phonegap.api.Plugin;
|
||||||
@ -27,129 +28,130 @@ import android.content.Context;
|
|||||||
*/
|
*/
|
||||||
public class CompassListener extends Plugin implements SensorEventListener {
|
public class CompassListener extends Plugin implements SensorEventListener {
|
||||||
|
|
||||||
public static int STOPPED = 0;
|
public static int STOPPED = 0;
|
||||||
public static int STARTING = 1;
|
public static int STARTING = 1;
|
||||||
public static int RUNNING = 2;
|
public static int RUNNING = 2;
|
||||||
public static int ERROR_FAILED_TO_START = 3;
|
public static int ERROR_FAILED_TO_START = 3;
|
||||||
|
|
||||||
public long TIMEOUT = 30000; // Timeout in msec to shut off listener
|
public long TIMEOUT = 30000; // Timeout in msec to shut off listener
|
||||||
|
|
||||||
int status; // status of listener
|
int status; // status of listener
|
||||||
float heading; // most recent heading value
|
float heading; // most recent heading value
|
||||||
long timeStamp; // time of most recent value
|
long timeStamp; // time of most recent value
|
||||||
long lastAccessTime; // time the value was last retrieved
|
long lastAccessTime; // time the value was last retrieved
|
||||||
|
int accuracy; // accuracy of the sensor
|
||||||
|
|
||||||
private SensorManager sensorManager;// Sensor manager
|
private SensorManager sensorManager;// Sensor manager
|
||||||
Sensor mSensor; // Compass sensor returned by sensor manager
|
Sensor mSensor; // Compass sensor returned by sensor manager
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
public CompassListener() {
|
public CompassListener() {
|
||||||
this.timeStamp = 0;
|
this.timeStamp = 0;
|
||||||
this.setStatus(CompassListener.STOPPED);
|
this.setStatus(CompassListener.STOPPED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the context of the Command. This can then be used to do things like
|
* Sets the context of the Command. This can then be used to do things like
|
||||||
* get file paths associated with the Activity.
|
* get file paths associated with the Activity.
|
||||||
*
|
*
|
||||||
* @param ctx The context of the main Activity.
|
* @param ctx The context of the main Activity.
|
||||||
*/
|
*/
|
||||||
public void setContext(PhonegapActivity ctx) {
|
public void setContext(PhonegapActivity ctx) {
|
||||||
super.setContext(ctx);
|
super.setContext(ctx);
|
||||||
this.sensorManager = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE);
|
this.sensorManager = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes the request and returns PluginResult.
|
* Executes the request and returns PluginResult.
|
||||||
*
|
*
|
||||||
* @param action The action to execute.
|
* @param action The action to execute.
|
||||||
* @param args JSONArry of arguments for the plugin.
|
* @param args JSONArry of arguments for the plugin.
|
||||||
* @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 A PluginResult object with a status and message.
|
||||||
*/
|
*/
|
||||||
public PluginResult execute(String action, JSONArray args, String callbackId) {
|
public PluginResult execute(String action, JSONArray args, String callbackId) {
|
||||||
PluginResult.Status status = PluginResult.Status.OK;
|
PluginResult.Status status = PluginResult.Status.OK;
|
||||||
String result = "";
|
String result = "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (action.equals("start")) {
|
if (action.equals("start")) {
|
||||||
this.start();
|
this.start();
|
||||||
}
|
}
|
||||||
else if (action.equals("stop")) {
|
else if (action.equals("stop")) {
|
||||||
this.stop();
|
this.stop();
|
||||||
}
|
}
|
||||||
else if (action.equals("getStatus")) {
|
else if (action.equals("getStatus")) {
|
||||||
int i = this.getStatus();
|
int i = this.getStatus();
|
||||||
return new PluginResult(status, i);
|
return new PluginResult(status, i);
|
||||||
}
|
}
|
||||||
else if (action.equals("getHeading")) {
|
else if (action.equals("getHeading")) {
|
||||||
// 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
|
||||||
if (this.status != RUNNING) {
|
if (this.status != RUNNING) {
|
||||||
int r = this.start();
|
int r = this.start();
|
||||||
if (r == ERROR_FAILED_TO_START) {
|
if (r == ERROR_FAILED_TO_START) {
|
||||||
return new PluginResult(PluginResult.Status.IO_EXCEPTION, ERROR_FAILED_TO_START);
|
return new PluginResult(PluginResult.Status.IO_EXCEPTION, ERROR_FAILED_TO_START);
|
||||||
}
|
}
|
||||||
// Wait until running
|
// Wait until running
|
||||||
long timeout = 2000;
|
long timeout = 2000;
|
||||||
while ((this.status == STARTING) && (timeout > 0)) {
|
while ((this.status == STARTING) && (timeout > 0)) {
|
||||||
timeout = timeout - 100;
|
timeout = timeout - 100;
|
||||||
try {
|
try {
|
||||||
Thread.sleep(100);
|
Thread.sleep(100);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (timeout == 0) {
|
if (timeout == 0) {
|
||||||
return new PluginResult(PluginResult.Status.IO_EXCEPTION, AccelListener.ERROR_FAILED_TO_START);
|
return new PluginResult(PluginResult.Status.IO_EXCEPTION, AccelListener.ERROR_FAILED_TO_START);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float f = this.getHeading();
|
//float f = this.getHeading();
|
||||||
return new PluginResult(status, f);
|
return new PluginResult(status, getCompassHeading(), "navigator.compass._castDate");
|
||||||
}
|
}
|
||||||
else if (action.equals("setTimeout")) {
|
else if (action.equals("setTimeout")) {
|
||||||
this.setTimeout(args.getLong(0));
|
this.setTimeout(args.getLong(0));
|
||||||
}
|
}
|
||||||
else if (action.equals("getTimeout")) {
|
else if (action.equals("getTimeout")) {
|
||||||
long l = this.getTimeout();
|
long l = this.getTimeout();
|
||||||
return new PluginResult(status, l);
|
return new PluginResult(status, l);
|
||||||
}
|
}
|
||||||
return new PluginResult(status, result);
|
return new PluginResult(status, result);
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
|
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identifies if action to be executed returns a value and should be run synchronously.
|
* Identifies if action to be executed returns a value and should be run synchronously.
|
||||||
*
|
*
|
||||||
* @param action The action to execute
|
* @param action The action to execute
|
||||||
* @return T=returns value
|
* @return T=returns value
|
||||||
*/
|
*/
|
||||||
public boolean isSynch(String action) {
|
public boolean isSynch(String action) {
|
||||||
if (action.equals("getStatus")) {
|
if (action.equals("getStatus")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (action.equals("getHeading")) {
|
else if (action.equals("getHeading")) {
|
||||||
// Can only return value if RUNNING
|
// Can only return value if RUNNING
|
||||||
if (this.status == RUNNING) {
|
if (this.status == RUNNING) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (action.equals("getTimeout")) {
|
else if (action.equals("getTimeout")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when listener is to be shut down and object is being destroyed.
|
* Called when listener is to be shut down and object is being destroyed.
|
||||||
*/
|
*/
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
this.stop();
|
this.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
// LOCAL METHODS
|
// LOCAL METHODS
|
||||||
@ -158,113 +160,135 @@ public class CompassListener extends Plugin implements SensorEventListener {
|
|||||||
/**
|
/**
|
||||||
* Start listening for compass sensor.
|
* Start listening for compass sensor.
|
||||||
*
|
*
|
||||||
* @return status of listener
|
* @return status of listener
|
||||||
*/
|
*/
|
||||||
public int start() {
|
public int start() {
|
||||||
|
|
||||||
// If already starting or running, then just return
|
// If already starting or running, then just return
|
||||||
if ((this.status == CompassListener.RUNNING) || (this.status == CompassListener.STARTING)) {
|
if ((this.status == CompassListener.RUNNING) || (this.status == CompassListener.STARTING)) {
|
||||||
return this.status;
|
return this.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get accelerometer from sensor manager
|
// Get accelerometer from sensor manager
|
||||||
List<Sensor> list = this.sensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
|
List<Sensor> list = this.sensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
|
||||||
|
|
||||||
// If found, then register as listener
|
// If found, then register as listener
|
||||||
if (list.size() > 0) {
|
if (list.size() > 0) {
|
||||||
this.mSensor = list.get(0);
|
this.mSensor = list.get(0);
|
||||||
this.sensorManager.registerListener(this, this.mSensor, SensorManager.SENSOR_DELAY_NORMAL);
|
this.sensorManager.registerListener(this, this.mSensor, SensorManager.SENSOR_DELAY_NORMAL);
|
||||||
this.lastAccessTime = System.currentTimeMillis();
|
this.lastAccessTime = System.currentTimeMillis();
|
||||||
this.setStatus(CompassListener.STARTING);
|
this.setStatus(CompassListener.STARTING);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If error, then set status to error
|
// If error, then set status to error
|
||||||
else {
|
else {
|
||||||
this.setStatus(CompassListener.ERROR_FAILED_TO_START);
|
this.setStatus(CompassListener.ERROR_FAILED_TO_START);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.status;
|
return this.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop listening to compass sensor.
|
* Stop listening to compass sensor.
|
||||||
*/
|
*/
|
||||||
public void stop() {
|
public void stop() {
|
||||||
if (this.status != CompassListener.STOPPED) {
|
if (this.status != CompassListener.STOPPED) {
|
||||||
this.sensorManager.unregisterListener(this);
|
this.sensorManager.unregisterListener(this);
|
||||||
}
|
}
|
||||||
this.setStatus(CompassListener.STOPPED);
|
this.setStatus(CompassListener.STOPPED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sensor listener event.
|
* Sensor listener event.
|
||||||
*
|
*
|
||||||
* @param SensorEvent event
|
* @param SensorEvent event
|
||||||
*/
|
*/
|
||||||
public void onSensorChanged(SensorEvent event) {
|
public void onSensorChanged(SensorEvent event) {
|
||||||
|
|
||||||
// We only care about the orientation as far as it refers to Magnetic North
|
// We only care about the orientation as far as it refers to Magnetic North
|
||||||
float heading = event.values[0];
|
float heading = event.values[0];
|
||||||
|
|
||||||
// Save heading
|
// Save heading
|
||||||
this.timeStamp = System.currentTimeMillis();
|
this.timeStamp = System.currentTimeMillis();
|
||||||
this.heading = heading;
|
this.heading = heading;
|
||||||
this.setStatus(CompassListener.RUNNING);
|
this.setStatus(CompassListener.RUNNING);
|
||||||
|
|
||||||
// If heading hasn't been read for TIMEOUT time, then turn off compass sensor to save power
|
// If heading hasn't been read for TIMEOUT time, then turn off compass sensor to save power
|
||||||
if ((this.timeStamp - this.lastAccessTime) > this.TIMEOUT) {
|
if ((this.timeStamp - this.lastAccessTime) > this.TIMEOUT) {
|
||||||
this.stop();
|
this.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get status of compass sensor.
|
* Get status of compass sensor.
|
||||||
*
|
*
|
||||||
* @return status
|
* @return status
|
||||||
*/
|
*/
|
||||||
public int getStatus() {
|
public int getStatus() {
|
||||||
return this.status;
|
return this.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the most recent compass heading.
|
* Get the most recent compass heading.
|
||||||
*
|
*
|
||||||
* @return heading
|
* @return heading
|
||||||
*/
|
*/
|
||||||
public float getHeading() {
|
public float getHeading() {
|
||||||
this.lastAccessTime = System.currentTimeMillis();
|
this.lastAccessTime = System.currentTimeMillis();
|
||||||
return this.heading;
|
return this.heading;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the timeout to turn off compass sensor if getHeading() hasn't been called.
|
* Set the timeout to turn off compass sensor if getHeading() hasn't been called.
|
||||||
*
|
*
|
||||||
* @param timeout Timeout in msec.
|
* @param timeout Timeout in msec.
|
||||||
*/
|
*/
|
||||||
public void setTimeout(long timeout) {
|
public void setTimeout(long timeout) {
|
||||||
this.TIMEOUT = timeout;
|
this.TIMEOUT = timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the timeout to turn off compass sensor if getHeading() hasn't been called.
|
* Get the timeout to turn off compass sensor if getHeading() hasn't been called.
|
||||||
*
|
*
|
||||||
* @return timeout in msec
|
* @return timeout in msec
|
||||||
*/
|
*/
|
||||||
public long getTimeout() {
|
public long getTimeout() {
|
||||||
return this.TIMEOUT;
|
return this.TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the status and send it to JavaScript.
|
* Set the status and send it to JavaScript.
|
||||||
* @param status
|
* @param status
|
||||||
*/
|
*/
|
||||||
private void setStatus(int status) {
|
private void setStatus(int status) {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the CompassHeading JSON object to be returned to JavaScript
|
||||||
|
*
|
||||||
|
* @return a compass heading
|
||||||
|
*/
|
||||||
|
private JSONObject getCompassHeading() {
|
||||||
|
JSONObject obj = new JSONObject();
|
||||||
|
|
||||||
|
try {
|
||||||
|
obj.put("magneticHeading", this.getHeading());
|
||||||
|
obj.put("trueHeading", this.getHeading());
|
||||||
|
// Since the magnetic and true heading are always the same our and accuracy
|
||||||
|
// is defined as the difference between true and magnetic always return zero
|
||||||
|
obj.put("headingAccuracy", 0);
|
||||||
|
obj.put("timestamp", this.timeStamp);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
// Should never happen
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user