RxBluetooth
Android reactive bluetooth
Install / Use
/learn @IvBaranov/RxBluetoothREADME
RxBluetooth
Android reactive bluetooth library. Basically, RxBluetooth is just wrapper around android BluetoothAdapter, so first of all the Bluetooth developer guide should be read.
RxBluetooth for RxJava 1 is available in respective branch.
Full documentation
Usage
-
Create
RxBluetoothinstance.RxBluetooth rxBluetooth = new RxBluetooth(this); // `this` is a context -
For android 6.0+ you need location permission.
if (ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(MainActivity.this, new String[] { android.Manifest.permission.ACCESS_COARSE_LOCATION }, REQUEST_PERMISSION_COARSE_LOCATION); } // And catch the result like this: @Override public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_PERMISSION_COARSE_LOCATION) { for (String permission : permissions) { if (android.Manifest.permission.ACCESS_COARSE_LOCATION.equals(permission)) { // Do stuff if permission granted } } } } -
Check that bluetooth is available and enabled:
// check if bluetooth is supported on your hardware if (!rxBluetooth.isBluetoothAvailable()) { // handle the lack of bluetooth support } else { // check if bluetooth is currently enabled and ready for use if (!rxBluetooth.isBluetoothEnabled()) { // to enable bluetooth via startActivityForResult() rxBluetooth.enableBluetooth(this, REQUEST_ENABLE_BT); } else { // you are ready } } -
Have fun.
-
Make sure you are unsubscribing and stopping discovery in
OnDestroy():if (rxBluetooth != null) { rxBluetooth.cancelDiscovery(); } unsubscribe(rxBluetoothSubscription);
Observing devices
rxBluetooth.observeDevices()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.computation())
.subscribe(new Consumer<BluetoothDevice>() {
@Override public void accept(@NonNull BluetoothDevice bluetoothDevice) throws Exception {
//
}
}));
Create connection between devices
// Use 00001101-0000-1000-8000-00805F9B34FB for SPP service
// (ex. Arduino) or use your own generated UUID.
// UUID uuid = UUID.fromString("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
rxBluetooth.connectAsServer("servername", uuid).subscribe(
new Consumer<BluetoothSocket>() {
@Override public void accept(BluetoothSocket bluetoothSocket) throws Exception {
// Client connected, do anything with the socket
}
}, new Consumer<Throwable>() {
@Override public void accept(Throwable throwable) throws Exception {
// On error
}
});
rxBluetooth.connectAsClient(bluetoothDevice, uuid).subscribe(
new Consumer<BluetoothSocket>() {
@Override public void accept(BluetoothSocket bluetoothSocket) throws Exception {
// Connected to bluetooth device, do anything with the socket
}
}, new Consumer<Throwable>() {
@Override public void accept(Throwable throwable) throws Exception {
// On error
}
});
Observing discovery state
To observe just ACTION_DISCOVERY_STARTED:
rxBluetooth.observeDiscovery()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.computation())
.filter(BtPredicate.in(BluetoothAdapter.ACTION_DISCOVERY_STARTED))
.subscribe(new Consumer<String>() {
@Override public void accept(String action) throws Exception {
//
}
});
To observe both ACTION_DISCOVERY_STARTED and ACTION_DISCOVERY_FINISHED:
rxBluetooth.observeDiscovery()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.computation())
.filter(BtPredicate.in(BluetoothAdapter.ACTION_DISCOVERY_STARTED, BluetoothAdapter.ACTION_DISCOVERY_FINISHED))
.subscribe(new Consumer<String>() {
@Override public void accept(String action) throws Exception {
//
}
});
Observing bluetooth state
rxBluetooth.observeBluetoothState()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.computation())
.filter(BtPredicate.in(BluetoothAdapter.STATE_ON))
.subscribe(new Consumer<Integer>() {
@Override public void accept(Integer integer) throws Exception {
//
}
});
You can observe single or multiple states:
BluetoothAdapter.STATE_OFF
BluetoothAdapter.STATE_TURNING_ON
BluetoothAdapter.STATE_ON
BluetoothAdapter.STATE_TURNING_OFF
Observing scan mode
rxBluetooth.observeScanMode()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.computation())
.filter(BtPredicate.in(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE))
.subscribe(new Consumer<Integer>() {
@Override public void accept(Integer integer) throws Exception {
//
}
});
You can observe single or multiple scan modes:
BluetoothAdapter.SCAN_MODE_NONE
BluetoothAdapter.SCAN_MODE_CONNECTABLE
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE
Getting the profile proxy object
rxBluetooth.observeBluetoothProfile(myProfile)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.computation())
.subscribe(new Consumer<ServiceEvent>() {
@Override public void accept(ServiceEvent serviceEvent) throws Exception {
switch (serviceEvent.getState()) {
case CONNECTED:
BluetoothProfile bluetoothProfile = serviceEvent.getBluetoothProfile();
List<BluetoothDevice> devices = bluetoothProfile.getConnectedDevices();
for ( final BluetoothDevice dev : devices ) {
//..
}
break;
case DISCONNECTED:
//serviceEvent.getBluetoothProfile() returns null
break;
}
}
});
myProfile can be one of BluetoothProfile.HEALTH, BluetoothProfile.HEADSET, BluetoothProfile.A2DP, BluetoothProfile.GATT or BluetoothProfile.GATT_SERVER
Clients should close profile proxy when they are no longer using the proxy obtained from observeBluetoothProfile:
rxBluetooth.closeProfileProxy(int profile, BluetoothProfile proxy);
Observing device state
To observe the current device state, you can receive the ConnectionStateEvent which provides the state, previous state, and BluetoothDevice.
rxBluetooth.observeConnectionState()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.computation())
.subscribe(new Consumer<ConnectionStateEvent>() {
@Override public void accept(ConnectionStateEvent event) throws Exception {
switch (event.getState()) {
case BluetoothAdapter.STATE_DISCONNECTED:
// device disconnected
break;
case BluetoothAdapter.STATE_CONNECTING:
// device connecting
break;
case BluetoothAdapter.STATE_CONNECTED:
// device connected
break;
case BluetoothAdapter.STATE_DISCONNECTING:
// device disconnecting
break;
}
}
});
Possible states are:
BluetoothAdapter.STATE_DISCONNECTED
BluetoothAdapter.STATE_CONNECTING
BluetoothAdapter.STATE_CONNECTED
BluetoothAdapter.STATE_DISCONNECTING
Observing device bond state
To observe the bond state of devices, you can receive the BondStateEvent which provides the state, previous state, and BluetoothDevice.
rxBluetooth.observeBondState()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.computation())
.subscribe(new Consumer<BondStateEvent>() {
@Override public void accept(BondStateEvent event) throws Exception {
switch (event.getState()) {
case BluetoothDevice.BOND_NONE:
// device unbonded
break;
case BluetoothDevice.BOND_BONDING:
// device bonding
break;
case BluetoothDevice.BOND_BONDED:
// device bonded
break;
}
}
});
Possible states are:
BluetoothDevice.BOND_NONE
BluetoothDevice.BOND_BONDING
BluetoothDevice.BOND_BONDED
Read and Write with BluetoothSocket
After creating a connection to the device, you can use BluetoothConnection class to read and write with its socket.
Read:
BluetoothConnection bluetoothConnection = new BluetoothConnection(bluetoothSocket);
// Observe every byte received
bluetoothConnection.observeByteStream()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Consumer<Byte>() {
@Override public void accept(Byte aByte) throws Exception {
// This will be called every single byte received
}
}, new Consumer<Throwable>() {
@Override public void accept(Throwable throwable) throws Exception {
// Error occured
}
});
// Or just observe string
bluetoothConnection.observeStringStream()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Consu
