Cómo obtener la dirección de la brújula en Android

Estoy tratando de hacer una aplicación de brújula para Android, como muchos otros tienen antes de mí.

Sin embargo, estoy teniendo un problema de entender cómo se supone que todo el asunto de la matriz de rotación funciona. He intentado mi camino hacia adelante y han llegado con el siguiente código:

public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction() .add(R.id.container, new PlaceholderFragment()) .commit(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. /*switch (item.getItemId()) { case R.id.action_settings: return true; }*/ return super.onOptionsItemSelected(item); } public static class PlaceholderFragment extends Fragment { TextView degreesText; ImageView needleView; private SensorManager sMan; private float[] mAcc = new float[3]; private float[] mMag = new float[3]; private float[] mRotationMatrix = new float[9]; private float[] mOrientation = new float[3]; private float fAzimuth; private boolean firstRun; public PlaceholderFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_main, container, false); //Test if application has been started for the first time firstRun = getActivity().getSharedPreferences("PREFERENCE", MODE_PRIVATE).getBoolean("firstRun", true); if (firstRun) { //Build warning dialog AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); //Set message and title builder.setMessage(R.string.dialog_message).setTitle(R.string.dialog_title); //Add dismiss button builder.setNeutralButton(R.string.dismiss, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //On okay click } }); AlertDialog dialog = builder.create(); //Show dialog dialog.show(); } //Set firstRun to false, so dialog doesn't show again getActivity().getSharedPreferences("PREFERENCE", MODE_PRIVATE).edit().putBoolean("firstRun", false).commit(); //Get text and image views degreesText = (TextView)rootView.findViewById(R.id.degrees_text); needleView = (ImageView)rootView.findViewById(R.id.needle); //Set up sensor manager sMan = (SensorManager)getActivity().getSystemService(SENSOR_SERVICE); //Listener for magnetic and accelerometer events SensorEventListener eventListener = new SensorEventListener() { @Override public void onSensorChanged(SensorEvent event) { switch (event.sensor.getType()) { case Sensor.TYPE_ACCELEROMETER: mAcc = event.values.clone(); break; case Sensor.TYPE_MAGNETIC_FIELD: mMag = event.values.clone(); break; } SensorManager.getRotationMatrix(mRotationMatrix, null, mAcc, mMag); SensorManager.getOrientation(mRotationMatrix, mOrientation); fAzimuth = (float)Math.round(Math.toDegrees(mOrientation[0])); fAzimuth = (fAzimuth + 360) % 360; degreesText.setText(String.valueOf(fAzimuth)); needleView.setRotation(-fAzimuth); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } }; //Register listeners for magnetic and accelerometer sensors sMan.registerListener(eventListener, sMan.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_NORMAL); sMan.registerListener(eventListener, sMan.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL); return rootView; } } } 

Esto funciona perfectamente bien, siempre y cuando mi teléfono está en modo retrato y se establecen en una superficie plana. Mi problema está en entender qué debo hacer para hacer que la misma cosa trabaje en modo del retrato y del paisaje, así como cuando sostén el teléfono en una cierta otra orientación.

De lo que he leído necesito usar SensorManager.remapCoordinateSystem() , pero no entiendo cuáles son los dos ejes que se supone que debo suministrar, y cómo funciona.

Cualquier ayuda en la comprensión de todo esto sería muy apreciada, gracias!

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.