Search code examples
javaandroidandroid-sensorssensormanager

Why doesn't my SensorEventListener implementation work? Not receiving onSensorChanged callbacks


I'm trying to make an app to display phones roation in degrees, but onSensorChanged is not getting called. The text in the textView isn't changing and I don't know why. It doesn't give any compile error. Here is the code.

package com.alex.location360;

import androidx.appcompat.app.AppCompatActivity;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements SensorEventListener  {

    TextView textView;
    float roll=0;
    @Override
    public void onSensorChanged(SensorEvent event) {
        float[] mGravity = new float[0];
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
            mGravity = event.values;

        float[] mGeomagnetic = new float[0];
        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);
                float azimuth = orientation[0]; // orientation contains: azimuth, pitch and roll
                float pitch = orientation[1];
                roll = orientation[2];
                roll= (float) Math.toDegrees(roll);
                textView.setText(String.valueOf(roll));
                Log.e("#",String.valueOf(roll));
            }
        }
    }
    @Override
    public void onAccuracyChanged(Sensor sensor, int i) {

    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView=findViewById(R.id.textView);
    }
}

Solution

  • You need to actually subscribe to sensor updates, rather than simply implementing SensorEventListener.

    Add this to your onCreate method:

    SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    magneticFieldSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
    sensorManager.registerListener(this, accelerometerSensor, SensorManager.SENSOR_DELAY_NORMAL);
    sensorManager.registerListener(this, magneticFieldSensor, SensorManager.SENSOR_DELAY_NORMAL);
    

    You'll probably also want to unsubscribe from the listeners in onDestroy (or use onStart/onStop if you only want updates while the Activity is visible.