Skip to content

kmazurek/rx-bluetooth-adapter

Repository files navigation

RxBluetoothAdapter

bitrise_badge

Reactive wrapper for Android's BluetoothAdapter class.

Introduction

The idea of this library is to provide reactive bindings and extensions for BluetoothAdapter.

The library was built with the following requirements in mind:

  1. The entire public API should be based on RxJava stream types (i.e. Observable, Single and Completable).
  2. Bluetooth preconditions (e.g. adapter enabled, permissions granted, device paired) should be checked eagerly on every call which requires them.
  3. Any exceptions raised inside the library should be propagated downstream via Rx.

RxBluetoothAdapter is aimed specifically at the classic Bluetooth API (< 4.0), it does not cover Bluetooth Low Energy. For BLE, I recommend using the excellent RxAndroidBle library.

Usage

Initialisation

RxBluetoothAdapter is meant to be used as a single instance. You can use a dependency injection framework (e.g. Dagger for Java or Kodein for Kotlin) or keep a singleton somewhere in your application.

val adapter = RxBluetoothAdapter(context)

Scanning for devices

We can initiate a scan for nearby Bluetooth devices by calling startDeviceScan on the adapter object. This call checks the required Bluetooth preconditions and either throws an error or continues with the scan, emitting discovered devices through the returned Observable.

Calling this method during an already ongoing scan is safe, the obtained Observable will not reemit devices which were discovered earlier during the scan.

adapter.startDeviceScan()
    .subscribe({ device ->
            // Process next discovered device
        }, { error ->
            // Handle error
        }, {
            // Scan complete
        }
    )

Device pairing

Having a BluetoothDevice object (e.g. obtained from a device scan), we can use the adapter's method pairDevice to start the pairing (bonding) process with that device.

The resulting Single returns true when pairing is successful (or the device is already paired with) and false when the process gets cancelled:

adapter.pairDevice(bluetoothDevice)
    .subscribe({ result ->
            // Process pairing result
        }, { error ->
            // Handle error
        }
    )

We can also query the adapter for already paired devices by accessing the field pairedDevices:

adapter.pairedDevices()
    .subscribe({ device ->
            // Do something with the paired device
        }, { error ->
            // Handle error
        }
    )

Connecting to a device

One of the main goals for this library was to provide a simple way of establishing serial port (SPP) connections to Bluetooth devices. Here's how we can connect to a remote BluetoothDevice using RxBluetoothAdapter:

adapter.connectToDevice(bluetoothDevice)
    .subscribe({ socket ->
        // Connection successful, save and/or use the obtained socket object
    }, { error ->
        // Connection failed, handle the error
    })

After obtaining a BluetoothSocket we can use it for two-way communication with the remote device. The communication itself is not part of the library, since the actual implementation will vary depending on the use case.

Observing events

RxBluetoothAdapter includes a reactive stream for monitoring the connection status of remote devices:

adapter.connectionEventStream
    .subscribe({ (state, device) ->
        when (state) {
            ConnectionState.CONNECTED -> Log.d("tag", "${device.address} - connected")
            ConnectionState.CONNECTING -> Log.d("tag", "${device.address} - connecting")
            ConnectionState.DISCONNECTED -> Log.d("tag", "${device.address} - disconnected")
        }
    })

This stream is based on broadcasts from the operating system (thanks to RxBroadcast). Certain events can also be emitted by RxBluetoothAdapter, e.g. ConnectionState.CONNECTED will be sent whenever a call to connectToDevice succeeds.

There is also a separate stream which can be used to watch the status of device scanning (i.e. if there is currently a device discovery in progress):

adapter.scanStateStream
    .subscribe({ isScanning ->
        // Do something depending on the state
    })

Both these streams are implemented using ReplaySubjects and will replay the last reported value to any new subscribers.

Installation

This library is available through JitPack. To use it, first add the JitPack Maven repository to your top level build.gradle like in the below example:

allprojects {
    repositories {
        . . .
        maven { url 'https://jitpack.io' }
    }
}

Once the repository is added, just add the following line to your application's build.gradle under dependencies:

implementation 'com.github.zakaprov:rx-bluetooth-adapter:1.1.1'

About

A reactive wrapper for Android's BluetoothAdapter.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages