无论屏幕方向如何,如何获得正确的方位(磁方向)? [英] How do I get the correct bearing (magnetic orientation) regardless of screen orientation?
问题描述
无论当前屏幕方向(横向或纵向)如何,我都想获取当前的磁方向.
I want to get the current magnetic orientation regardless of the current screen orientation (landscape or portrait).
我找到了 这个 示例,但它是不是方向独立的,对吧?而这个也没有帮助我.我也读过 http://android-developer.blogspot.de/2010/09/one-screen-turn-deserves-another.html.
I found this example, but it's not orientation independant, right? And this didn't help me either. I did also read http://android-developers.blogspot.de/2010/09/one-screen-turn-deserves-another.html.
这是我目前不推荐使用的方法(简短):
This is my current approach with the deprecated way I don't want to use (short):
mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
private SensorEventListener sensorEventListener = new SensorEventListener() {
public void onSensorChanged(SensorEvent event) {
/* Get measured value */
float current_measured_bearing = (float) event.values[0];
/* Compensate device orientation */
switch (((WindowManager) getSystemService(WINDOW_SERVICE))
.getDefaultDisplay().getRotation()) {
case Surface.ROTATION_90:
current_measured_bearing = current_measured_bearing + 90f;
break;
case Surface.ROTATION_180:
current_measured_bearing = current_measured_bearing - 180f;
break;
case Surface.ROTATION_270:
current_measured_bearing = current_measured_bearing - 90f;
break;
}
但是最后一部分肯定是错误的!在这种情况下,如何正确使用较新的方法 getRotationMatrix()
?(与方向无关)或者我是否只需要使用基于旋转矩阵的 event.values[]
数组的其他值?还是我需要重新映射坐标"? 实现这一目标的正确方法是什么?
But the last part is definitely wrong! How do I use the newer method getRotationMatrix()
correctly in this case? (Orientation independent) Or do I simply have to use other values of the event.values[]
array based on the Rotation Matrix? Or will I need to 'remap the coordinates'? So is that the correct way of achieving this?
我正在为具有 360° 屏幕旋转和 API 级别 11+ 的设备进行开发.
I'm developing for devices with 360° screen rotation and on API Level 11+.
我知道这些问题经常被问到,但我根本无法将他们的答案转移到我的问题上.
I know that those questions are asked very often but I could simply not transfer their answers to my question.
推荐答案
好的,我终于设法让代码工作了!
OK I finally managed to get the code working!
首先,我注册了一个 Sensor.TYPE_MAGNETIC_FIELD
和 Sensor.TYPE_GRAVITY
:(就像 Hoan Nguyen 说的!)
First, I register a Sensor.TYPE_MAGNETIC_FIELD
and Sensor.TYPE_GRAVITY
: (like Hoan Nguyen said!)
/**
* Initialize the Sensors (Gravity and magnetic field, required as a compass
* sensor)
*/
private void initSensors() {
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
Sensor mSensorGravity = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
Sensor mSensorMagneticField = sensorManager
.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
/* Initialize the gravity sensor */
if (mSensorGravity != null) {
Log.i(TAG, "Gravity sensor available. (TYPE_GRAVITY)");
sensorManager.registerListener(mSensorEventListener,
mSensorGravity, SensorManager.SENSOR_DELAY_GAME);
} else {
Log.i(TAG, "Gravity sensor unavailable. (TYPE_GRAVITY)");
}
/* Initialize the magnetic field sensor */
if (mSensorMagneticField != null) {
Log.i(TAG, "Magnetic field sensor available. (TYPE_MAGNETIC_FIELD)");
sensorManager.registerListener(mSensorEventListener,
mSensorMagneticField, SensorManager.SENSOR_DELAY_GAME);
} else {
Log.i(TAG,
"Magnetic field sensor unavailable. (TYPE_MAGNETIC_FIELD)");
}
}
我使用那个 SensorEventListner
进行计算:
And I use that SensorEventListner
for the computation:
private SensorEventListener mSensorEventListener = new SensorEventListener() {
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_GRAVITY) {
mGravity = event.values.clone();
} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
mMagnetic = event.values.clone();
}
if (mGravity != null && mMagnetic != null) {
/* Create rotation Matrix */
float[] rotationMatrix = new float[9];
if (SensorManager.getRotationMatrix(rotationMatrix, null,
mGravity, mMagnetic)) {
/* Compensate device orientation */
// http://android-developers.blogspot.de/2010/09/one-screen-turn-deserves-another.html
float[] remappedRotationMatrix = new float[9];
switch (getWindowManager().getDefaultDisplay()
.getRotation()) {
case Surface.ROTATION_0:
SensorManager.remapCoordinateSystem(rotationMatrix,
SensorManager.AXIS_X, SensorManager.AXIS_Y,
remappedRotationMatrix);
break;
case Surface.ROTATION_90:
SensorManager.remapCoordinateSystem(rotationMatrix,
SensorManager.AXIS_Y,
SensorManager.AXIS_MINUS_X,
remappedRotationMatrix);
break;
case Surface.ROTATION_180:
SensorManager.remapCoordinateSystem(rotationMatrix,
SensorManager.AXIS_MINUS_X,
SensorManager.AXIS_MINUS_Y,
remappedRotationMatrix);
break;
case Surface.ROTATION_270:
SensorManager.remapCoordinateSystem(rotationMatrix,
SensorManager.AXIS_MINUS_Y,
SensorManager.AXIS_X, remappedRotationMatrix);
break;
}
/* Calculate Orientation */
float results[] = new float[3];
SensorManager.getOrientation(remappedRotationMatrix,
results);
/* Get measured value */
float current_measured_bearing = (float) (results[0] * 180 / Math.PI);
if (current_measured_bearing < 0) {
current_measured_bearing += 360;
}
/* Smooth values using a 'Low Pass Filter' */
current_measured_bearing = current_measured_bearing
+ SMOOTHING_FACTOR_COMPASS
* (current_measured_bearing - compass_last_measured_bearing);
/* Update normal output */
visual_compass_value.setText(String.valueOf(Math
.round(current_bearing))
+ getString(R.string.degrees));
/*
* Update variables for next use (Required for Low Pass
* Filter)
*/
compass_last_measured_bearing = current_measured_bearing;
}
}
}
};
这篇关于无论屏幕方向如何,如何获得正确的方位(磁方向)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!