有人能帮助我顺利完成传感器事件吗?
我正在尝试使用Sony Smart Watch 2的加速度计数据来动画在Android设备的屏幕上挥动的旗帜。 使用索尼的传感器控制示例代码作为起点,我得到了一个很好的工作设置。但只有约5-6秒!然后传感器数据开始以团块形式进入,弄乱了我的动画。试图找到罪魁祸首,我已经削减了我的智能手表代码,这是非常必要的:
监听器只记录自上次sensorevent以来的毫秒数:
private final AccessorySensorEventListener timeListener = new AccessorySensorEventListener() {
long lastTime = 0;
@Override
public void onSensorEvent(AccessorySensorEvent event) {
Log.i(TAG, "SmartWatch - onSensorEvent: " + (System.currentTimeMillis()-lastTime));
lastTime = System.currentTimeMillis();
}
};
此听众的注册
SW2SensorsControl(final String hostAppPackageName, final Context context) {
super(context, hostAppPackageName);
AccessorySensorManager manager = new AccessorySensorManager(context, hostAppPackageName);
if (DeviceInfoHelper.isSensorSupported(context, hostAppPackageName, SensorTypeValue.ACCELEROMETER)) {
accelerometer = manager.getSensor(SensorTypeValue.ACCELEROMETER);
}
if(accelerometer!=null) {
try {
accelerometer.registerFixedRateListener(timeListener, com.sonyericsson.extras.liveware.aef.sensor.Sensor.SensorRates.SENSOR_DELAY_NORMAL);
} catch (AccessorySensorException e) {
Log.d(TAG, "Failed to register listener", e);
}
}
}
运行代码,我看到sensorevents流入精细介于10到70毫秒之间。但是大约6秒后,我开始看到打嗝:200毫秒,然后他们试图“赶上”,我得到5分钟的读数。在此之后,它运行良好几秒钟,然后我看到另一个打嗝:500~100毫秒,并再次一些快速的“追赶”事件。 - 这个方案重复并且变得更频繁,直到几秒钟之后,流完全陷入困境。 我已经在A三星Galaxy S5,Nexus-4和Nexus-5上进行了测试,所以它不是特定于设备的,尽管在SG5上,logcat被称为“ServiceKeeper”的东西发送垃圾邮件显然是一些系统进程。这是一个450毫秒的打嗝的例子,接着是短暂的“追赶”:
06-30 11:47:23.208: I/SW2SensorsControl(5173): SmartWatch - onSensorEvent: 450
06-30 11:47:23.208: I/ServiceKeeper(857): In getappinfo pid = 857 pkgName = android appinfo = null
06-30 11:47:23.208: I/ServiceKeeper(857): In getseinfo pid = 857 uid = 1000 seinfo= system
06-30 11:47:23.218: I/ServiceKeeper(857): In getappinfo pid = 857 pkgName = android appinfo = null
06-30 11:47:23.218: I/ServiceKeeper(857): In getseinfo pid = 857 uid = 1000 seinfo= system
06-30 11:47:23.218: I/SW2SensorsControl(5173): SmartWatch - onSensorEvent: 9
06-30 11:47:23.218: I/ServiceKeeper(857): In getappinfo pid = 857 pkgName = android appinfo = null
06-30 11:47:23.218: I/ServiceKeeper(857): In getseinfo pid = 857 uid = 1000 seinfo= system
06-30 11:47:23.228: I/ServiceKeeper(857): In getappinfo pid = 857 pkgName = android appinfo = null
06-30 11:47:23.228: I/ServiceKeeper(857): In getseinfo pid = 857 uid = 1000 seinfo= system
06-30 11:47:23.228: I/SW2SensorsControl(5173): SmartWatch - onSensorEvent: 9
06-30 11:47:23.228: I/ServiceKeeper(857): In getappinfo pid = 857 pkgName = android appinfo = null
06-30 11:47:23.228: I/ServiceKeeper(857): In getseinfo pid = 857 uid = 1000 seinfo= system
06-30 11:47:23.228: I/ServiceKeeper(857): In getappinfo pid = 857 pkgName = android appinfo = null
06-30 11:47:23.228: I/SW2SensorsControl(5173): SmartWatch - onSensorEvent: 3
06-30 11:47:23.228: I/ServiceKeeper(857): In getseinfo pid = 857 uid = 1000 seinfo= system
06-30 11:47:23.238: I/ServiceKeeper(857): In getappinfo pid = 857 pkgName = android appinfo = null
06-30 11:47:23.238: I/ServiceKeeper(857): In getseinfo pid = 857 uid = 1000 seinfo= system
06-30 11:47:23.238: I/ServiceKeeper(857): In getappinfo pid = 857 pkgName = android appinfo = null
06-30 11:47:23.238: I/ServiceKeeper(857): In getseinfo pid = 857 uid = 1000 seinfo= system
正如你所看到的,这里的听众没有做任何工作 - 除了记录时间 - 但是当动画我的旗帜时,打嗝开始更快进入(因为还有更多的事情发生)。这就像传感器事件线程正在被预先设定,并且事件在场景后排队,或者可能是未读取的蓝牙接收缓冲区。当我使用替代
accelerometer.registerInterruptListener(timeListener);
事件流更快,打嗝变得更糟! 任何人都能告诉我这是否可以解决?这是我的代码,是Android还是索尼?
此致
编辑:
传感器事件中的时间戳本身并不显示“追赶”行为,而是以39-41ms的稳定速率继续(时间戳以纳秒为单位 - 为什么?)。还有奇怪的打嗝 - 通常是401或402ms。 在基于加速度计进行动画制作时,这对我来说会更有用。但是听众并没有以任何接近常规的价格接收它们;有时在下一个“丛”进来之前几秒钟过去了......
编辑-2:
今天在三星Galaxy S-3上进行了测试。因为数据比Nexus-4或SG S-5(最差)要快得多。三星都是垃圾邮件 logcat输出,在S5上它是一个没有有用信息的系统进程,但在S3上它显示“BluetoothSocket.cpp; readNative” 我怀疑传感器读数的结块行为可能是由蓝牙系统引起的:可能是输入缓冲区?有人知道是否可以改变蓝牙输入缓冲区的读取速率?
答案 0 :(得分:1)
我怀疑问题在于您更新显示器的频率。挥舞旗帜动画的时间间隔是多少?如果您每隔几毫秒更新一次显示,那么您可能会遇到一些延迟。
----编辑-----
抱歉延误。在再次查看您的问题后,我想知道问题可能与您如何注册手表传感器有关。您是否使用HelloSensors示例应用程序作为基础。如果没有,我建议你去看看。以下是传感器在样品中的注册方式。如果您还有问题,请试试这个并告诉我
/**
* Checks if the sensor currently being used supports interrupt mode and
* registers an interrupt listener if it does. If not, a fixed rate listener
* will be registered instead.
*/
private void register() {
Log.d(HelloSensorsExtensionService.LOG_TAG, "Register listener");
AccessorySensor sensor = getCurrentSensor();
if (sensor != null) {
try {
if (sensor.isInterruptModeSupported()) {
sensor.registerInterruptListener(mListener);
} else {
sensor.registerFixedRateListener(mListener, Sensor.SensorRates.SENSOR_DELAY_UI);
}
} catch (AccessorySensorException e) {
Log.d(HelloSensorsExtensionService.LOG_TAG, "Failed to register listener", e);
}
}
}