Получить угол устройства с помощью функции getOrientation()

Я использовал Sensor.TYPE_ORIENTATION для определения текущего угла наклона устройства, но TYPE_ORIENTATION устарел в API версии 8. В руководстве SensorManager это относится к функции getOrientation() для использования TYPE_ORIENTATION.

Вот руководство


Вот мой старый код:

public void onSensorChanged(SensorEvent event) {
        Log.d("debug","Sensor Changed");
        if (event.sensor.getType()==Sensor.TYPE_ORIENTATION) {
            Log.d("debug",Float.toString(event.values[0]));


            float mAzimuth = event.values[0];
            float mPitch = event.values[1];
            float mRoll = event.values[2];

            Log.d("debug","mAzimuth :"+Float.toString(mAzimuth));
            Log.d("debug","mPitch :"+Float.toString(mPitch));
            Log.d("debug","mRoll :"+Float.toString(mRoll));
        }

    }

Я действительно запутался в использовании функции getOrientation(), может ли кто-нибудь показать мне пример, как получить углы?


person fobus    schedule 02.12.2013    source источник


Ответы (4)


Теперь вы используете два датчика (ACCELEROMETER и MAGNETIC_FIELD), чтобы получить эту информацию. Дополнительные сведения см. в сообщении в блоге.

public class CompassActivity extends Activity implements SensorEventListener {

  private SensorManager mSensorManager;
  Sensor accelerometer;
  Sensor magnetometer;

  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(mCustomDrawableView);    // Register the sensor listeners
    mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
    accelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    magnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
  }

  protected void onResume() {
    super.onResume();
    mSensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_UI);
    mSensorManager.registerListener(this, magnetometer, SensorManager.SENSOR_DELAY_UI);
  }

  protected void onPause() {
    super.onPause();
    mSensorManager.unregisterListener(this);
  }

  public void onAccuracyChanged(Sensor sensor, int accuracy) {  }

  float[] mGravity;
  float[] mGeomagnetic;
  public void onSensorChanged(SensorEvent event) {
    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
      mGravity = event.values;
    if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
      mGeomagnetic = event.values;
    if (mGravity != null && mGeomagnetic != null) {
      float R[] = new float[9];
      float I[] = new float[9];
      boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);
      if (success) {
        float orientation[] = new float[3];
        SensorManager.getOrientation(R, orientation);
        azimut = orientation[0]; // orientation contains: azimut, pitch and roll
      }
    }
  }
}

Разрешения:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
person JRomero    schedule 02.12.2013
comment
Спасибо за ответ, но строка ниже всегда возвращает false : boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeoмагнитный); - person fobus; 03.12.2013
comment
Странно, но проверьте stackoverflow.com/a/14224122/552902 похоже, что перебор значений событий вместо прямой ссылки может почини это. - person JRomero; 03.12.2013
comment
Нет, он не всегда возвращает false, иногда он возвращает true, примерно каждые 10 секунд возвращает true, но время не является регулярным. - person fobus; 03.12.2013
comment
Звучит как новый вопрос, извините. - person JRomero; 03.12.2013
comment
@fobus возвращает false, потому что, скорее всего, на вашем устройстве нет компаса и, следовательно, вы не получаете магнитные значения. - person agamov; 13.10.2015
comment
ВНИМАНИЕ: приведенный выше код будет собирать МНОГО мусора из-за новых массивов в onSensorChanged(). Код здесь лучше: stackoverflow.com/a/10291428/550471 - person Someone Somewhere; 06.09.2017
comment
Было бы неплохо обновить это и сейчас, чтобы указать на «Sensor.TYPE_ROTATION_VECTOR», который, вероятно, широко поддерживается и может быть намного проще в использовании — хороший пример здесь, чтобы направить людей на stackoverflow.com/a/53408643/334402 - person Mick; 27.12.2019

Относительно вашего второго вопроса. Когда вы регистрируете слушателей датчиков, измените свой код следующим образом:

protected void onResume() {          
    super.onResume();          
    mSensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);          
    mSensorManager.registerListener(this, magnetometer, SensorManager.SENSOR_DELAY_NORMAL);          
}
person Shaheed    schedule 23.12.2014

У Google есть отличное демонстрационное приложение для ориентации в их серии обучающих программ для разработчиков Google под названием TiltSpot. Поскольку у него есть лицензия Apache, я позволил себе превратить его в небольшую библиотеку под названием это упрощает получение ориентации, добавляя это к вашей деятельности:

        getLifecycle().addObserver(new OrientationReporter(this, (a, p, r) -> {
            Log.i("orientation","a="+a+" p="+p+" r="+r);
        }));
person JohnnyLambada    schedule 20.12.2019
comment
Не удалось разрешить: com.github.johnnylambada:johnnylambada-orientation:1.0.0 - person karatuno; 19.10.2020

Мой ответ для тех, кто получает прыгающие значения заголовка. Для получения дальнейших инструкций дайте мне знать в комментарии.

Sensor accelerometer;
Sensor magnetometer;
private float[] mGravity = new float[3];
private float[] mGeomagnetic = new float[3];
private float[] Rv = new float[9];
private float[] I = new float[9]; 

класс MapsActivity

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, SensorEventListener{

onSensorChanged(событие SensorEvent)

@Override
public void onSensorChanged(SensorEvent event) {

    synchronized (this) {
        float INITIAL_ALPHA = 0.97f;
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {

            mGravity[0] = INITIAL_ALPHA * mGravity[0] + (1 - INITIAL_ALPHA)
                    * event.values[0];
            mGravity[1] = INITIAL_ALPHA * mGravity[1] + (1 - INITIAL_ALPHA)
                    * event.values[1];
            mGravity[2] = INITIAL_ALPHA * mGravity[2] + (1 - INITIAL_ALPHA)
                    * event.values[2];
        }
        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {

            mGeomagnetic[0] = INITIAL_ALPHA * mGeomagnetic[0] + (1 - INITIAL_ALPHA)
                    * event.values[0];
            mGeomagnetic[1] = INITIAL_ALPHA * mGeomagnetic[1] + (1 - INITIAL_ALPHA)
                    * event.values[1];
            mGeomagnetic[2] = INITIAL_ALPHA * mGeomagnetic[2] + (1 - INITIAL_ALPHA)
                    * event.values[2];

            if (Math.abs(mGeomagnetic[2]) > Math.abs(mGeomagnetic[1])) {
                magStrength = Math.round(Math.abs(mGeomagnetic[2]));
            } else {
                magStrength = Math.round(Math.abs(mGeomagnetic[1]));
            }
        }

        boolean success = SensorManager.getRotationMatrix(Rv, I, mGravity, mGeomagnetic);
        if (success) {
            float[] orientation = new float[3];
            SensorManager.getOrientation(Rv, orientation);

            azimuth = (float) Math.toDegrees(orientation[0]);
            azimuth = (azimuth + 360) % 360;
            // Log.d(TAG, "azimuth (deg): " + azimuth);

            float degree = Math.round(azimuth);

            // create a rotation animation (reverse turn degree degrees)
            RotateAnimation ra = new RotateAnimation(
                    currentDegree,
                    -degree,
                    Animation.RELATIVE_TO_SELF, 0.5f,
                    Animation.RELATIVE_TO_SELF,
                    0.5f);

            ra.setDuration(500);
            ra.setFillAfter(true);
            ra.setRepeatCount(0);

            binding.compassImage.startAnimation(ra);
            showDirection(degree);

            currentDegree = -degree;

        }
    }
}

при изменении точности

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {

}

по возобновлению()

 @Override
protected void onResume() {
    super.onResume();
    if (mSensorManager == null) {
        mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        accelerometer = 
       mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        magnetometer = 
       mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
    }
       mSensorManager.registerListener(this, accelerometer, 
       SensorManager.SENSOR_DELAY_UI);
       mSensorManager.registerListener(this, magnetometer, 
       SensorManager.SENSOR_DELAY_UI);
}

на паузу()

@Override
protected void onPause() {
    super.onPause();
    mSensorManager.unregisterListener(MapsActivity.this);
}
person Nikit Dungrani    schedule 29.06.2021