传感器TYPE_ACCELEROMETER和TYPE_MAGNETIC_FIELD - 它们适用于手机,但不适用于平板电脑

时间:2012-07-01 08:59:15

标签: android android-sensors

在我的2D游戏中,我有以下代码,负责游戏实体控制(飞行飞机)。对于手机而言,这一切似乎都运转良好,但遗憾的是我得到的一些信息在Android平板电脑上转向完全不可靠(轴被搞砸了,或者根本不起作用)。不幸的是,我没有自己的平板电脑,所以我无法进一步研究它。那么..以下代码有什么问题? (为清楚起见,我只提供了与传感器相关的代码)

// ...
private float[] accelerometerValues;
private float[] magneticFieldValues;
private float[] R;
private float[] I;
private float[] outR;
private float[] sensorValues;

private Sensor accelerometer;
private Sensor magneticField;
// ...

// ... sensor initialization
    sensorManager = (SensorManager)activity.getSystemService(Context.SENSOR_SERVICE);
    if(sensorManager == null)
        return;
    accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 
    magneticField = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
// ...

// ... onPause() sensor is being unregistered
public void onResume() {
    if(!sensorManager.registerListener(sensorListener, accelerometer, SensorManager.SENSOR_DELAY_GAME) ||
       !sensorManager.registerListener(sensorListener, magneticField, SensorManager.SENSOR_DELAY_GAME))
// ...

    // ...
    sensorListener = new SensorEventListener() {
        public void onAccuracyChanged(Sensor arg0, int arg1) {              
        }
        public void onSensorChanged(android.hardware.SensorEvent event) {
            synchronized(InputMgr.this) {
                switch(event.sensor.getType()) {
                case Sensor.TYPE_ACCELEROMETER:
                    System.arraycopy(event.values, 0, accelerometerValues, 0, 3);
                    break;
                case Sensor.TYPE_MAGNETIC_FIELD:
                    System.arraycopy(event.values, 0, magneticFieldValues, 0, 3);
                    break;
                }
            }
        }
    };  
    // ...  

    // used somewhere in the game
public void getSensorValues(float values[]) {
    synchronized(InputMgr.this) {
        SensorManager.getRotationMatrix(R, I, accelerometerValues, magneticFieldValues);
        SensorManager.remapCoordinateSystem(R, SensorManager.AXIS_Y, SensorManager.AXIS_X, outR);
        SensorManager.getOrientation(outR, sensorValues);
        System.arraycopy(sensorValues, 0, values, 0, sensorValues.length);
    }
}

2 个答案:

答案 0 :(得分:3)

这不会让你振作起来,但我有类似的问题。我可以看到一个TYPE_MAGNETIC_FIELD传感器,我可以添加一个事件监听器,但我从来没有从中获取任何数据。其他传感器工作正常。这是在Galaxy Tab 7上。

onSensorChanged(SensorEvent事件)永远不会触发案例Sensor.TYPE_MAGNETIC_FIELD:

因此我没有从磁场传感器获得数据。

如果你解决了,请告诉我们=)

答案 1 :(得分:2)

在默认方向为横向的设备上( - >大多数平板电脑),传感器值有点“错误”(我不知道为什么)。因此,您需要捕获这些设备并重新映射旋转矩阵。

要检查矩阵是否需要重新映射,可以使用以下代码:

public boolean needToRemapOrientationMatrix;

// compute once (e.g. in onCreate() of your Activity):
Display display = ((WindowManager)getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int orientation;
if(display.getWidth() < display.getHeight()) orientation = Configuration.ORIENTATION_PORTRAIT;
else if(display.getWidth() > display.getHeight()) orientation = Configuration.ORIENTATION_LANDSCAPE;
else orientation = Configuration.ORIENTATION_SQUARE;
int rotation = display.getRotation();
needToRemapOrientationMatrix =
    (orientation==Configuration.ORIENTATION_LANDSCAPE && (rotation==Surface.ROTATION_0 || rotation==Surface.ROTATION_180)) ||
    (orientation==Configuration.ORIENTATION_PORTRAIT && (rotation==Surface.ROTATION_90 || rotation==Surface.ROTATION_270));

当您读取传感器值时,如果需要,重新映射矩阵:

public void getSensorValues(float values[]) {
    synchronized(InputMgr.this) {
        SensorManager.getRotationMatrix(R, I, accelerometerValues, magneticFieldValues);

        if(needToRemapOrientationMatrix)
            SensorManager.remapCoordinateSystem(R, SensorManager.AXIS_MINUS_Y, SensorManager.AXIS_X, R);

        SensorManager.remapCoordinateSystem(R, SensorManager.AXIS_Y, SensorManager.AXIS_X, outR);
        SensorManager.getOrientation(outR, sensorValues);
        System.arraycopy(sensorValues, 0, values, 0, sensorValues.length);
    }
}

这对我有用,我希望它有所帮助。