package no.topi.fiken.display; import android.app.Service; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothManager; import android.content.Context; import android.content.Intent; import android.os.Handler; import android.os.IBinder; import android.util.Log; import android.widget.Toast; public class DefaultDisplayService extends Service implements DisplayService { private final Context context = DefaultDisplayService.this; private final static String TAG = DefaultDisplayService.class.getSimpleName(); private final IBinder binder = new LocalBinder(this); private BluetoothManager mBluetoothManager; private BluetoothAdapter mBluetoothAdapter; private BluetoothGattService displayService; private BluetoothGatt gatt; private Handler handler; private int UPDATE_RSSI_DELAY = 1000; private Runnable updateRssi = new Runnable() { @Override public void run() { if(gatt != null) { gatt.readRemoteRssi(); } handler.postDelayed(this, UPDATE_RSSI_DELAY); } }; public static enum ServiceState { BROKEN, IDLE, SCANNING, CONNECTED, } private ServiceState serviceState = ServiceState.BROKEN; @Override public IBinder onBind(Intent intent) { return binder; } @Override public void onCreate() { handler = new Handler(); handler.postDelayed(updateRssi, UPDATE_RSSI_DELAY); } public boolean initialize() { // For API level 18 and above, get a reference to BluetoothAdapter through // BluetoothManager. if (mBluetoothManager == null) { mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); if (mBluetoothManager == null) { Log.e(TAG, "Unable to initialize BluetoothManager."); return false; } } mBluetoothAdapter = mBluetoothManager.getAdapter(); if (mBluetoothAdapter == null) { Log.e(TAG, "Unable to obtain a BluetoothAdapter."); return false; } Log.e(TAG, "Bluetooth initialized"); serviceState = ServiceState.IDLE; return true; } @Override public boolean connect(final String address) { if (serviceState != ServiceState.IDLE) { if (!(serviceState == ServiceState.CONNECTED && gatt.getDevice().getAddress().equals(address))) { Log.e(TAG, "connect(): Not idle: " + serviceState); return false; } Log.i(TAG, "connect(): already connected: " + serviceState); return true; } BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); gatt = device.connectGatt(this, false, new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { // Toast.makeText(context, "Connected", Toast.LENGTH_SHORT).show(); if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothGatt.STATE_CONNECTED) { boolean ok = gatt.discoverServices(); if (!ok) { disconnect(); } else { Intent intent = IntentAction.DEVICE_UPDATE.intent(); intent.putExtra(IntentExtra.DEVICE_ADDRESS.name(), address); intent.putExtra(IntentExtra.CONNECTED.name(), true); sendBroadcast(intent); } } else { Log.w(TAG, "Could not connect to device"); // Toast.makeText(context, "Could not connect to device", Toast.LENGTH_SHORT).show(); } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { Log.i(TAG, "onServicesDiscovered"); Log.i(TAG, "Constants.TRYGVIS_IO_FIKEN_STATUS_PANEL_UUID = " + Constants.TRYGVIS_IO_FIKEN_STATUS_PANEL_UUID); for (BluetoothGattService bluetoothGattService : gatt.getServices()) { Log.i(TAG, "bluetoothGattService.getUuid() = " + bluetoothGattService.getUuid()); } displayService = gatt.getService(Constants.TRYGVIS_IO_FIKEN_STATUS_PANEL_UUID); Log.i(TAG, "service=" + displayService); Intent intent = IntentAction.DEVICE_UPDATE.intent(); intent.putExtra(IntentExtra.DEVICE_ADDRESS.name(), address); intent.putExtra(IntentExtra.DEVICE_IS_DISPLAY.name(), displayService != null); sendBroadcast(intent); } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { Log.i(TAG, "onCharacteristicRead"); } @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { Log.i(TAG, "onCharacteristicWrite"); } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { Log.i(TAG, "onCharacteristicChanged"); } @Override public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { Log.i(TAG, "onDescriptorRead"); } @Override public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { Log.i(TAG, "onDescriptorWrite"); } @Override public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { Log.i(TAG, "onReliableWriteCompleted"); } @Override public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { Log.i(TAG, "onReadRemoteRssi, status=" + status + ", rssi=" + rssi); if (status == BluetoothGatt.GATT_SUCCESS) { Intent intent = IntentAction.DEVICE_UPDATE.intent(); intent.putExtra(IntentExtra.DEVICE_ADDRESS.name(), gatt.getDevice().getAddress()); intent.putExtra(IntentExtra.RSSI.name(), rssi); sendBroadcast(intent); } } }); if (gatt != null) { serviceState = ServiceState.CONNECTED; return true; } else { return false; } } @Override public void disconnect() { if (serviceState != ServiceState.CONNECTED) { Log.d(TAG, "disconnect(): Not connected: " + serviceState); return; } serviceState = ServiceState.IDLE; if (gatt != null) { try { gatt.disconnect(); } catch (Exception e) { Log.w(TAG, "gatt.disconnect()", e); } try { gatt.close(); } catch (Exception e) { Log.w(TAG, "gatt.close()", e); } gatt = null; } displayService = null; } @Override public void startScan() { if (serviceState != ServiceState.IDLE) { Toast.makeText(context, "startScan(): Not idle", Toast.LENGTH_SHORT).show(); return; } serviceState = ServiceState.SCANNING; mBluetoothAdapter.startLeScan(leScanCallback); } @Override public void stopScan() { Log.d(TAG, "stopScan(): stopping scanning"); if (serviceState != ServiceState.SCANNING) { Log.d(TAG, "stopScan(): not scanning"); return; } mBluetoothAdapter.stopLeScan(leScanCallback); serviceState = ServiceState.IDLE; } private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) { Log.i(TAG, "onLeScan()"); Intent intent = IntentAction.DEVICE_UPDATE.intent(); intent.putExtra(IntentExtra.DEVICE_ADDRESS.name(), device.getAddress()); intent.putExtra(IntentExtra.DEVICE_NAME.name(), device.getName()); intent.putExtra(IntentExtra.RSSI.name(), rssi); sendBroadcast(intent); } }; }