package com.novoda.example.compass.activities; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.hardware.GeomagneticField; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.location.Location; import android.os.Bundle; import android.util.Log; import com.actionbarsherlock.app.SherlockFragmentActivity; import com.novoda.example.compass.NovoCompass; import com.novoda.example.compass.utils.CompassUtils; import com.novoda.example.compass.utils.LowPassFilter; import com.novoda.location.exception.NoProviderAvailable; import java.util.concurrent.atomic.AtomicBoolean; public abstract class BasicSensorActivity extends SherlockFragmentActivity implements SensorEventListener { private static final int FIRST_SENSOR_ITEM = 0; private static final AtomicBoolean ATOMIC_BOOLEAN = new AtomicBoolean(false); private static final float grav[] = new float[3]; private static final float mag[] = new float[3]; private static final float rotation[] = new float[9]; private static final float orientation[] = new float[3]; private static final String TAG = "BasicSensorActivity"; private static float smoothed[] = new float[3]; private Location location; private GeomagneticField magField; private IntentFilter filter; private SensorManager sensorManager; private Sensor acclSensor; private Sensor magFieldSensor; private double bearing = 0; private int rotationDegrees = 0; public BroadcastReceiver freshLocationReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { location = NovoCompass.getLocator().getLocation(); magField = new GeomagneticField((float) location.getLatitude(), (float) location.getLongitude(), (float) location.getAltitude(), System.currentTimeMillis()); } }; protected void onCreate(Bundle bundle) { super.onCreate(bundle); sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); initLocationIntentFilter(); } private void initLocationIntentFilter() { filter = new IntentFilter(); filter.addAction(NovoCompass.LOCATION_UPDATE_ACTION); } @Override public void onResume() { super.onResume(); registerReceiver(freshLocationReceiver, filter); registerAcclSensor(); registerMagSensor(); registerLocationUpdates(); } @Override protected void onPause() { super.onPause(); unregisterReceiver(freshLocationReceiver); unRegisterAcclSensor(); unRegisterMagSensor(); unRegisterLocationUpdates(); } private void registerAcclSensor() { if (sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER).size() > 0) { acclSensor = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER).get(FIRST_SENSOR_ITEM); sensorManager.registerListener(this, acclSensor, SensorManager.SENSOR_DELAY_NORMAL); } }; private void registerMagSensor() { if (sensorManager.getSensorList(Sensor.TYPE_MAGNETIC_FIELD).size() > 0) { magFieldSensor = sensorManager.getSensorList(Sensor.TYPE_MAGNETIC_FIELD).get(FIRST_SENSOR_ITEM); sensorManager.registerListener(this, magFieldSensor, SensorManager.SENSOR_DELAY_NORMAL); } }; private void registerLocationUpdates() { try { NovoCompass.getLocator().startLocationUpdates(); } catch (NoProviderAvailable np) { Log.e(TAG, "There is no provider available", np); } } private void unRegisterLocationUpdates() { NovoCompass.getLocator().stopLocationUpdates(); } private void unRegisterAcclSensor() { if (acclSensor == null) { return; } sensorManager.unregisterListener(this, acclSensor); } public void unRegisterMagSensor() { if (magFieldSensor == null) { return; } sensorManager.unregisterListener(this, magFieldSensor); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // TODO Auto-generated method stub } @Override public void onSensorChanged(SensorEvent event) { if (!ATOMIC_BOOLEAN.compareAndSet(false, true)) return; updateSensorValues(event); ATOMIC_BOOLEAN.set(false); } private void updateSensorValues(SensorEvent event) { if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { setAcclValues(event); } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { setmagValues(event); } SensorManager.getRotationMatrix(rotation, null, grav, mag); SensorManager.getOrientation(rotation, orientation); double floatBearing = orientation[0]; floatBearing = Math.toDegrees(floatBearing); if (magField != null) floatBearing += magField.getDeclination(); if (floatBearing < 0) floatBearing += 360; setBearing(floatBearing); setRotationInDegrees(floatBearing); } private void setRotationInDegrees(double floatBearing) { this.bearing = floatBearing; } private void setBearing(double floatBearing) { this.rotationDegrees = CompassUtils.getRotationDegreesFromBearing(floatBearing); } public int getRotation(){ return rotationDegrees; } public double getBearing(){ return bearing; } private void setmagValues(SensorEvent event) { smoothed = LowPassFilter.filter(event.values, mag); mag[0] = smoothed[0]; mag[1] = smoothed[1]; mag[2] = smoothed[2]; } private void setAcclValues(SensorEvent event) { smoothed = LowPassFilter.filter(event.values, grav); grav[0] = smoothed[0]; grav[1] = smoothed[1]; grav[2] = smoothed[2]; } }