CB-8876 Rewrote wp8 impementation to be more stable
diff --git a/src/wp/Accelerometer.cs b/src/wp/Accelerometer.cs
index cba911c..33c5434 100644
--- a/src/wp/Accelerometer.cs
+++ b/src/wp/Accelerometer.cs
@@ -1,4 +1,4 @@
-/*
+/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -20,6 +20,7 @@
using Microsoft.Devices.Sensors;
using System.Globalization;
using System.Diagnostics;
+using System.Windows.Threading;
namespace WPCordovaClassLib.Cordova.Commands
{
@@ -28,47 +29,6 @@
/// </summary>
public class Accelerometer : BaseCommand
{
- #region AccelerometerOptions class
- /// <summary>
- /// Represents Accelerometer options.
- /// </summary>
- [DataContract]
- public class AccelerometerOptions
- {
- /// <summary>
- /// How often to retrieve the Acceleration in milliseconds
- /// </summary>
- [DataMember(IsRequired = false, Name = "frequency")]
- public int Frequency { get; set; }
-
- /// <summary>
- /// Watcher id
- /// </summary>
- [DataMember(IsRequired = false, Name = "id")]
- public string Id { get; set; }
-
- /// <summary>
- /// Creates options object with default parameters
- /// </summary>
- public AccelerometerOptions()
- {
- this.SetDefaultValues(new StreamingContext());
- }
-
- /// <summary>
- /// Initializes default values for class fields.
- /// Implemented in separate method because default constructor is not invoked during deserialization.
- /// </summary>
- /// <param name="context"></param>
- [OnDeserializing()]
- public void SetDefaultValues(StreamingContext context)
- {
- this.Frequency = 10000;
- }
- }
-
- #endregion
-
#region Status codes and Constants
public const int Stopped = 0;
@@ -90,23 +50,19 @@
/// <summary>
/// Accelerometer
/// </summary>
- private static Microsoft.Devices.Sensors.Accelerometer accelerometer = new Microsoft.Devices.Sensors.Accelerometer();
-
- private static DateTime StartOfEpoch = new DateTime(1970, 1, 1, 0, 0, 0);
-
- #endregion
+ private static readonly Windows.Devices.Sensors.Accelerometer accelerometer = Windows.Devices.Sensors.Accelerometer.GetDefault();
/// <summary>
- /// Sensor listener event
- /// </summary>
- private void accelerometer_CurrentValueChanged(object sender, SensorReadingEventArgs<AccelerometerReading> e)
- {
- this.SetStatus(Running);
+ /// Timer which is used to update
+ /// </summary>
+ private static Timer updateTimer;
- PluginResult result = new PluginResult(PluginResult.Status.OK, GetCurrentAccelerationFormatted());
- result.KeepCallback = true;
- DispatchCommandResult(result);
- }
+ /// <summary>
+ /// Callback Id to report acceleration result in watch mode
+ /// </summary>
+ private static string watchCallbackId;
+
+ #endregion
/// <summary>
/// Starts listening for acceleration sensor
@@ -114,56 +70,64 @@
/// <returns>status of listener</returns>
public void start(string options)
{
- if ((currentStatus == Running) || (currentStatus == Starting))
+ watchCallbackId = GetCallbackIdFromOptions(options);
+
+ if (currentStatus == Running)
{
return;
}
+
try
{
- lock (accelerometer)
- {
- accelerometer.CurrentValueChanged += accelerometer_CurrentValueChanged;
- accelerometer.Start();
- this.SetStatus(Starting);
- }
+ // we use 20ms as a minimum allowed update interval
+ int minReportInterval = Math.Max((int)accelerometer.MinimumReportInterval, 20);
- long timeout = 2000;
- while ((currentStatus == Starting) && (timeout > 0))
- {
- timeout = timeout - 100;
- Thread.Sleep(100);
- }
+ updateTimer = new Timer(ReportAccelerationValue, null, 0, minReportInterval);
+ this.SetStatus(Running);
- if (currentStatus != Running)
- {
- this.SetStatus(ErrorFailedToStart);
- DispatchCommandResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, ErrorFailedToStart));
- return;
- }
+ PluginResult result = new PluginResult(PluginResult.Status.OK, GetCurrentAccelerationFormatted());
+ result.KeepCallback = true;
+ DispatchCommandResult(result, watchCallbackId);
}
- catch (Exception)
+ catch (Exception ex)
{
this.SetStatus(ErrorFailedToStart);
- DispatchCommandResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, ErrorFailedToStart));
- return;
+ DispatchCommandResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, ErrorFailedToStart), watchCallbackId);
}
- PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
- result.KeepCallback = true;
- DispatchCommandResult(result);
}
public void stop(string options)
{
+ string callbackId = GetCallbackIdFromOptions(options);
+
if (currentStatus == Running)
{
- lock (accelerometer)
- {
- accelerometer.CurrentValueChanged -= accelerometer_CurrentValueChanged;
- accelerometer.Stop();
- this.SetStatus(Stopped);
- }
+ watchCallbackId = null;
+ updateTimer.Dispose();
+ this.SetStatus(Stopped);
}
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK));
+
+ DispatchCommandResult(new PluginResult(PluginResult.Status.OK), callbackId);
+ }
+
+ public void getCurrentAcceleration(string options)
+ {
+ string callbackId = GetCallbackIdFromOptions(options);
+
+ DispatchCommandResult(new PluginResult(PluginResult.Status.OK, GetCurrentAccelerationFormatted()), callbackId);
+ }
+
+ private void ReportAccelerationValue(object stateInfo)
+ {
+ if (String.IsNullOrEmpty(watchCallbackId)) {
+ // soemthing goes wrong, callback has been called after stop..
+ return;
+ }
+ string currentAccelerationFormatted = GetCurrentAccelerationFormatted();
+ var result = currentAccelerationFormatted == null ? new PluginResult(PluginResult.Status.NO_RESULT)
+ : new PluginResult(PluginResult.Status.OK, currentAccelerationFormatted);
+ result.KeepCallback = true;
+ DispatchCommandResult(result, watchCallbackId);
}
/// <summary>
@@ -172,15 +136,20 @@
/// <returns>Coordinates in JSON format</returns>
private string GetCurrentAccelerationFormatted()
{
- // convert to unix timestamp
- // long timestamp = ((accelerometer.CurrentValue.Timestamp.DateTime - StartOfEpoch).Ticks) / 10000;
- // Note: Removed timestamp, to let the JS side create it using (new Date().getTime()) -jm
- // this resolves an issue with inconsistencies between JS dates and Native DateTime
- string resultCoordinates = String.Format("\"x\":{0},\"y\":{1},\"z\":{2}",
- (accelerometer.CurrentValue.Acceleration.X * gConstant).ToString("0.00000", CultureInfo.InvariantCulture),
- (accelerometer.CurrentValue.Acceleration.Y * gConstant).ToString("0.00000", CultureInfo.InvariantCulture),
- (accelerometer.CurrentValue.Acceleration.Z * gConstant).ToString("0.00000", CultureInfo.InvariantCulture));
- return "{" + resultCoordinates + "}";
+ try
+ {
+ var currentReading = accelerometer.GetCurrentReading();
+ var currentCoordinates = String.Format("\"x\":{0},\"y\":{1},\"z\":{2}",
+ (currentReading.AccelerationX * gConstant).ToString("0.00000", CultureInfo.InvariantCulture),
+ (currentReading.AccelerationY * gConstant).ToString("0.00000", CultureInfo.InvariantCulture),
+ (currentReading.AccelerationZ * gConstant).ToString("0.00000", CultureInfo.InvariantCulture));
+
+ return "{" + currentCoordinates + "}";
+ }
+ catch
+ {
+ return null;
+ }
}
/// <summary>
@@ -191,6 +160,20 @@
{
currentStatus = status;
}
+
+ private string GetCallbackIdFromOptions(string options)
+ {
+ try
+ {
+ string[] optionsString = JSON.JsonHelper.Deserialize<string[]>(options);
+
+ return optionsString[0];
+ }
+ catch (Exception)
+ {
+ DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), this.CurrentCommandCallbackId);
+ return null;
+ }
+ }
}
}
-
diff --git a/www/accelerometer.js b/www/accelerometer.js
index b6e9f97..900899c 100644
--- a/www/accelerometer.js
+++ b/www/accelerometer.js
@@ -42,13 +42,13 @@
// Tells native to start.
function start() {
- exec(function(a) {
+ exec(function (a) {
var tempListeners = listeners.slice(0);
accel = new Acceleration(a.x, a.y, a.z, a.timestamp);
for (var i = 0, l = tempListeners.length; i < l; i++) {
tempListeners[i].win(accel);
}
- }, function(e) {
+ }, function (e) {
var tempListeners = listeners.slice(0);
for (var i = 0, l = tempListeners.length; i < l; i++) {
tempListeners[i].fail(e);
@@ -60,12 +60,13 @@
// Tells native to stop.
function stop() {
exec(null, null, "Accelerometer", "stop", []);
+ accel = null;
running = false;
}
// Adds a callback pair to the listeners array
function createCallbackPair(win, fail) {
- return {win:win, fail:fail};
+ return { win: win, fail: fail };
}
// Removes a win/fail listener pair from the listeners array
@@ -87,15 +88,26 @@
* @param {Function} errorCallback The function to call when there is an error getting the acceleration data. (OPTIONAL)
* @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL)
*/
- getCurrentAcceleration: function(successCallback, errorCallback, options) {
+ getCurrentAcceleration: function (successCallback, errorCallback, options) {
argscheck.checkArgs('fFO', 'accelerometer.getCurrentAcceleration', arguments);
+ if (cordova.platformId === "windowsphone") {
+ exec(function (a) {
+ accel = new Acceleration(a.x, a.y, a.z, a.timestamp);
+ successCallback(accel);
+ }, function (e) {
+ errorCallback(e);
+ }, "Accelerometer", "getCurrentAcceleration", []);
+
+ return;
+ }
+
var p;
- var win = function(a) {
+ var win = function (a) {
removeListeners(p);
successCallback(a);
};
- var fail = function(e) {
+ var fail = function (e) {
removeListeners(p);
errorCallback && errorCallback(e);
};
@@ -116,7 +128,7 @@
* @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL)
* @return String The watch id that must be passed to #clearWatch to stop watching.
*/
- watchAcceleration: function(successCallback, errorCallback, options) {
+ watchAcceleration: function (successCallback, errorCallback, options) {
argscheck.checkArgs('fFO', 'accelerometer.watchAcceleration', arguments);
// Default interval (10 sec)
var frequency = (options && options.frequency && typeof options.frequency == 'number') ? options.frequency : 10000;
@@ -124,19 +136,19 @@
// Keep reference to watch id, and report accel readings as often as defined in frequency
var id = utils.createUUID();
- var p = createCallbackPair(function(){}, function(e) {
+ var p = createCallbackPair(function () { }, function (e) {
removeListeners(p);
errorCallback && errorCallback(e);
});
listeners.push(p);
timers[id] = {
- timer:window.setInterval(function() {
+ timer: window.setInterval(function () {
if (accel) {
successCallback(accel);
}
}, frequency),
- listeners:p
+ listeners: p
};
if (running) {
@@ -157,7 +169,7 @@
*
* @param {String} id The id of the watch returned from #watchAcceleration.
*/
- clearWatch: function(id) {
+ clearWatch: function (id) {
// Stop javascript timer & remove from timer list
if (id && timers[id]) {
window.clearInterval(timers[id].timer);