package interdroid.swan.sensors.impl; import interdroid.swan.R; import interdroid.swan.sensors.AbstractConfigurationActivity; import interdroid.swan.sensors.AbstractSwanSensor; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.util.Log; /** * A sensor for discovered bluetooth devices. * * @author nick <palmer@cs.vu.nl> * */ public class BluetoothSensor extends AbstractSwanSensor { private static final String TAG = "Bluetooth Sensor"; /** * This configuration activity for this sensor. * * @author nick <palmer@cs.vu.nl> * */ public static class ConfigurationActivity extends AbstractConfigurationActivity { @Override public final int getPreferencesXML() { return R.xml.bluetooth_preferences; } } /** * The device name field. */ public static final String DEVICE_NAME_FIELD = "name"; /** * The device address field. */ public static final String DEVICE_ADDRESS_FIELD = "address"; /** * The bond state for the device. */ public static final String DEVICE_BOND_STATE = "bond_state"; /** * The class of the device. */ private static final String DEVICE_CLASS = "class"; /** * The major class of the device. */ private static final String DEVICE_MAJOR_CLASS = "major_class"; /** * The discovery interval. */ public static final String DISCOVERY_INTERVAL = "discovery_interval"; /** * The default discovery interval. */ public static final long DEFAULT_DISCOVERY_INTERVAL = 5 * 60 * 1000; // ms /** * A flag to indicate we should stop polling. */ private boolean stopPolling = false; /** * The bluetooth adapter we use to do discovery. */ private BluetoothAdapter mBluetoothAdapter; /** * The broadcast receiver which gets information on bluetooth discovery. */ private BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() { @Override public void onReceive(final Context context, final Intent intent) { long now = System.currentTimeMillis(); BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); Log.d(TAG, "Bluetooth discovered: " + device.getName() + " " + device.getAddress()); putValueTrimSize(DEVICE_NAME_FIELD, null, now, device.getName()); putValueTrimSize(DEVICE_ADDRESS_FIELD, null, now, device.getAddress()); } }; /** * The thread which polls for bluetooth devices. */ private Thread bluetoothPoller = new Thread() { public void run() { while (!stopPolling) { long start = System.currentTimeMillis(); if (registeredConfigurations.size() > 0) { if (mBluetoothAdapter != null && !mBluetoothAdapter.isDiscovering()) { mBluetoothAdapter.startDiscovery(); Log.d(TAG, "bt started discovery"); } } try { Thread.sleep(currentConfiguration .getLong(DISCOVERY_INTERVAL) + start - System.currentTimeMillis()); } catch (InterruptedException e) { Log.w(TAG, "Interrupted while sleeping."); } } } }; @Override public final String[] getValuePaths() { return new String[] { DEVICE_ADDRESS_FIELD, DEVICE_NAME_FIELD, DEVICE_BOND_STATE, DEVICE_CLASS, DEVICE_MAJOR_CLASS }; } @Override public final void initDefaultConfiguration(final Bundle defaults) { defaults.putLong(DISCOVERY_INTERVAL, DEFAULT_DISCOVERY_INTERVAL); } @Override public final void onConnected() { SENSOR_NAME = "Bluetooth Sensor"; mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); Log.d(TAG, "bluetooth connected"); } @Override public final void register(final String id, final String valuePath, final Bundle configuration) { if (registeredConfigurations.size() == 1) { registerReceiver(bluetoothReceiver, new IntentFilter( BluetoothDevice.ACTION_FOUND)); if (!bluetoothPoller.isAlive()) { bluetoothPoller.start(); } } updatePollRate(); } /** * Update the polling rate. */ private void updatePollRate() { boolean keepDefault = true; long updatedPollRate = Long.MAX_VALUE; for (Bundle configuration : registeredConfigurations.values()) { if (configuration.containsKey(DISCOVERY_INTERVAL)) { keepDefault = false; updatedPollRate = Math.min(updatedPollRate, configuration.getLong(DISCOVERY_INTERVAL)); } } if (keepDefault) { currentConfiguration.putLong(DISCOVERY_INTERVAL, DEFAULT_DISCOVERY_INTERVAL); } else { currentConfiguration.putLong(DISCOVERY_INTERVAL, updatedPollRate); } } @Override public final void unregister(final String id) { if (registeredConfigurations.size() == 0) { unregisterReceiver(bluetoothReceiver); } updatePollRate(); } @Override public final void onDestroySensor() { if (registeredConfigurations.size() > 0) { unregisterReceiver(bluetoothReceiver); } mBluetoothAdapter.cancelDiscovery(); stopPolling = true; bluetoothPoller.interrupt(); super.onDestroySensor(); } }