/*
This file was modified from or inspired by Apache Cordova.
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package com.polyvi.xface.extension;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import com.polyvi.xface.extension.XExtensionResult.Status;
public class XAccelerometerExt extends XExtension implements
SensorEventListener {
private final static int STOPPED = 0;
private final static int STARTING = 1;
private final static int RUNNING = 2;
private final static int ERROR_FAILED_TO_START = 3;
private final static String COMMAND_START = "start";
private final static String COMMAND_STOP = "stop";
private float mX, mY, mZ; // 最近一次获得的acceleration值
private long mTimestamp; // 最近一次获得的acceleration的时间戳
private int mStatus; // 监听器所处的状态
private int mAccuracy; // 获取到的数据的精度
private SensorManager mSensorManager; // 用于获得Acceleration sensor
private Sensor mSensor; // Acceleration sensor
private XCallbackContext mCallbackCtx;
public XAccelerometerExt() {
mX = 0;
mY = 0;
mZ = 0;
mTimestamp = 0;
mStatus = STOPPED;
mAccuracy = SensorManager.SENSOR_STATUS_UNRELIABLE;
}
@Override
public void sendAsyncResult(String result) {
}
@Override
public boolean isAsync(String action) {
return action.equals(COMMAND_START) && mStatus != RUNNING;
}
@Override
public XExtensionResult exec(String action,
JSONArray args, XCallbackContext callbackCtx) {
XExtensionResult.Status extensionStatus = Status.NO_RESULT;
mCallbackCtx = callbackCtx;
if (action.equals(COMMAND_START)) {
if (mStatus != RUNNING) {
start();
}
} else if (action.equals(COMMAND_STOP)) {
if (RUNNING == mStatus) {
stop();
}
extensionStatus = Status.OK;
} else {
extensionStatus = Status.INVALID_ACTION;
}
return new XExtensionResult(extensionStatus);
}
/**
* 开始监听accelerometer sensor
*/
private void start() {
if ((mStatus == RUNNING) || (mStatus == STARTING)) {
return;
}
mStatus = STARTING;
if (null == mSensorManager) {
mSensorManager = (SensorManager) getContext()
.getSystemService(Context.SENSOR_SERVICE);
}
List<Sensor> list = mSensorManager
.getSensorList(Sensor.TYPE_ACCELEROMETER);
if ((list != null) && (list.size() > 0)) {
mSensor = list.get(0);
mSensorManager.registerListener(this, mSensor,
SensorManager.SENSOR_DELAY_UI);
} else {
mStatus = ERROR_FAILED_TO_START;
mCallbackCtx.error("No sensors found to register accelerometer listening to.");
}
// Wait until running
long timeout = 2000;
while ((this.mStatus == STARTING) && (timeout > 0)) {
timeout = timeout - 100;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (timeout == 0) {
mStatus = ERROR_FAILED_TO_START;
mCallbackCtx.error("Accelerometer could not be started.");
}
}
/**
* 停止监听accelerometer sensor
*/
private void stop() {
if (STOPPED != mStatus && null != mSensorManager) {
mSensorManager.unregisterListener(this);
}
mStatus = STOPPED;
mAccuracy = SensorManager.SENSOR_STATUS_UNRELIABLE;
}
private void win() {
XExtensionResult result = new XExtensionResult(Status.OK,
getAccelerationJSON());
result.setKeepCallback(true);
mCallbackCtx.sendExtensionResult(result);
}
/**
* 获取json格式的重力感应数据
*/
private JSONObject getAccelerationJSON() {
JSONObject r = new JSONObject();
try {
r.put("x", mX);
r.put("y", mY);
r.put("z", mZ);
r.put("timestamp", mTimestamp);
} catch (JSONException e) {
e.printStackTrace();
}
return r;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// Only look at accelerometer events
if (sensor.getType() != Sensor.TYPE_ACCELEROMETER) {
return;
}
// If not running, then just return
if (mStatus == STOPPED) {
return;
}
mAccuracy = accuracy;
}
@Override
public void onSensorChanged(SensorEvent event) {
// Only look at accelerometer events
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) {
return;
}
// If not running, then just return
if (mStatus == STOPPED) {
return;
}
mStatus = RUNNING;
if (mAccuracy >= SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM) {
mTimestamp = System.currentTimeMillis();
mX = event.values[0];
mY = event.values[1];
mZ = event.values[2];
win();
}
}
@Override
public void destroy() {
stop();
super.destroy();
}
}