Skip to content

Instantly share code, notes, and snippets.

@cleac
Created July 14, 2015 14:40
Show Gist options
  • Save cleac/e1aee66e97178af8beec to your computer and use it in GitHub Desktop.
Save cleac/e1aee66e97178af8beec to your computer and use it in GitHub Desktop.
Code
public class BluetoothService extends Service {
private final static String LOG_TAG = BluetoothService.class.getName();
private final static String AUTHORITY = "com.forcemove.forceemotion.bt";
private final int SERVICE_STATUS_ID = 1;
private BluetoothGatt mBluetoothGatt;
public final static String ACTION_GATT_CONNECTED = AUTHORITY + ".ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_CONNECTING = AUTHORITY + ".ACTION_GATT_CONNECTING";
public final static String ACTION_GATT_DISCONNECTED = AUTHORITY + ".ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED = AUTHORITY + ".ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_GATT_DATA_AVAILABLE = AUTHORITY + ".ACTION_GATT_DATA_AVAILABLE";
public final static String ACTION_GATT_EXTRA_DATA = AUTHORITY + ".ACTION_GATT_EXTRA_DATA";
private int mConnectionState = STATE_DISCONNECTED;
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTING = 1;
private static final int STATE_CONNECTED = 2;
private final int CHARACTER_NOTI_ID = 2;
private final int CONNECTION_STATUS_ID = 3;
private final int FOUND_DEVICES_ID = CONNECTION_STATUS_ID + 1;
private final int BATTERY_STATE_ID = 5;
private final int KEY_NOTI_ID = BATTERY_STATE_ID + 1;
/**
* Variable that defines interaction with Bluetooth device: gets data from and sends broadcasts
* notifications about new data; checks connection state and looks for Bluetooth services that
* can be discovered
*/
private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentAction = null;
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
gatt.discoverServices();
break;
case BluetoothProfile.STATE_DISCONNECTED:
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
break;
case BluetoothProfile.STATE_CONNECTING:
intentAction = ACTION_GATT_CONNECTING;
mConnectionState = STATE_CONNECTING;
}
if(intentAction!=null)
broadcastUpdate(intentAction);
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status)
{
if(status == BluetoothGatt.GATT_SUCCESS) {
String uuid = characteristic.getUuid().toString().toUpperCase();
if(uuid.equals(SupportedGattAttributes.Characteristics.Battery)) {
sendNotification("Battery level " + characteristic.getIntValue(
BluetoothGattCharacteristic.FORMAT_UINT8, 1
) + '%', BATTERY_STATE_ID);
} else if(uuid.equals(SupportedGattAttributes.Characteristics.KeyReport)) {
sendNotification("Got a key!", KEY_NOTI_ID);
}
broadcastUpdate(ACTION_GATT_DATA_AVAILABLE, characteristic);
} else {
Log.e(LOG_TAG,"onCharacteristicRead received : " + status);
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
String uuid = characteristic.getUuid().toString().toUpperCase();
if(uuid.equals(SupportedGattAttributes.Characteristics.Battery)) {
sendNotification("Battery level " + characteristic.getIntValue(
BluetoothGattCharacteristic.FORMAT_UINT8, 1) + '%', BATTERY_STATE_ID);
} else if(uuid.equals(SupportedGattAttributes.Characteristics.KeyReport)) {
sendNotification("Got a key!", KEY_NOTI_ID);
}
broadcastUpdate(ACTION_GATT_DATA_AVAILABLE,characteristic);
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if(status == BluetoothGatt.GATT_SUCCESS) {
List<BluetoothGattService> services = mBluetoothGatt.getServices();
for(BluetoothGattService service:services) {
UUID uuid_current = service.getUuid();
BluetoothGattCharacteristic characteristic;
if (uuid_current.equals(UUID.fromString(SupportedGattAttributes.Services.Battery))) {
characteristic = service.getCharacteristic(
UUID.fromString(SupportedGattAttributes.Characteristics.Battery));
} else if (uuid_current.equals(UUID.fromString(SupportedGattAttributes.Services.HID))) {
characteristic = service.getCharacteristic(
UUID.fromString(SupportedGattAttributes.Characteristics.KeyReport));
} else {
continue;
}
if(characteristic==null)
Log.e(LOG_TAG,"Unable to find characteristic");
else {
gatt.readCharacteristic(characteristic);
Log.e(LOG_TAG,"READING CHARACTERISTIC");
}
}
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.e(LOG_TAG, "onServicesDiscovered received: " + status);
}
}
public void broadcastUpdate(String intentAction) {
if(intentAction.equals(ACTION_GATT_SERVICES_DISCOVERED)) {
NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification.Builder notiBuilder = new Notification.Builder(BluetoothService.this)
.setSmallIcon(R.drawable.ic_autorenew_white_48dp)
.setContentTitle("Force")
.setContentText("Found services");
Intent resultIntent = new Intent(BluetoothService.this, BluetoothInfoActivity.class);
resultIntent.putExtra(Intent.EXTRA_TEXT, ACTION_GATT_SERVICES_DISCOVERED);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(BluetoothService.this);
stackBuilder.addParentStack(ScanBluetoothActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
notiBuilder.setContentIntent(resultPendingIntent);
notificationManager.notify(SERVICE_STATUS_ID, notiBuilder.build());
}
}
public void broadcastUpdate(String intentAction,BluetoothGattCharacteristic characteristic) {
sendNotification("Got data", CHARACTER_NOTI_ID);
}
};
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
sendNotification("Service stopped", SERVICE_STATUS_ID);
if(mBluetoothGatt==null)
return;
mBluetoothGatt.disconnect();
mBluetoothGatt.close();
mBluetoothGatt = null;
}
private final IBinder mLocalBinder = new LocalBinder();
public class LocalBinder extends Binder {
public BluetoothService getService() {
return BluetoothService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mLocalBinder;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(mBluetoothGatt==null) {
BluetoothManager mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter mBluetoothAdapter = mBluetoothManager.getAdapter();
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(SettingsAccessor.getDeviceAddress(this));
if (device == null) {
sendNotification("Device not found",0);
}
mBluetoothGatt = device.connectGatt(this, true, mGattCallback);
} else {
mBluetoothGatt.connect();
}
return START_STICKY;
}
private void sendNotification(String message, int id) {
NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification.Builder notiBuilder = new Notification.Builder(BluetoothService.this)
.setSmallIcon(R.drawable.ic_autorenew_white_48dp)
.setContentTitle("Force")
.setContentText(message);
Intent resultIntent = new Intent(BluetoothService.this, BluetoothInfoActivity.class);
resultIntent.putExtra(Intent.EXTRA_TEXT, message);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(BluetoothService.this);
stackBuilder.addParentStack(ScanBluetoothActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
notiBuilder.setContentIntent(resultPendingIntent);
notificationManager.notify(id, notiBuilder.build());
}
public List<BluetoothGattService> getGattServices(){
if(mBluetoothGatt!=null)
return mBluetoothGatt.getServices();
else
return null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment