/******************************************************************************* * Gaggle is Copyright 2010 by Geeksville Industries LLC, a California limited liability corporation. * * Gaggle is distributed under a dual license. We've chosen this approach because within Gaggle we've used a number * of components that Geeksville Industries LLC might reuse for commercial products. Gaggle can be distributed under * either of the two licenses listed below. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Commercial Distribution License * If you would like to distribute Gaggle (or portions thereof) under a license other than * the "GNU General Public License, version 2", contact Geeksville Industries. Geeksville Industries reserves * the right to release Gaggle source code under a commercial license of its choice. * * GNU Public License, version 2 * All other distribution of Gaggle must conform to the terms of the GNU Public License, version 2. The full * text of this license is included in the Gaggle source, see assets/manual/gpl-2.0.txt. ******************************************************************************/ package com.geeksville.location; import java.util.List; import java.util.Observable; import java.util.Observer; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; abstract class SensorClient extends Observable implements SensorEventListener { protected static SensorManager sensorMan; private int sensorType; protected int timeSpanMs = 500; public SensorClient(Context context, int sensorType) { initManager(context); this.sensorType = sensorType; if (getSensor() == null) throw new RuntimeException("Sensor not found"); } protected static void initManager(Context context) { if (sensorMan == null) sensorMan = (SensorManager) context .getSystemService(Context.SENSOR_SERVICE); } /** * If you are just using observers, you do not need to call this method. It * is here folks who want to poll instead */ private void stopListening() { sensorMan.unregisterListener(this); } // / The hardware sensor we are connected to (or null for not found) public Sensor getSensor() { List<Sensor> sensors = sensorMan.getSensorList(sensorType); if (sensors.size() > 0) return sensors.get(0); else return null; } /** * If you are just using observers, you do not need to call this method. It * is here folks who want to poll instead */ private void startListening() { Sensor sensor = getSensor(); sensorMan.registerListener( this, sensor, 100000 /*100 ms*/); //SensorManager.SENSOR_DELAY_NORMAL); } /* * (non-Javadoc) * * @see java.util.Observable#addObserver(java.util.Observer) */ @Override public synchronized void addObserver(Observer observer) { if (countObservers() == 0) startListening(); super.addObserver(observer); } /* * (non-Javadoc) * * @see java.util.Observable#deleteObserver(java.util.Observer) */ @Override public synchronized void deleteObserver(Observer observer) { super.deleteObserver(observer); if (countObservers() == 0) stopListening(); } float[] values; /** * * @return the last set of values we received from this sensor */ public float[] getValues() { return values; } /** * Crufty - we will break if the clock is changed while we are running FIXME */ long lastUpdate = System.currentTimeMillis(); @Override public void onSensorChanged(SensorEvent event) { this.values = event.values; // No need for a deep copy fullRateSensorChanged(values); } protected void fullRateSensorChanged(float[] values) { // We limit updates to a slowish rate to avoid burning cycles elsewhere long nowMs = System.currentTimeMillis(); long diff = nowMs - lastUpdate; if (diff >= timeSpanMs) { onThrottledSensorChanged(values); lastUpdate = nowMs; } } protected abstract void onThrottledSensorChanged(float[] values); }