Skip to content

Commit c58d57a

Browse files
authored
Add support for service filtering during scanning (#117)
1 parent 5e1bfda commit c58d57a

6 files changed

Lines changed: 41 additions & 11 deletions

File tree

core/api/core.api

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,8 @@ public abstract interface class com/juul/kable/Scanner {
220220
}
221221

222222
public final class com/juul/kable/ScannerKt {
223-
public static final fun Scanner ()Lcom/juul/kable/Scanner;
223+
public static final fun Scanner (Ljava/util/List;)Lcom/juul/kable/Scanner;
224+
public static synthetic fun Scanner$default (Ljava/util/List;ILjava/lang/Object;)Lcom/juul/kable/Scanner;
224225
}
225226

226227
public abstract interface class com/juul/kable/Service {

core/src/androidMain/kotlin/Scanner.kt

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,25 @@ package com.juul.kable
22

33
import android.bluetooth.BluetoothAdapter
44
import android.bluetooth.le.ScanCallback
5+
import android.bluetooth.le.ScanFilter
56
import android.bluetooth.le.ScanResult
7+
import android.bluetooth.le.ScanSettings
8+
import android.os.ParcelUuid
69
import android.util.Log
10+
import com.benasher44.uuid.Uuid
711
import kotlinx.coroutines.cancel
812
import kotlinx.coroutines.channels.awaitClose
913
import kotlinx.coroutines.channels.sendBlocking
1014
import kotlinx.coroutines.flow.Flow
1115
import kotlinx.coroutines.flow.callbackFlow
1216

1317
public class ScanFailedException internal constructor(
14-
public val errorCode: Int
18+
public val errorCode: Int,
1519
) : IllegalStateException("Bluetooth scan failed with error code $errorCode")
1620

17-
public actual fun Scanner(): Scanner = AndroidScanner()
21+
public actual fun Scanner(services: List<Uuid>?): Scanner = AndroidScanner(services)
1822

19-
public class AndroidScanner internal constructor() : Scanner {
23+
public class AndroidScanner internal constructor(private val filterServices: List<Uuid>?) : Scanner {
2024

2125
private val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
2226
?: error("Bluetooth not supported")
@@ -47,7 +51,17 @@ public class AndroidScanner internal constructor() : Scanner {
4751
cancel("Bluetooth scan failed", ScanFailedException(errorCode))
4852
}
4953
}
50-
bluetoothAdapter.bluetoothLeScanner.startScan(callback)
54+
55+
val scanFilter =
56+
filterServices
57+
?.map { ScanFilter.Builder().setServiceUuid(ParcelUuid(it)).build() }
58+
?.toList()
59+
bluetoothAdapter.bluetoothLeScanner.startScan(
60+
scanFilter,
61+
ScanSettings.Builder().build(),
62+
callback,
63+
)
64+
5165
awaitClose {
5266
bluetoothAdapter.bluetoothLeScanner.stopScan(callback)
5367
}

core/src/appleMain/kotlin/CentralManager.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ public class CentralManager internal constructor() {
2929
options: Map<Any?, *>?,
3030
) {
3131
withContext(dispatcher) {
32-
cbCentralManager.scanForPeripheralsWithServices(services, options)
32+
cbCentralManager.scanForPeripheralsWithServices(
33+
serviceUUIDs = services?.map { it.toCBUUID() },
34+
options = options,
35+
)
3336
}
3437
}
3538

core/src/appleMain/kotlin/Scanner.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ import platform.CoreBluetooth.CBManagerStatePoweredOn
1313
import platform.CoreBluetooth.CBManagerStateUnauthorized
1414
import platform.CoreBluetooth.CBManagerStateUnsupported
1515

16-
public actual fun Scanner(): Scanner = AppleScanner(CentralManager.Default, services = null)
16+
public actual fun Scanner(services: List<Uuid>?): Scanner = AppleScanner(
17+
central = CentralManager.Default,
18+
services = services,
19+
)
1720

1821
public class AppleScanner internal constructor(
1922
central: CentralManager,
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
package com.juul.kable
22

3+
import com.benasher44.uuid.Uuid
34
import kotlinx.coroutines.flow.Flow
45

56
public interface Scanner {
67
public val advertisements: Flow<Advertisement>
78
}
89

9-
// todo: Add support for specifying services to filter against (for platforms that support it).
10-
// https://github.com/JuulLabs/kable/issues/22
11-
public expect fun Scanner(): Scanner
10+
public expect fun Scanner(services: List<Uuid>? = null): Scanner

core/src/jsMain/kotlin/Scanner.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.juul.kable
22

3+
import com.benasher44.uuid.Uuid
34
import com.juul.kable.external.Bluetooth
45
import com.juul.kable.external.BluetoothAdvertisingEvent
56
import kotlinx.coroutines.await
@@ -11,7 +12,16 @@ import org.w3c.dom.events.Event
1112

1213
private const val ADVERTISEMENT_RECEIVED_EVENT = "advertisementreceived"
1314

14-
public actual fun Scanner(): Scanner = JsScanner(bluetooth, Options())
15+
public actual fun Scanner(services: List<Uuid>?): Scanner {
16+
val filters = services
17+
?.map { it.toString() }
18+
?.toTypedArray()
19+
?.let { arrayOf<Options.Filter>(Options.Filter.Services(it)) }
20+
return JsScanner(
21+
bluetooth = bluetooth,
22+
options = Options(filters = filters),
23+
)
24+
}
1525

1626
/**
1727
* Only available on Chrome 79+ with "Experimental Web Platform features" enabled via:

0 commit comments

Comments
 (0)