Kotlin Bluetooth
Native Android ==> Bluetooth module
The Validic SDK introduces a Kotlin API for interacting with BluetoothPeripherals
and BluetoothDevices
. All BluetoothRequests
are executed using kotlin coroutines and are exposed as suspend functions.
Scanning
viewLifecycleScope.launch {
val request = ScanRequest(bluetoothPeripheral)
request.setOnStartHandler { Log.i("Bluetooth", "Starting scanning") }
request.setOnCompleteHandler { Log.i("Bluetooth", "Scanning completed" }
try {
val scanResult: BluetoothScanResult = request.enqueue()
} catch (e: ValidicBluetoothException) {
Log.w("Bluetooth", e.getMessage())
}
}
After retrieving instances of a BluetoothPeripheral
and BluetoothDevice
from a BluetoothScanResult
operations with a BluetoothPeripheral
and BluetoothDevice
are possible.
Pairing
viewLifecycleScope.launch {
val request = ScanRequest(bluetoothPeripheral)
request.onStart = object : OnStartHandler {
override fun onStart() {
Log.i("Bluetooth", "Scanning starting")
}
}
request.onCompleted = object : OnCompleteHandler {
override fun onComplete{
Log.i("Bluetooth", "Scanning completed")
}
}
try {
val scanResult: BluetoothScanResult = request.enqueue()
val readRequest: ReadRequest =
PairRequest(scanResult.bluetoothPeripheral, scanResult.bluetoothDevice)
readRequest.onStart = object : OnStartHandler {
override fun onStart() {
Log.i("Bluetooth", "Pairing starting")
}
}
readRequest.onCompleted = object : OnCompleteHandler {
override fun onComplete{
Log.i("Bluetooth", "Pairing completed"
}
}
val pairResult = request.enqueue()
} catch (e: ValidicBluetoothException) {
Log.w("Bluetooth", e.getMessage())
}
}
Reading
viewLifecycleScope.launch {
val request = ScanRequest(bluetoothPeripheral)
request.onStart = object : OnStartHandler {
override fun onStart() {
Log.i("Bluetooth", "Scanning starting")
}
}
request.onCompleted = object : OnCompleteHandler {
override fun onComplete{
Log.i("Bluetooth", "Reading completed")
}
}
try {
val scanResult: BluetoothScanResult = request.enqueue()
val readRequest: ReadRequest =
ReadRequest(scanResult.bluetoothPeripheral, scanResult.bluetoothDevice)
readRequest.onStart = object : OnStartHandler {
override fun onStart() {
Log.i("Bluetooth", "Reading starting")
}
}
readRequest.onCompleted = object : OnCompleteHandler {
override fun onComplete{
Log.i("Bluetooth", "Reading completed"
}
}
val readResult: ReadResult = request.enqueue()
} catch (e: ValidicBluetoothException) {
Log.w("Bluetooth", e.getMessage())
}
}
Passive Read
After a PairRequest
or a ReadRequest
completes successfully, it is possible to set up reading in the background for a specific device.
viewLifecycleScope.launch {
val request = ScanRequest(bluetoothPeripheral)
request.onStart = object : OnStartHandler {
override fun onStart() {
Log.i("Bluetooth", "Scanning starting")
}
}
request.onCompleted = object : OnCompleteHandler {
override fun onComplete{
Log.i("Bluetooth", "Reading completed")
}
}
try {
val scanResult: BluetoothScanResult = request.enqueue()
val readRequest: ReadRequest =
ReadRequest(scanResult.bluetoothPeripheral, scanResult.bluetoothDevice)
readRequest.onStart = object : OnStartHandler {
override fun onStart() {
Log.i("Bluetooth", "Reading starting")
}
}
readRequest.onCompleted = object : OnCompleteHandler {
override fun onComplete{
Log.i("Bluetooth", "Reading completed"
}
}
val readResult: ReadResult = request.enqueue()
Log.i("Bluetooth", "Reading success")
val monitorRequest: MonitorDeviceRequest =
MonitorDeviceRequest(readResult.bluetoothPeripheral, true);
val monitorDeviceResult = monitorRequest.enqueue()
Log.i("Bluetooth", "Enabled monitoring device in the background")
val disableRequest =
MonitorDeviceRequest = MonitorDeviceRequest(readResult.bluetoothPeripheral, false);
Log.i("Bluetooth", "Disabled monitoring device in the background")
} catch (e: ValidicBluetoothException) {
Log.w("Bluetooth", e.getMessage())
}
}
To capture which devices are currently being monitored in the background, query the PassiveBluetoothManager.monitoredDevices
property.
val devices: Set<String> = PassiveBluetoothManager.getInstance(context).getMonitoredDevices()
Listening for events can be accomplished setting a BluetoothListener on the PassiveBluetoothManager as described in the above section.
Java Interop
BluetoothRequests
can be consumed in java clients by converting the request to a JDK CompletableFuture, ListenableFuture
or Single
depending on which async library is added to the client dependencies.
// app/build.gradle
dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-rx2:1.8.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.8.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.8.0"
}
ListenableFuture
ExecutorService service = Executors.newSingleThreadExecutor();
try {
ListenableFuture<BluetoothScanResult> resultFuture = ValidicBluetoothKt.asListenableFuture(new ScanRequest(BluetoothPeripheral.getPeripheralForID(1)));
resultFuture.addListener(()->{
try {
BluetoothScanResult result = resultFuture.get();
Log.i("Bluetooth", result.getDevice().getAddress());
} catch (ExecutionException e) {
e.printStackTrace();
}
}, service);
} catch (ValidicBluetoothException bluetoothException) {
bluetoothException.printStackTrace();
}
CompletableFuture
ExecutorService service = Executors.newSingleThreadExecutor();
try {
CompletableFuture<BluetoothScanResult> resultFuture = ValidicBluetoothKt.asCompletableFuture(new ScanRequest(BluetoothPeripheral.getPeripheralForID(1)));
} catch (InterruptedException e) {
e.printStackTrace();
resultFuture.handleAsync((result, throwable)->{
if(throwable!=null){ Log.e(throwable) }
else {Log.i("Bluetooth", result.getDevice().getAddress()); }
}, service);
} catch (ValidicBluetoothException bluetoothException) {
bluetoothException.printStackTrace();
}
RxJava Single
Disposable disposable = null;
Single<BluetoothScanResult> resultSingle = ValidicBluetoothKt.asRxSingle(new ScanRequest(BluetoothPeripheral.getPeripheralForID(1)));
disposable = resultSingle.subscribe(result, throwable)->{
if(throwable!=null){ Log.e(throwable) }
else {Log.i("Bluetooth", result.getDevice().getAddress()); }
});
Special Considerations
Most supported Bluetooth devices function similarly and you can follow the instructions on this page to work with them using the Kotlin API.
However, a few of our supported devices have additional requirements and/or considerations that you need to be aware of. Those are covered in Bluetooth Behavior.
Updated 4 days ago