2016-08-02 9 views
10

Ich brauche Geräteausrichtung. Wie ich weiß, verwendet normalerweise TYPE_ACCELEROMETER und TYPE_MAGNETIC_FIELD Sensoren. Mein Problem ist, dass SensorManager.getDefaultSensor mich null für den geomagnetischen Sensor zurückgibt. Es gibt auch null für TYPE_ORIENTATION Sensor zurück.Android-Gerät Ausrichtung ohne geomagnetische

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); 

Ich brauche eine andere Möglichkeit, Geräteausrichtung zu bekommen.

+0

Post-Code. – Jas

+0

@Jas zu Frage hinzugefügt – Ircover

+0

können Sie Bildschirmbreite und -höhe verwenden, um die Ausrichtung zu bestimmen, im Landscape-Modus ist die Breite normalerweise höher als die Höhe. – ashutiwari4

Antwort

2

ich habe so etwas wie:

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){} 
    }; 
} 

, wenn Sie über meine verstehen wollen, wenn Aussagen dieses Bild sehen image

für meine verwende ich den Bildschirm in einem Portrait-Modus zu sperren, und eine Verwendung 2 Bilder, um den Winkel auf dem Bildschirm zu zeigen, das ist mein Screenshot screenshot

Ich muss immer noch etwas besser machen, nur nicht genug Zeit dafür.

ich hoffe, dass diese Hilfe, wenn Sie einen vollständigen Code benötigen, lassen Sie es mich wissen.

1

Sie müssen dem Manifest einige Berechtigungen hinzufügen. Die docs heißt es:

der Standardsensor den angeforderten Typ und Wakeup-Eigenschaften passende falls vorhanden und die Anwendung verfügt über die notwendigen Berechtigungen oder null, sonst

Ich weiß, es unlogisch klingt, aber Offensichtlich sind die erforderlichen Berechtigungen:

<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"/> 

(oder eine Untergruppe von denen).

Siehe hier: manifest.xml when using sensors

+0

Wenn Sie über geomagnetische sprechen, habe ich einige Kompass-Anwendungen versucht - alle von ihnen sagt mein Gerät nicht benötigt Sensor. – Ircover

5

Orientierung kann in drei Euler-Winkel zerlegt werden: Nick-, Roll- und Azimuth.

Mit nur Beschleunigungsmesserdaten können Sie Ihren Azimut nicht berechnen, auch nicht das Vorzeichen Ihrer Tonhöhe.

Sie können etwas versuchen, da dies etwas über Ihre Nick- und Wankbewegungen zu wissen:

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

Wie der OP sagte, kann er sich nicht auf das Magnetometer verlassen, während Ihr Code es erfordert. – strangetimes

+1

Falsch, mein Code reagiert, wenn er null ist und immer noch teilweise Orientierung bietet. –

1

Sie die GEOMAGNETIC_ROTATION_VECTOR wie diese versuchen:

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

Und berechnen Sie den Sensor info mit diesem:

... 
// 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); 

Extrahiert von android Dokumentation: https://developer.android.com/guide/topics/sensors/sensors_position.html

fügen Sie die richtigen Berechtigungen im Manifest hinzu.

Hoffe, das hilft.

0

Für alle, die immer noch von diesem Problem verwirrt sind, sagen Sie: Sie möchten die Ausrichtung Ihres Telefons (Azimut, Tonhöhe und Roll), aber manchmal ist das Magnetfeld instabil, so dass die Orientierung erhalten Sie auch instabil. Die obigen Antworten können Ihnen helfen, den Neigungs- und Rollwinkel zu erhalten, aber Sie können den Azimutwinkel immer noch nicht erhalten. Sie sagten, es sei unmöglich. Dann wirst du verzweifelt. Also, was sollten Sie tun, um dieses Problem zu lösen?

Wenn Sie nur über die Orientierung kümmern und Sie kümmern sich nicht um, wo Norden ist, hier ist mein Vorschlag, versuchen Sie diesen Sensor, es funktioniert super in meinem Fall:

TYPE_GAME_ROTATION_VECTOR