2016-08-02 87 views
10

我需要获取设备方向。据我所知,通常使用TYPE_ACCELEROMETERTYPE_MAGNETIC_FIELD传感器。我的问题是SensorManager.getDefaultSensor返回给我地磁传感器null。它也返回nullTYPE_ORIENTATION传感器。没有地磁的Android设备方向

manager = (SensorManager) getSystemService(SENSOR_SERVICE); 
Sensor sensorAcc = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), //normal object 
     sensorMagn = manager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); //null 
orientationListener = new OrientationSensorListener(); 
manager.registerListener(orientationListener, sensorAcc, 10); 
manager.registerListener(orientationListener, sensorMagn, 10); 

我需要另一种方法来获取设备方向。

+0

发布您的代码。 – Jas

+0

@Jas添加到问题 – Ircover

+0

您可以利用屏幕宽度和高度来确定方向,在横向模式下,通常宽度高于高度。 – ashutiwari4

回答

2

我不喜欢的东西:

public class MainActivity extends AppCompatActivity 
{ 
    SensorManager sensorManager; 
    Sensor sensor; 
    ImageView imageViewProtractorPointer; 

    ///////////////////////////////////// 
    ///////////// onResume ////////////// 
    ///////////////////////////////////// 
    @Override 
    protected void onResume() 
    { 
     super.onResume(); 
     // register sensor listener again if return to application 
     if(sensor !=null) sensorManager.registerListener(sensorListener,sensor,SensorManager.SENSOR_DELAY_NORMAL); 
    } 
    ///////////////////////////////////// 
    ///////////// onCreate ////////////// 
    ///////////////////////////////////// 
    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     imageViewProtractorPointer = (ImageView)findViewById(R.id.imageView2); 
     // get the SensorManager 
     sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); 
     // get the Sensor ACCELEROMETER 
     sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 
    } 
    ///////////////////////////////////// 
    ///////////// onPause /////////////// 
    ///////////////////////////////////// 
    @Override 
    protected void onPause() 
    { 
     // Uninteresting the sensor listener to prevent battery drain if not in use 
     super.onPause(); 
     if(sensor !=null) sensorManager.unregisterListener(sensorListener); 
    } 

    ///////////////////////////////////////////// 
    /////////// SensorEventListener ///////////// 
    ///////////////////////////////////////////// 
    SensorEventListener sensorListener = new SensorEventListener() 
    { 
     @Override 
     public void onSensorChanged(SensorEvent sensorEvent) 
     { 
      // i will use values from 0 to 9 without decimal 
      int x = (int)sensorEvent.values[0]; 
      int y = (int)sensorEvent.values[1]; 
      int angle = 0; 

      if(y>=0 && x<=0) angle = x*10; 
      if(x<=0 && y<=0) angle = (y*10)-90; 
      if(x>=0 && y<=0) angle = (-x*10)-180; 
      if(x>=0 && y>=0) angle = (-y*10)-270; 

      imageViewProtractorPointer.setRotation((float)angle); 
     } 
     @Override 
     public void onAccuracyChanged(Sensor sensor, int i){} 
    }; 
} 
如果你想了解关于我的if语句看到这个图像 image

为我用我锁定屏幕处于纵向模式

,和使用2图像显示在屏幕上的角度,这是我的屏幕截图 screenshot

我仍然必须使它好一点,只是没有足够的时间。

我希望这个帮助,如果你需要一个完整的代码让我知道。

1

您必须向清单添加一些权限。该文档指出:

默认的传感器相匹配的请求的类型和唤醒特性如果存在和应用具有必要的权限,否则返回null

我知道这听起来直觉,但显然你需要的权限是:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> 
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/> 
<uses-permission android:name="android.permission.INTERNET"/> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 

(或那些的子集)。

在这里看到:俯仰,滚转和方位角:manifest.xml when using sensors

+0

如果你在谈论地磁,我尝试了一些指南针应用程序 - 他们都说我的设备不需要传感器。 – Ircover

5

方向可以在三个欧拉角分解。

只有加速度计数据,你不能计算你的方位角,既不是你的音高标志。

你可以试一下,因为这对了解你的俯仰和横滚:

private final float[] mMagnet = new float[3];    // magnetic field vector 
    private final float[] mAcceleration = new float[3];   // accelerometer vector 
    private final float[] mAccMagOrientation = new float[3]; // orientation angles from mAcceleration and mMagnet 
    private float[] mRotationMatrix = new float[9];    // accelerometer and magnetometer based rotation matrix 

    public void onSensorChanged(SensorEvent event) { 
    switch (event.sensor.getType()) { 
     case Sensor.TYPE_ACCELEROMETER: 
      System.arraycopy(event.values, 0, mAcceleration, 0, 3); // save datas 
      calculateAccMagOrientation();      // then calculate new orientation 
      break; 
     case Sensor.TYPE_MAGNETIC_FIELD: 
      System.arraycopy(event.values, 0, mMagnet, 0, 3);   // save datas 
      break; 
     default: break; 
    } 
} 
public void calculateAccMagOrientation() { 
    if (SensorManager.getRotationMatrix(mRotationMatrix, null, mAcceleration, mMagnet)) 
     SensorManager.getOrientation(mRotationMatrix, mAccMagOrientation); 
    else { // Most chances are that there are no magnet datas 
     double gx, gy, gz; 
     gx = mAcceleration[0]/9.81f; 
     gy = mAcceleration[1]/9.81f; 
     gz = mAcceleration[2]/9.81f; 
     // http://theccontinuum.com/2012/09/24/arduino-imu-pitch-roll-from-accelerometer/ 
     float pitch = (float) -Math.atan(gy/Math.sqrt(gx * gx + gz * gz)); 
     float roll = (float) -Math.atan(gx/Math.sqrt(gy * gy + gz * gz)); 
     float azimuth = 0; // Impossible to guess 

     mAccMagOrientation[0] = azimuth; 
     mAccMagOrientation[1] = pitch; 
     mAccMagOrientation[2] = roll; 
     mRotationMatrix = getRotationMatrixFromOrientation(mAccMagOrientation); 
    } 
} 
public static float[] getRotationMatrixFromOrientation(float[] o) { 
    float[] xM = new float[9]; 
    float[] yM = new float[9]; 
    float[] zM = new float[9]; 

    float sinX = (float) Math.sin(o[1]); 
    float cosX = (float) Math.cos(o[1]); 
    float sinY = (float) Math.sin(o[2]); 
    float cosY = (float) Math.cos(o[2]); 
    float sinZ = (float) Math.sin(o[0]); 
    float cosZ = (float) Math.cos(o[0]); 

    // rotation about x-axis (pitch) 
    xM[0] = 1.0f;xM[1] = 0.0f;xM[2] = 0.0f; 
    xM[3] = 0.0f;xM[4] = cosX;xM[5] = sinX; 
    xM[6] = 0.0f;xM[7] =-sinX;xM[8] = cosX; 

    // rotation about y-axis (roll) 
    yM[0] = cosY;yM[1] = 0.0f;yM[2] = sinY; 
    yM[3] = 0.0f;yM[4] = 1.0f;yM[5] = 0.0f; 
    yM[6] =-sinY;yM[7] = 0.0f;yM[8] = cosY; 

    // rotation about z-axis (azimuth) 
    zM[0] = cosZ;zM[1] = sinZ;zM[2] = 0.0f; 
    zM[3] =-sinZ;zM[4] = cosZ;zM[5] = 0.0f; 
    zM[6] = 0.0f;zM[7] = 0.0f;zM[8] = 1.0f; 

    // rotation order is y, x, z (roll, pitch, azimuth) 
    float[] resultMatrix = matrixMultiplication(xM, yM); 
    resultMatrix = matrixMultiplication(zM, resultMatrix); 
    return resultMatrix; 
} 
public static float[] matrixMultiplication(float[] A, float[] B) { 
    float[] result = new float[9]; 

    result[0] = A[0] * B[0] + A[1] * B[3] + A[2] * B[6]; 
    result[1] = A[0] * B[1] + A[1] * B[4] + A[2] * B[7]; 
    result[2] = A[0] * B[2] + A[1] * B[5] + A[2] * B[8]; 

    result[3] = A[3] * B[0] + A[4] * B[3] + A[5] * B[6]; 
    result[4] = A[3] * B[1] + A[4] * B[4] + A[5] * B[7]; 
    result[5] = A[3] * B[2] + A[4] * B[5] + A[5] * B[8]; 

    result[6] = A[6] * B[0] + A[7] * B[3] + A[8] * B[6]; 
    result[7] = A[6] * B[1] + A[7] * B[4] + A[8] * B[7]; 
    result[8] = A[6] * B[2] + A[7] * B[5] + A[8] * B[8]; 

    return result; 
} 
+0

正如OP所说,他不能依靠磁力计,而你的代码需要它。 – strangetimes

+1

错误,如果代码为空并且仍然提供部分方向,则代码会发生反应。 –

1

你可以尝试这样的GEOMAGNETIC_ROTATION_VECTOR:

private SensorManager mSensorManager; 
private Sensor mSensor; 
... 
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR) 

而计算与该传感器信息:

... 
// Rotation matrix based on current readings from accelerometer and magnetometer. 
final float[] rotationMatrix = new float[9]; 
mSensorManager.getRotationMatrix(rotationMatrix, null, accelerometerReading, magnetometerReading); 

// Express the updated rotation matrix as three orientation angles. 
final float[] orientationAngles = new float[3]; 
mSensorManager.getOrientation(rotationMatrix, orientationAngles); 

从android中提取文档:https://developer.android.com/guide/topics/sensors/sensors_position.html

在清单中添加适当的权限。

希望这会有所帮助。

0

对于那些仍然困惑于这个问题的人来说,你想要获得手机的方向(方位角,俯仰角和滚转角),但有时候磁场不稳定,所以你得到的方向也是不稳定。上面的答案可以帮助你获得俯仰和滚转角度,但你仍然无法得到方位角。他们说这是不可能的。然后你变得绝望。那么,你应该怎么做才能解决这个问题?

如果你只关心取向和你不关心,其中北方,这里是我的建议,试试这个传感器,它在我的情况下工作真棒:

TYPE_GAME_ROTATION_VECTOR