0

SO im trying to make a App that tracks which direction the phone is pointed VIA the compass and once a button is hit on the screen it displays the number of where it is pointed in degrees. So far i understand how the compass is created but can not find which values are the pointed direction in relation to North. Here is what i have so far.

public class compass extends Activity implements OnClickListener, SensorEventListener{

    private final SensorManager DirPoint;
    float var;
    TextView theNumber;

    Button DirectionIn;

    public compass(){ 
        DirPoint = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    }

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

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        theNumber = (textView) findViewById(R.id.output);
        DirectionIn =(Button) findViewById(R.Id.Buton);

        DirectionIn.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                //gets direction of phone compass
                // ((TextView)findViewById(R.id.output)).setText(var);
            }
        }
    }
}

Any help would be welcomed or if im headed in the right direction even would be nice.

manlio
  • 18,345
  • 14
  • 76
  • 126

2 Answers2

3

You have to implement a "compass". You can do this like this:

Let your activity implement the SensorEventListener and add the necessary fields:

public class CompassActivity extends Activity implements SensorEventListener {

    private SensorManager sensorManager;
    private Sensor accelerometer;
    private Sensor magnetometer;
    private float[] lastAccelerometer = new float[3];
    private float[] lastMagnetometer = new float[3];
    private boolean lastAccelerometerSet = false;
    private boolean lastMagnetometerSet = false;
    private float[] rotationMatrix = new float[9];
    private float[] orientation = new float[3];
    private float currentDegree = 0f;

In the onCreate method of the activity get and start the two sensors, the accelerometer and the magnetometer:

        // onCreate method stub ...
        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        magnetometer = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_UI);
        sensorManager.registerListener(this, magnetometer, SensorManager.SENSOR_DELAY_UI);
        // more onCreate method stub ....

In the method of the SensorEventListener you can now calculate the heading of the phone and calculate the bearing between the current location and a other location:

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor == this.accelerometer) {
            System.arraycopy(event.values, 0, this.lastAccelerometer, 0, event.values.length);
            this.lastAccelerometerSet = true;
        } else if (event.sensor == this.magnetometer) {
            System.arraycopy(event.values, 0, this.lastMagnetometer, 0, event.values.length);
            this.lastMagnetometerSet = true;
        }

        if (this.lastAccelerometerSet && this.lastAccelerometerSet) {
            SensorManager.getRotationMatrix(this.rotationMatrix,null, this.lastAccelerometer, this.lastMagnetometer);
            SensorManager.getOrientation(this.rotationMatrix, this.orientation);


            float azimuthInRadiands = this.orientation[0];

            // this is now the heading of the phone. If you want
            // to rotate a view to north don´t forget that you have
            // to rotate by the negative value.
            float azimuthInDegrees = (float) Math.toDegrees(azimuthInRadiands);

        }
    }

But don´t forget that there is much more behind a compass. You have to show the user if the magnetic field sensor is uncalibrated. You have to calculate the difference between the magnetic and the geographic north...

I have created a small compass helper class. The HowTo is in the readme. It will provide you all the information you need to present a compass on the screen:

Compass Assistant on GitHub

It provides you the current heading of the device. Please don´t hesitate to ask me if you have problems.

Artur Hellmann
  • 315
  • 4
  • 21
0

For Details look here

Use a compination of TYPE_ACCELEROMETER and TYPE_MAGNETIC_FIELD.

        Sensor beschleunigung = sensor.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
        Sensor magnetometer = sensor.getSensorList(Sensor.TYPE_MAGNETIC_FIELD).get(0);
        sensor.registerListener(handler, beschleunigung, SensorManager.SENSOR_DELAY_NORMAL, null);
        sensor.registerListener(handler, magnetometer, SensorManager.SENSOR_DELAY_NORMAL, null);

and

handler = new SensorEventListener() {
        float[] mGravity;
        float[] mGeomagnetic;

        @Override
        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
                }
            }

            NavigationArrow.this.setOffsetFromNorth((float) Math.toDegrees(azimut));
        }

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

        }
    };

Hope that helps :)

Matthias H
  • 1,300
  • 13
  • 19
  • NavigationArrow.this.setOffsetFromNorth((float) Math.toDegrees(azimut)); This line of code, what is Navigation arrow>? and in this code which number is the direction? would it be navigation arrow? and if so can i cast that to a float so i can display the number? – user2640706 Aug 01 '13 at 07:00
  • Navigation Arrow is the class these snippets where in. The value that i set in setOffsetFromNorth is the value u need i think. try: println((float) Math.toDegrees(azimut)) – Matthias H Aug 01 '13 at 07:21
  • Was code useful and solved your question? If yes please mark as solved :) yours Matthias – Matthias H Aug 01 '13 at 09:44