Android Geräteorientierung ohne geomagnetisch

Ich muss Geräteorientierung bekommen. Wie ich in der Regel verwendete TYPE_ACCELEROMETER und TYPE_MAGNETIC_FIELD Sensoren kennen. Mein Problem ist, dass SensorManager.getDefaultSensor mir null für geomagnetischen Sensor zurückgibt. Es gibt auch null für den TYPE_ORIENTATION Sensor zurück.

 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äteorientierung zu bekommen.

  • Android - Landschaftsmodus deaktivieren?
  • OnCreate nicht aufgerufen, wenn der Bildschirm dreht - Android
  • Inkonsistente Orientierungssensorwerte auf Android für Azimut / Gier und Roll
  • Android: alternatives Layout xml für den Landschaftsmodus
  • Android Fragment Lebenszyklus über Orientierung ändert sich
  • Wie finde ich Landschaft links (normal) vs Landschaft rechts (umgekehrt) mit Unterstützung für natürlich Landschaftsgeräte?
  • Bilder, die mit ACTION_IMAGE_CAPTURE aufgenommen wurden, gibt immer 1 für ExifInterface.TAG_ORIENTATION auf einige neuere Geräte zurück
  • Welche Aktivitätsmethode wird aufgerufen, wenn Orientierungsänderungen auftreten?
  • 6 Solutions collect form web for “Android Geräteorientierung ohne geomagnetisch”

    Die Orientierung kann in drei Euler-Winkel zerlegt werden: Pitch, Roll und Azimut.

    Mit nur Beschleunigungsmesser-Daten kannst du deinen Azimut nicht berechnen, weder das Zeichen deines Pitches.

    Sie können etwas ausprobieren, um etwas über Ihren Pitch und Roll 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; } 

    Um den Drehwinkel zu erhalten, wenn das Gerät nicht flach ist, implementiert OrientationEventListener . onOrientationChanged gibt die onOrientationChanged . Weitere Informationen finden Sie unter https://developer.android.com/reference/android/view/OrientationEventListener.html .

    Ich habe so etwas gemacht:

     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 du über meine if-Aussagen verstehen willst, sehen sie dieses Bild Bild

    Für meine Verwendung Ich sperre den Bildschirm in einem Porträt-Modus, und eine Verwendung von 2 Bildern, um den Winkel auf dem Bildschirm zu zeigen, das ist mein Screenshot Bildschirmfoto

    Ich muss es noch besser machen, einfach nicht genug Zeit dafür.

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

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

    Der Standard-Sensor entspricht den angeforderten Typ- und WakeUp-Eigenschaften, falls vorhanden und die Applikation hat die notwendigen Berechtigungen oder null sonst

    Ich weiß, es klingt gegen intuitiv, aber anscheinend sind die Berechtigungen, die Sie benötigen:

     <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 Untermenge davon).

    Sehen Sie hier: manifest.xml bei der Verwendung von Sensoren

    Sie können den GEOMAGNETIC_ROTATION_VECTOR so ausprobieren:

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

    Und berechnen Sie die 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 aus Android-Dokumenten: https://developer.android.com/guide/topics/sensors/sensors_position.html

    Füge die entsprechenden Berechtigungen in das Manifest hinzu.

    Hoffe das hilft.

    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.