1 | /*
|
2 | *
|
3 | * Licensed to the Apache Software Foundation (ASF) under one
|
4 | * or more contributor license agreements. See the NOTICE file
|
5 | * distributed with this work for additional information
|
6 | * regarding copyright ownership. The ASF licenses this file
|
7 | * to you under the Apache License, Version 2.0 (the
|
8 | * "License"); you may not use this file except in compliance
|
9 | * with the License. You may obtain a copy of the License at
|
10 | *
|
11 | * http://www.apache.org/licenses/LICENSE-2.0
|
12 | *
|
13 | * Unless required by applicable law or agreed to in writing,
|
14 | * software distributed under the License is distributed on an
|
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
16 | * KIND, either express or implied. See the License for the
|
17 | * specific language governing permissions and limitations
|
18 | * under the License.
|
19 | *
|
20 | */
|
21 |
|
22 | /**
|
23 | * This class provides access to device accelerometer data.
|
24 | * @constructor
|
25 | */
|
26 | var argscheck = require('cordova/argscheck'),
|
27 | utils = require("cordova/utils"),
|
28 | exec = require("cordova/exec"),
|
29 | Acceleration = require('./Acceleration');
|
30 |
|
31 | // Is the accel sensor running?
|
32 | var running = false;
|
33 |
|
34 | // Keeps reference to watchAcceleration calls.
|
35 | var timers = {};
|
36 |
|
37 | // Array of listeners; used to keep track of when we should call start and stop.
|
38 | var listeners = [];
|
39 |
|
40 | // Last returned acceleration object from native
|
41 | var accel = null;
|
42 |
|
43 | // Timer used when faking up devicemotion events
|
44 | var eventTimerId = null;
|
45 |
|
46 | // Tells native to start.
|
47 | function start() {
|
48 | exec(function (a) {
|
49 | var tempListeners = listeners.slice(0);
|
50 | accel = new Acceleration(a.x, a.y, a.z, a.timestamp);
|
51 | for (var i = 0, l = tempListeners.length; i < l; i++) {
|
52 | tempListeners[i].win(accel);
|
53 | }
|
54 | }, function (e) {
|
55 | var tempListeners = listeners.slice(0);
|
56 | for (var i = 0, l = tempListeners.length; i < l; i++) {
|
57 | tempListeners[i].fail(e);
|
58 | }
|
59 | }, "Accelerometer", "start", []);
|
60 | running = true;
|
61 | }
|
62 |
|
63 | // Tells native to stop.
|
64 | function stop() {
|
65 | exec(null, null, "Accelerometer", "stop", []);
|
66 | accel = null;
|
67 | running = false;
|
68 | }
|
69 |
|
70 | // Adds a callback pair to the listeners array
|
71 | function createCallbackPair(win, fail) {
|
72 | return { win: win, fail: fail };
|
73 | }
|
74 |
|
75 | // Removes a win/fail listener pair from the listeners array
|
76 | function removeListeners(l) {
|
77 | var idx = listeners.indexOf(l);
|
78 | if (idx > -1) {
|
79 | listeners.splice(idx, 1);
|
80 | if (listeners.length === 0) {
|
81 | stop();
|
82 | }
|
83 | }
|
84 | }
|
85 |
|
86 | var accelerometer = {
|
87 | /**
|
88 | * Asynchronously acquires the current acceleration.
|
89 | *
|
90 | * @param {Function} successCallback The function to call when the acceleration data is available
|
91 | * @param {Function} errorCallback The function to call when there is an error getting the acceleration data. (OPTIONAL)
|
92 | * @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL)
|
93 | */
|
94 | getCurrentAcceleration: function (successCallback, errorCallback, options) {
|
95 | argscheck.checkArgs('fFO', 'accelerometer.getCurrentAcceleration', arguments);
|
96 |
|
97 | if (cordova.platformId === "windowsphone") {
|
98 | exec(function (a) {
|
99 | accel = new Acceleration(a.x, a.y, a.z, a.timestamp);
|
100 | successCallback(accel);
|
101 | }, function (e) {
|
102 | errorCallback(e);
|
103 | }, "Accelerometer", "getCurrentAcceleration", []);
|
104 |
|
105 | return;
|
106 | }
|
107 |
|
108 | var p;
|
109 | var win = function (a) {
|
110 | removeListeners(p);
|
111 | successCallback(a);
|
112 | };
|
113 | var fail = function (e) {
|
114 | removeListeners(p);
|
115 | if (errorCallback) {
|
116 | errorCallback(e);
|
117 | }
|
118 | };
|
119 |
|
120 | p = createCallbackPair(win, fail);
|
121 | listeners.push(p);
|
122 |
|
123 | if (!running) {
|
124 | start();
|
125 | }
|
126 | },
|
127 |
|
128 | /**
|
129 | * Asynchronously acquires the acceleration repeatedly at a given interval.
|
130 | *
|
131 | * @param {Function} successCallback The function to call each time the acceleration data is available
|
132 | * @param {Function} errorCallback The function to call when there is an error getting the acceleration data. (OPTIONAL)
|
133 | * @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL)
|
134 | * @return String The watch id that must be passed to #clearWatch to stop watching.
|
135 | */
|
136 | watchAcceleration: function (successCallback, errorCallback, options) {
|
137 | argscheck.checkArgs('fFO', 'accelerometer.watchAcceleration', arguments);
|
138 | // Default interval (10 sec)
|
139 | var frequency = (options && options.frequency && typeof options.frequency == 'number') ? options.frequency : 10000;
|
140 |
|
141 | // Keep reference to watch id, and report accel readings as often as defined in frequency
|
142 | var id = utils.createUUID();
|
143 |
|
144 | var p = createCallbackPair(function () { }, function (e) {
|
145 | removeListeners(p);
|
146 | if (errorCallback) {
|
147 | errorCallback(e);
|
148 | }
|
149 | });
|
150 | listeners.push(p);
|
151 |
|
152 | timers[id] = {
|
153 | timer: window.setInterval(function () {
|
154 | if (accel) {
|
155 | successCallback(accel);
|
156 | }
|
157 | }, frequency),
|
158 | listeners: p
|
159 | };
|
160 |
|
161 | if (running) {
|
162 | // If we're already running then immediately invoke the success callback
|
163 | // but only if we have retrieved a value, sample code does not check for null ...
|
164 | if (accel) {
|
165 | successCallback(accel);
|
166 | }
|
167 | } else {
|
168 | start();
|
169 | }
|
170 |
|
171 | if (cordova.platformId === "browser" && !eventTimerId) {
|
172 | // Start firing devicemotion events if we haven't already
|
173 | var devicemotionEvent = new Event('devicemotion');
|
174 | eventTimerId = window.setInterval(function() {
|
175 | window.dispatchEvent(devicemotionEvent);
|
176 | }, 200);
|
177 | }
|
178 |
|
179 | return id;
|
180 | },
|
181 |
|
182 | /**
|
183 | * Clears the specified accelerometer watch.
|
184 | *
|
185 | * @param {String} id The id of the watch returned from #watchAcceleration.
|
186 | */
|
187 | clearWatch: function (id) {
|
188 | // Stop javascript timer & remove from timer list
|
189 | if (id && timers[id]) {
|
190 | window.clearInterval(timers[id].timer);
|
191 | removeListeners(timers[id].listeners);
|
192 | delete timers[id];
|
193 |
|
194 | if (eventTimerId && Object.keys(timers).length === 0) {
|
195 | // No more watchers, so stop firing 'devicemotion' events
|
196 | window.clearInterval(eventTimerId);
|
197 | eventTimerId = null;
|
198 | }
|
199 | }
|
200 | }
|
201 | };
|
202 | module.exports = accelerometer;
|