Я поворачиваю телефон — значения датчиков Android остаются постоянными

У меня есть проблема, с которой я боролся уже несколько недель.

У меня есть приложение, которое использует датчик TYPE_ROTATION_VECTOR. Когда я дома, он всегда работает, но когда я нахожусь на улице, датчик перестает работать. Я по-прежнему получаю вызовы onSensorChanged, но значения остаются прежними, даже когда устройство перемещается или поворачивается.

На данный момент мое решение состоит в том, чтобы определить, остаются ли значения неизменными в течение некоторого времени, и если они остаются, я отменяю регистрацию и перерегистрирую SensorEventListener. Потом снова работает.

Но почему это может происходить и только снаружи? Проблема возникает как на Galaxy S3 Mini (с Android 4.1), так и на Nexus 10 (с Android 4.4).

Ниже приведен код моего класса RotationSensor. Объект RotationSensor является членом Fragment с setRetainInstance(true);. Но ошибка возникает только с датчиком TYPE_ROTATION_VECTOR, поэтому я предполагаю, что ошибка должна быть в приведенном ниже коде.

public class RotationSensor extends OrientationSensor { //The super class is just an abstract class which doesn't do anything
private int screen_rotation=0;
 private SensorManager mSensorManager;
 private Sensor mSensor, magSensor;
 private float[] values = null;
private Activity activity=null;
 private SensorListener listener;
 private float magField=0;

 private float[] orientationValsFlat = new float[3];
 private float[] orientationValsOpp = new float[3];
 private float[] mRotationMatrix = new float[9];
 private float[] matrixI=null;

 private float[] m_NormMagFieldValues = null;


//This method is called from a Fragment's onResume method.
 @Override
 public void register(Activity activity, SensorListener otherListener,int sensorSpeed) {
     this.activity=activity;
     listener=otherListener;
     mSensorManager = (SensorManager) activity.getSystemService(Context.SENSOR_SERVICE);
     mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
     if (mSensor==null){ 
         mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
         matrixI= new float[9];
     }
     magSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
     mSensorManager.registerListener(this, mSensor, sensorSpeed);
     mSensorManager.registerListener(this, magSensor, sensorSpeed);
 }

//Called from onPause in a Fragment
 @Override
 public void unregister() {
     activity=null;
     listener=null;
     mSensorManager.unregisterListener (this, mSensor);
     mSensorManager.unregisterListener (this, magSensor);
 }

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
    if (activity==null) return;
    if (listener!=null) listener.onAccuracyChanged(sensor, accuracy);
}

@Override
public void onSensorChanged(SensorEvent event) {
    if (activity==null) return;
    if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) 
    {
        values= event.values.clone();
        SensorManager.getRotationMatrixFromVector(mRotationMatrix, values);

        float[] remapMatrix = new float[9];
        SensorManager.remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_X, SensorManager.AXIS_Z, remapMatrix);
        SensorManager.getOrientation(remapMatrix, orientationValsOpp);
        SensorManager.getOrientation(mRotationMatrix, orientationValsFlat);

        screen_rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
       float screen_adjustment = 0;


       switch(screen_rotation) {
            case Surface.ROTATION_0:   screen_adjustment =          0;         break;
            case Surface.ROTATION_90:  screen_adjustment =   (float)Math.PI/2; break;
            case Surface.ROTATION_180: screen_adjustment =   (float)Math.PI;   break;
            case Surface.ROTATION_270: screen_adjustment = 3*(float)Math.PI/2; break;
        }

       if (screen_rotation==Surface.ROTATION_90 || screen_rotation==Surface.ROTATION_270) arrayswap (orientationValsFlat,1,2);
        orientationValsFlat[0]+=screen_adjustment;
        orientationValsOpp[0]+=screen_adjustment;

    }
    if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
          if (m_NormMagFieldValues == null) m_NormMagFieldValues = new float[3];
            m_NormMagFieldValues=event.values.clone();
         magField = (float)Math.sqrt(m_NormMagFieldValues[0]*m_NormMagFieldValues[0] + m_NormMagFieldValues[1]*m_NormMagFieldValues[1] + m_NormMagFieldValues[2]*m_NormMagFieldValues[2]);
    }
    if (event.sensor.getType()==Sensor.TYPE_ACCELEROMETER){
        values = event.values.clone();

        if (m_NormMagFieldValues!=null && SensorManager.getRotationMatrix(mRotationMatrix, matrixI, values,  m_NormMagFieldValues)){
         SensorManager.getOrientation(mRotationMatrix, orientationValsFlat);
         orientationValsOpp=orientationValsFlat;
        screen_rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
           float screen_adjustment = 0;


           switch(screen_rotation) {
                case Surface.ROTATION_0:   screen_adjustment =          0;         break;
                case Surface.ROTATION_90:  screen_adjustment =   (float)Math.PI/(4); break;
                case Surface.ROTATION_180: screen_adjustment =   (float)Math.PI/(-2);   break;
                case Surface.ROTATION_270: screen_adjustment = 3*(float)Math.PI/4; break;
            }

           if (screen_rotation==Surface.ROTATION_90 || screen_rotation==Surface.ROTATION_270) arrayswap (orientationValsFlat,1,2);

         orientationValsFlat[0]+=screen_adjustment; orientationValsOpp[0]+=screen_adjustment;
        }
    }


    if (listener!=null) listener.onSensorChanged(this,event); 
}

@Override
public int getField(){
    return (int)magField;
}

@Override
public double getAzimuth() {
    boolean opp =(screen_rotation==Surface.ROTATION_0 && Math.toDegrees(getPitch())<-50);
    if (opp)
        return orientationValsOpp[0];
    else
        return orientationValsFlat[0];
  }

@Override
public double getPitch() {
    return orientationValsFlat[1];
}

@Override
public double getRoll() {
    return orientationValsFlat[2];
}

private void arrayswap (float[] array, int index1, int index2){
    float temp= array[index1];
    array[index1]=array[index2];
    array[index2]=temp;
}

}

 public interface SensorListener {
     public void onSensorChanged(OrientationSensor os, SensorEvent event);
     public void onAccuracyChanged(Sensor sensor, int accuracy);
}

person AndroidHobby    schedule 12.07.2014    source источник


Ответы (1)


Возможно следующее: у вас может не быть unregister() слушателя sensorEventListener перед закрытием приложения. Итак, SensorManager получает onSensorChanged() событий в ваших логах.

Все, что вам нужно, это unregisterListener() до закрытия приложения. Вы можете отменить регистрацию в onPause() методе активности.

Если проблема не устранена, отправьте в ответ полный исходный код, который вы написали, и лог-кат, который вы получили для этого приложения.

person Rahul Raina    schedule 14.05.2015