我正在学习Android编程的基础知识。
我有一个简单的Android测试应用程序,其中我将加速度计,磁力计和方向数据记录到外部文件,同时还显示它。我通过调用方法 initLogger ,单击开始按钮(相关传感器的registerListener)启动日志记录过程。
看起来与此类似......
public void initLogger(View view)
{
boolean bFlag = false;
Button btnStart = (Button)findViewById(R.id.btnStartLog);
Button btnStop = (Button)findViewById(R.id.btnStopLog);
btnStart.setEnabled(bFlag);
btnStop.setEnabled(!bFlag);
bEnableLogging = true;
//Start reading the sensor values
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_UI);
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);
//so on....
还有一个Stop按钮,它将停止记录过程(最后通过为每个传感器调用unregisterListener来取消注册)
数据检索过程发生在 onSensorChanged 处理程序中,该处理程序将从相关传感器检索数据,将值设置为相应的UI元素,最后将数据记录到外部.csv文件。
onSensorChanged eventhandler看起来像这样......
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
// accelerometer
TextView tAX = (TextView) findViewById(R.id.txtViewAxValue);
TextView tAY = (TextView) findViewById(R.id.txtViewAyValue);
TextView tAZ = (TextView) findViewById(R.id.txtViewAzValue);
// magnetic field
TextView tMX = (TextView) findViewById(R.id.txtViewMx);
TextView tMY = (TextView) findViewById(R.id.txtViewMy);
TextView tMZ = (TextView) findViewById(R.id.txtViewMz);
if (bEnableLogging) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
accelerometerdata = event.values.clone();
tAX.setText(Double.toString(accelerometerdata[0]));
tAY.setText(Double.toString(accelerometerdata[1]));
tAZ.setText(Double.toString(accelerometerdata[2]));
}
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
magneticmatrixdata = event.values.clone();
tMX.setText(Double.toString(magneticmatrixdata[0]));
tMY.setText(Double.toString(magneticmatrixdata[1]));
tMZ.setText(Double.toString(magneticmatrixdata[2]));
}
// so on ....
虽然我从所有配置的传感器接收数据,但我无法控制接收数据的速率。即
我知道当传感器数据发生变化时会触发SensorChanged事件。但是我希望以固定费率解雇此事件。 例如:每40毫秒
问题:
专家在这里SO.Please帮助我:)
答案 0 :(得分:3)
您可以通过更改注册传感器时的延迟来更改间隔。
int SENSOR_DELAY_FASTEST get sensor data as fast as possible
int SENSOR_DELAY_GAME rate suitable for games
int SENSOR_DELAY_NORMAL rate (default) suitable for screen orientation changes
int SENSOR_DELAY_UI rate suitable for the user interface
根据this,最快的延迟是你需要的,如果它没有足够快地改变,那是因为没有变化。没有getSensorData方法。
您可以指定其他数据延迟,例如SENSOR_DELAY_GAME(20,000 微秒延迟),SENSOR_DELAY_UI(60,000微秒延迟),或 SENSOR_DELAY_FASTEST(0微秒延迟)。从Android 3.0开始(API 等级11)你也可以将延迟指定为绝对值(in 微秒)。
您指定的延迟只是建议的延迟。 Android 系统和其他应用程序可以改变这种延迟。作为最好的 练习时,你应该指定最大的延迟,因为 系统通常使用比您指定的延迟更小的延迟 (也就是说,您应该选择仍然满足的最慢采样率 您的应用程序的需求)。使用较大的延迟会降低 加载到处理器上,因此耗电量更少。
答案 1 :(得分:2)
由于您知道如果没有触发SensorChanged事件,则没有任何更改,您可以使用旧值。 当您在特定时间间隔内询问LOG数据时,我不会在onSensorChanged方法中执行任何输出,只需将新数据克隆到accelerometerdata变量即可。 而且每40ms记录一次accelerometerdata的值。这样,即使数据没有改变,您也会每40ms记录一次实际值....
注意:根据Ridcullys的回答,似乎也可以在特定的时间间隔内“传递”传感器数据。但是由于这些“交付”的延迟与Android上的传感器数据一样,使用我的解决方案,您将更精确地在40毫秒间隔。另一方面,如果传感器数据在您记录的那一刻发生变化,则可能会发生延迟新数据一个时间间隔的情况。 我猜(不确定这一点) - 因为它只是关于记录而不是像“尽可能快地实时获取”,所以这不是一个要求 - 定时器解决方案导致更少的CPU负载。 / p>
答案 2 :(得分:1)
使用registerListener使用SensorManager
注册您的监听器,而不是固定常量SENSOR_DELAY_...
,您可以传递微秒的间隔,如JavaDocs中所述:
rate速率传感器事件的传递时间为。这只是一个暗示 系统。可以比指定的更快或更慢地接收事件 率。通常会更快地收到事件。该值必须是其中之一 SENSOR_DELAY_NORMAL,SENSOR_DELAY_UI,SENSOR_DELAY_GAME,或 SENSOR_DELAY_FASTEST或,事件之间所需的延迟 微秒。
所以,只需传递 40000 来匹配您的示例请求,同样,如上所述,这只是一个提示,所以我不会依赖于精确到微秒的间隔获取值。
答案 3 :(得分:0)
我一直试图弄清楚如何使用传感器进行很长时间的延迟,到目前为止我已经成功了。关于developer.android的文档说明延迟时间可以用微秒来指定,下面是我试过的大量数据:
// Initialize in onCreate
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE)
mLight = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
// Register the listener, and play around with delay
mSensorManager.registerListener(this, mLight, 200000000);
但请注意下面的LogCat转储 - onSensorChanged() - 每秒被调用多达4次......我试图找出更大的延迟但到目前为止没有成功!!!
01-14 06:58:07.088:D / IOE传感器(20933):onSensorChanged被调用,事件是:android.hardware.SensorEvent@42849f70 01-14:58:07.268:D / IOE Sensors(20933):onSensorChanged调用,事件为:android.hardware.SensorEvent@42849f70 01-14:58:07.448:D / IOE传感器(20933):onSensorChanged调用,事件为:android.hardware.SensorEvent@42849f70 01-14:58:07.628:D / IOE Sensors(20933):onSensorChanged调用,事件为:android.hardware.SensorEvent@42849f70 01-14:58:07.808:D / IOE传感器(20933):onSensorChanged调用,事件为:android.hardware.SensorEvent@42849f70 01-14:58:07.989:D / IOE传感器(20933):onSensorChanged调用,事件为:android.hardware.SensorEvent@42849f70 01-14 06:58:08.169:D / IOE Sensors(20933):onSensorChanged调用,事件为:android.hardware.SensorEvent@42849f70
答案 4 :(得分:0)
似乎调用onSensorChanged的速率必须是4个建议值之一。
你可以做些什么来慢慢阅读'是使用SENSOR_DELAY_UI和(在onSensorChanged中)测量自上次读取感应数据以来经过的时间:
long lastUpdate = System.currentTimeMillis();
// In onSensorChanged:
long curTime = System.currentTimeMillis();
if ((curTime - lastUpdate) > 500){ // only reads data twice per second
lastUpdate = curTime;
// do stuff
}
我在这里看到的唯一缺点是if语句将被多次调用并带有错误结果。