feat: sensors can be bonded
Known issue: app enters an unrecoverable state if a pairing PIN with less than 6 digits is entered.
This commit is contained in:
@@ -3,15 +3,23 @@ package com.example.sensortestingapp
|
||||
import android.annotation.SuppressLint
|
||||
import android.bluetooth.BluetoothAdapter
|
||||
import android.bluetooth.BluetoothDevice
|
||||
import android.bluetooth.BluetoothDevice.BOND_BONDED
|
||||
import android.bluetooth.BluetoothDevice.BOND_BONDING
|
||||
import android.bluetooth.BluetoothDevice.BOND_NONE
|
||||
import android.bluetooth.BluetoothGatt
|
||||
import android.bluetooth.BluetoothGatt.GATT_SUCCESS
|
||||
import android.bluetooth.BluetoothGattCallback
|
||||
import android.bluetooth.BluetoothGattCharacteristic
|
||||
import android.bluetooth.BluetoothGattDescriptor
|
||||
import android.bluetooth.BluetoothProfile
|
||||
import android.bluetooth.BluetoothProfile.STATE_DISCONNECTED
|
||||
import android.bluetooth.le.ScanCallback
|
||||
import android.bluetooth.le.ScanResult
|
||||
import android.bluetooth.le.ScanSettings
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.util.Log
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
@@ -62,6 +70,18 @@ data class DiscoverServicesRequest(
|
||||
override val device: BluetoothDevice,
|
||||
) : BleOperationType()
|
||||
|
||||
data class BondRequest(
|
||||
override val device: BluetoothDevice,
|
||||
) : BleOperationType()
|
||||
|
||||
data class UnbondRequest(
|
||||
override val device: BluetoothDevice,
|
||||
) : BleOperationType()
|
||||
|
||||
data class ReadRemoteRssi(
|
||||
override val device: BluetoothDevice,
|
||||
) : BleOperationType()
|
||||
|
||||
|
||||
open class BleListener(private val deviceAddress: String?) {
|
||||
|
||||
@@ -74,6 +94,8 @@ open class BleListener(private val deviceAddress: String?) {
|
||||
|
||||
open fun onConnect(gatt: BluetoothGatt) {}
|
||||
|
||||
open fun onConnectToBondedFailed(gatt: BluetoothGatt) {}
|
||||
|
||||
open fun onDisconnect(gatt: BluetoothGatt) {}
|
||||
|
||||
open fun onSuccessfulCharRead(
|
||||
@@ -112,6 +134,18 @@ open class BleListener(private val deviceAddress: String?) {
|
||||
|
||||
}
|
||||
|
||||
open fun onBonded(device: BluetoothDevice) {
|
||||
|
||||
}
|
||||
|
||||
open fun onUnbonded(device: BluetoothDevice) {
|
||||
|
||||
}
|
||||
|
||||
open fun onReadRemoteRssi(gatt: BluetoothGatt, rssi: Int) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -179,6 +213,69 @@ class ConnectionManager(val context: Context, bleAdapter: BluetoothAdapter) {
|
||||
bleAdapter.bluetoothLeScanner
|
||||
}
|
||||
|
||||
init {
|
||||
val broadcastReceiver = object : BroadcastReceiver() {
|
||||
|
||||
private fun successfulBondingAttempt(prev: Int, curr: Int): Boolean {
|
||||
return prev == BOND_BONDING && curr == BOND_BONDED || prev == BOND_NONE && curr == BOND_BONDED
|
||||
}
|
||||
|
||||
private fun unsuccessfulBondingAttempt(prev: Int, curr: Int): Boolean {
|
||||
return prev == BOND_BONDING && curr == BOND_NONE
|
||||
}
|
||||
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (intent.action == BluetoothDevice.ACTION_BOND_STATE_CHANGED) {
|
||||
val device =
|
||||
intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)!!
|
||||
val previousBondState =
|
||||
intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, -1)
|
||||
val bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1)
|
||||
val bondTransition = "${previousBondState.toBondStateDescription()} to " +
|
||||
bondState.toBondStateDescription()
|
||||
Log.i(
|
||||
"ConnectionManager",
|
||||
"${device.address} bond state changed | $bondTransition"
|
||||
)
|
||||
|
||||
if (bondState == BOND_BONDED) {
|
||||
notifyListeners(device.address) { it.onBonded(device) }
|
||||
}
|
||||
if (bondState == BOND_NONE) {
|
||||
notifyListeners(device.address) { it.onUnbonded(device) }
|
||||
}
|
||||
|
||||
val operation = pendingOperation
|
||||
if (
|
||||
(operation is BondRequest && (successfulBondingAttempt(
|
||||
previousBondState, bondState
|
||||
) || unsuccessfulBondingAttempt(
|
||||
previousBondState, bondState
|
||||
)) || operation is UnbondRequest && bondState == BOND_NONE)
|
||||
&& operation.device.address == device.address
|
||||
) {
|
||||
signalEndOfOperation(operation)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun Int.toBondStateDescription() = when (this) {
|
||||
BOND_BONDED -> "BONDED"
|
||||
BOND_BONDING -> "BONDING"
|
||||
BOND_NONE -> "NOT BONDED"
|
||||
else -> "ERROR: $this"
|
||||
}
|
||||
}
|
||||
|
||||
context.registerReceiver(
|
||||
broadcastReceiver,
|
||||
IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED)
|
||||
)
|
||||
}
|
||||
|
||||
var isScanning = false
|
||||
set(value) {
|
||||
field = value
|
||||
@@ -260,6 +357,18 @@ class ConnectionManager(val context: Context, bleAdapter: BluetoothAdapter) {
|
||||
enqueueOperation(SetNotification(device, service, char, false))
|
||||
}
|
||||
|
||||
fun bond(device: BluetoothDevice) {
|
||||
enqueueOperation(BondRequest(device))
|
||||
}
|
||||
|
||||
fun unbond(device: BluetoothDevice) {
|
||||
enqueueOperation(UnbondRequest(device))
|
||||
}
|
||||
|
||||
fun readRemoteRssi(device: BluetoothDevice) {
|
||||
enqueueOperation(ReadRemoteRssi(device))
|
||||
}
|
||||
|
||||
|
||||
// - Beginning of PRIVATE functions
|
||||
|
||||
@@ -325,10 +434,52 @@ class ConnectionManager(val context: Context, bleAdapter: BluetoothAdapter) {
|
||||
return
|
||||
}
|
||||
|
||||
if (operation is BondRequest) {
|
||||
if (operation.device.bondState == BOND_NONE) {
|
||||
if (!operation.device.createBond()) {
|
||||
Log.e(
|
||||
"ConnectionManager", "createBond() returned false " +
|
||||
"for device ${operation.device.address}"
|
||||
)
|
||||
signalEndOfOperation(operation)
|
||||
}
|
||||
} else {
|
||||
Log.e(
|
||||
"ConnectionManager",
|
||||
"BondRequest for device ${operation.device.address} aborted. " +
|
||||
"operation.device.bondState (${operation.device.bondState}) == BOND_NONE (${BOND_NONE})"
|
||||
)
|
||||
signalEndOfOperation(operation)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (operation is UnbondRequest) {
|
||||
if (operation.device.bondState == BOND_BONDED) {
|
||||
val method = operation.device.javaClass.getMethod("removeBond")
|
||||
val removeBondSuccessful = method.invoke(operation.device) as Boolean
|
||||
if (!removeBondSuccessful) {
|
||||
Log.e(
|
||||
"ConnectionManager", "removeBond() returned false " +
|
||||
"for device ${operation.device.address}"
|
||||
)
|
||||
signalEndOfOperation(operation)
|
||||
}
|
||||
} else {
|
||||
Log.e(
|
||||
"ConnectionManager",
|
||||
"UnbondRequest for device ${operation.device.address} aborted. " +
|
||||
"operation.device.bondState (${operation.device.bondState}) == BOND_BONDED (${BOND_BONDED})"
|
||||
)
|
||||
signalEndOfOperation(operation)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Check BluetoothGatt availability for other operations
|
||||
val gatt = deviceGattMap[operation.device]
|
||||
?: this@ConnectionManager.run {
|
||||
Log.e(
|
||||
Log.w(
|
||||
"ConnectionManager",
|
||||
"Not connected to ${operation.device.address}! Aborting $operation operation."
|
||||
)
|
||||
@@ -419,11 +570,15 @@ class ConnectionManager(val context: Context, bleAdapter: BluetoothAdapter) {
|
||||
}
|
||||
}
|
||||
|
||||
is ReadRemoteRssi -> {
|
||||
gatt.readRemoteRssi()
|
||||
}
|
||||
|
||||
|
||||
// necessary because of IDE type inference bug
|
||||
// https://youtrack.jetbrains.com/issue/KTIJ-20749/Exhaustive-when-check-does-not-take-into-account-the-values-excluded-by-previous-if-conditions
|
||||
is Connect -> {
|
||||
Log.e("ConnectionManager", "Shouldn't get here")
|
||||
is Connect, is BondRequest, is UnbondRequest -> {
|
||||
Log.e("ConnectionManager", "Shouldn't get here: $operation")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -431,8 +586,24 @@ class ConnectionManager(val context: Context, bleAdapter: BluetoothAdapter) {
|
||||
private val callback = object : BluetoothGattCallback() {
|
||||
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
|
||||
val deviceAddress = gatt.device.address
|
||||
val operation = pendingOperation
|
||||
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
if (operation is Connect
|
||||
&& operation.device.bondState == BOND_BONDED
|
||||
&& deviceAddress == operation.device.address
|
||||
&& status == 133
|
||||
&& newState == STATE_DISCONNECTED
|
||||
) {
|
||||
Log.i(
|
||||
"ConnectionManager",
|
||||
"onConnectionStateChange: Timeout when connecting to bonded device $deviceAddress. " +
|
||||
"Device probably not in vicinity."
|
||||
)
|
||||
notifyListeners(gatt.device.address) {
|
||||
it.onConnectToBondedFailed(gatt)
|
||||
}
|
||||
signalEndOfOperation(operation)
|
||||
} else if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
if (newState == BluetoothProfile.STATE_CONNECTED) {
|
||||
Log.i(
|
||||
"ConnectionManager",
|
||||
@@ -442,11 +613,11 @@ class ConnectionManager(val context: Context, bleAdapter: BluetoothAdapter) {
|
||||
notifyListeners(gatt.device.address) {
|
||||
it.onConnect(gatt)
|
||||
}
|
||||
val operation = pendingOperation
|
||||
|
||||
if (operation is Connect) {
|
||||
signalEndOfOperation(operation)
|
||||
}
|
||||
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
|
||||
} else if (newState == STATE_DISCONNECTED) {
|
||||
Log.e(
|
||||
"ConnectionManager",
|
||||
"onConnectionStateChange: disconnected from $deviceAddress"
|
||||
@@ -579,6 +750,20 @@ class ConnectionManager(val context: Context, bleAdapter: BluetoothAdapter) {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onReadRemoteRssi(gatt: BluetoothGatt, rssi: Int, status: Int) {
|
||||
if (status == GATT_SUCCESS) {
|
||||
notifyListeners(gatt.device.address) { it.onReadRemoteRssi(gatt, rssi) }
|
||||
} else {
|
||||
Log.e(
|
||||
"BluetoothGattCallback",
|
||||
"ReadRemoteRssi failed for ${gatt.device.address}, error: $status"
|
||||
)
|
||||
}
|
||||
val op = pendingOperation
|
||||
if (op is ReadRemoteRssi && gatt.device.address == op.device.address) {
|
||||
signalEndOfOperation(op)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ interface Measurement {
|
||||
interface DeviceListEntry {
|
||||
val address: String
|
||||
|
||||
var rssi: Int
|
||||
var rssi: Int?
|
||||
|
||||
val name: String?
|
||||
|
||||
@@ -80,14 +80,17 @@ class DeviceListAdapter(
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
fun bind(result: DeviceListEntry) {
|
||||
val rssi = result.rssi
|
||||
deviceNameView.text = result.name ?: "<N/A>"
|
||||
deviceProgress.visibility = if (result.hasRunningOp) VISIBLE else INVISIBLE
|
||||
macAddressView.text = result.address
|
||||
signalStrengthView.text = "${result.rssi ?: "-"} dBm"
|
||||
signalStrengthView.text = "${rssi ?: "-"} dBm"
|
||||
var signalStrengthIcon = R.drawable.signal_strength_weak
|
||||
if (result.rssi >= -55) {
|
||||
if (rssi == null) {
|
||||
signalStrengthIcon = R.drawable.signal_strength_none
|
||||
} else if (rssi >= -55) {
|
||||
signalStrengthIcon = R.drawable.signal_strength_strong
|
||||
} else if (result.rssi >= -80) {
|
||||
} else if (rssi >= -80) {
|
||||
signalStrengthIcon = R.drawable.signal_strength_medium
|
||||
}
|
||||
signalStrengthView.setCompoundDrawablesWithIntrinsicBounds(
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.example.sensortestingapp
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.bluetooth.BluetoothDevice
|
||||
import android.bluetooth.BluetoothDevice.BOND_BONDED
|
||||
import android.bluetooth.BluetoothGatt
|
||||
import android.bluetooth.BluetoothGattCharacteristic
|
||||
import android.bluetooth.BluetoothGattDescriptor
|
||||
@@ -15,6 +16,7 @@ import java.util.EnumSet
|
||||
import java.util.UUID
|
||||
import java.util.stream.Collectors
|
||||
|
||||
|
||||
private val DEMO_SERVICE_UUID = UUID.fromString("00000000-0001-11E1-9AB4-0002A5D5C51B")
|
||||
private val DEMO_CHAR_UUID = UUID.fromString("00140000-0001-11E1-AC36-0002A5D5C51B")
|
||||
|
||||
@@ -92,26 +94,30 @@ private fun demoPayloadToMeasurements(payload: DemoPayload): List<Measurement> {
|
||||
}
|
||||
|
||||
enum class DeviceStatus {
|
||||
DISCOVERED, CONNECTED, BONDED, SUBSCRIBED
|
||||
CONNECTED, BONDED, SUBSCRIBED, MISSING
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
class KirbyDevice(
|
||||
private val connectionManager: ConnectionManager,
|
||||
private val bleDevice: BluetoothDevice,
|
||||
initialRssi: Int,
|
||||
override var hasRunningOp: Boolean = false,
|
||||
private val onStateChange: (device: KirbyDevice) -> Unit
|
||||
) : BleListener(bleDevice.address), DeviceListEntry {
|
||||
|
||||
|
||||
override fun onScanResult(callbackType: Int, result: ScanResult) {
|
||||
statuses.add(DeviceStatus.DISCOVERED)
|
||||
rssi = result.rssi
|
||||
onStateChange(this)
|
||||
}
|
||||
|
||||
override fun onConnect(gatt: BluetoothGatt) {
|
||||
statuses.add(DeviceStatus.CONNECTED)
|
||||
statuses.remove(DeviceStatus.MISSING)
|
||||
onStateChange(this)
|
||||
}
|
||||
|
||||
override fun onConnectToBondedFailed(gatt: BluetoothGatt) {
|
||||
statuses.add(DeviceStatus.MISSING)
|
||||
onStateChange(this)
|
||||
}
|
||||
|
||||
@@ -131,7 +137,6 @@ class KirbyDevice(
|
||||
|
||||
override fun onCharChange(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
|
||||
addMeasurement(characteristic)
|
||||
//statuses.add(DeviceStatus.SUBSCRIBED)
|
||||
onStateChange(this)
|
||||
}
|
||||
|
||||
@@ -153,11 +158,25 @@ class KirbyDevice(
|
||||
onStateChange(this)
|
||||
}
|
||||
|
||||
override var rssi = initialRssi
|
||||
set(value) {
|
||||
field = value
|
||||
onStateChange(this)
|
||||
}
|
||||
override fun onBonded(device: BluetoothDevice) {
|
||||
statuses.add(DeviceStatus.BONDED)
|
||||
onStateChange(this)
|
||||
}
|
||||
|
||||
override fun onUnbonded(device: BluetoothDevice) {
|
||||
statuses.remove(DeviceStatus.BONDED)
|
||||
onStateChange(this)
|
||||
}
|
||||
|
||||
override fun onReadRemoteRssi(gatt: BluetoothGatt, rssi: Int) {
|
||||
this.rssi = rssi
|
||||
onStateChange(this)
|
||||
}
|
||||
|
||||
override var hasRunningOp: Boolean = false
|
||||
|
||||
override var rssi: Int? = null
|
||||
|
||||
|
||||
private fun addMeasurement(characteristic: BluetoothGattCharacteristic) {
|
||||
if (characteristic.service.uuid == DEMO_SERVICE_UUID && characteristic.uuid == DEMO_CHAR_UUID) {
|
||||
@@ -171,6 +190,12 @@ class KirbyDevice(
|
||||
|
||||
private val statuses = EnumSet.noneOf(DeviceStatus::class.java)
|
||||
|
||||
init {
|
||||
if (bleDevice.bondState == BOND_BONDED) {
|
||||
statuses.add(DeviceStatus.BONDED)
|
||||
}
|
||||
}
|
||||
|
||||
override val address: String
|
||||
get() = bleDevice.address
|
||||
|
||||
@@ -181,10 +206,6 @@ class KirbyDevice(
|
||||
override val status: String?
|
||||
get() = statuses.stream().map { it.name }.collect(Collectors.joining(", "))
|
||||
|
||||
// override fun getRssi(): Int? {
|
||||
// return rssi
|
||||
// }
|
||||
|
||||
override fun getMeasurements(): List<Measurement> {
|
||||
if (measurements.isEmpty()) {
|
||||
return emptyList()
|
||||
@@ -195,7 +216,23 @@ class KirbyDevice(
|
||||
|
||||
override fun getActions(): List<Action> {
|
||||
val actions = mutableListOf<Action>()
|
||||
if (statuses.contains(DeviceStatus.DISCOVERED) && !statuses.contains(DeviceStatus.CONNECTED)
|
||||
if (!statuses.contains(DeviceStatus.BONDED)) {
|
||||
actions.add(object : Action {
|
||||
override fun getLabel(): String {
|
||||
return "Bond"
|
||||
}
|
||||
|
||||
override fun getIcon(): Int {
|
||||
return R.drawable.action_icon_bond
|
||||
}
|
||||
|
||||
override fun execute() {
|
||||
connectionManager.bond(bleDevice)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (!statuses.contains(DeviceStatus.CONNECTED)
|
||||
) {
|
||||
actions.add(object : Action {
|
||||
override fun getLabel(): String {
|
||||
@@ -208,6 +245,7 @@ class KirbyDevice(
|
||||
|
||||
override fun execute() {
|
||||
connectionManager.connect(bleDevice)
|
||||
connectionManager.readRemoteRssi(bleDevice)
|
||||
connectionManager.discoverServices(bleDevice)
|
||||
}
|
||||
})
|
||||
@@ -260,6 +298,21 @@ class KirbyDevice(
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
actions.add(object : Action {
|
||||
override fun getLabel(): String {
|
||||
return "Update Signal Strength"
|
||||
}
|
||||
|
||||
override fun getIcon(): Int {
|
||||
return R.drawable.action_icon_update_signal_strength
|
||||
}
|
||||
|
||||
override fun execute() {
|
||||
connectionManager.readRemoteRssi(bleDevice)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
if (statuses.contains(DeviceStatus.SUBSCRIBED)) {
|
||||
@@ -280,6 +333,22 @@ class KirbyDevice(
|
||||
})
|
||||
}
|
||||
|
||||
if (statuses.contains(DeviceStatus.BONDED)
|
||||
) {
|
||||
actions.add(object : Action {
|
||||
override fun getLabel(): String {
|
||||
return "Unbond"
|
||||
}
|
||||
|
||||
override fun getIcon(): Int {
|
||||
return R.drawable.action_icon_unbond
|
||||
}
|
||||
|
||||
override fun execute() {
|
||||
connectionManager.unbond(bleDevice)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.bluetooth.BluetoothAdapter
|
||||
import android.bluetooth.BluetoothDevice
|
||||
import android.bluetooth.BluetoothManager
|
||||
import android.bluetooth.le.ScanResult
|
||||
import android.content.Context
|
||||
@@ -22,8 +23,6 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator
|
||||
import com.example.sensortestingapp.databinding.ActivityMainBinding
|
||||
|
||||
@@ -91,21 +90,24 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
}
|
||||
|
||||
private fun isKirbyDevice(device: BluetoothDevice): Boolean {
|
||||
return (device.name ?: "").lowercase().contains("kirby")
|
||||
}
|
||||
|
||||
private fun setupDevicesList() {
|
||||
binding.devicesList.apply {
|
||||
adapter = deviceListAdapter
|
||||
layoutManager = LinearLayoutManager(
|
||||
this@MainActivity,
|
||||
RecyclerView.VERTICAL,
|
||||
false
|
||||
)
|
||||
//isNestedScrollingEnabled = false
|
||||
}
|
||||
|
||||
val animator = binding.devicesList.itemAnimator
|
||||
if (animator is SimpleItemAnimator) {
|
||||
animator.supportsChangeAnimations = false
|
||||
}
|
||||
|
||||
bluetoothAdapter.bondedDevices.filter { isKirbyDevice(it) }.forEach {
|
||||
newKirbyDevice(it)
|
||||
}
|
||||
|
||||
//addDummyDevices()
|
||||
}
|
||||
|
||||
@@ -131,7 +133,7 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
override fun onScanResult(callbackType: Int, result: ScanResult) {
|
||||
if ((result.device.name ?: "").lowercase().contains("kirby")) {
|
||||
if (isKirbyDevice(result.device)) {
|
||||
|
||||
Log.i(
|
||||
"ScanCallback",
|
||||
@@ -139,9 +141,7 @@ class MainActivity : AppCompatActivity() {
|
||||
)
|
||||
val kirbyDevice = kirbyDevices.find { it.address == result.device.address }
|
||||
if (kirbyDevice == null) {
|
||||
newKirbyDevice(callbackType, result)
|
||||
} else {
|
||||
kirbyDevice.rssi = result.rssi
|
||||
newKirbyDevice(result.device).onScanResult(callbackType, result)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -150,8 +150,8 @@ class MainActivity : AppCompatActivity() {
|
||||
return mngr
|
||||
}
|
||||
|
||||
private fun newKirbyDevice(callbackType: Int, scanResult: ScanResult): KirbyDevice {
|
||||
val device = KirbyDevice(connectionManager, scanResult.device, scanResult.rssi) {
|
||||
private fun newKirbyDevice(bleDevice: BluetoothDevice): KirbyDevice {
|
||||
val device = KirbyDevice(connectionManager, bleDevice) {
|
||||
val i = kirbyDevices.indexOfFirst { d -> d === it }
|
||||
runOnUiThread {
|
||||
deviceListAdapter.notifyItemChanged(i)
|
||||
@@ -159,7 +159,6 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
connectionManager.register(device)
|
||||
kirbyDevices.add(device)
|
||||
device.onScanResult(callbackType, scanResult)
|
||||
deviceListAdapter.notifyItemInserted(kirbyDevices.size - 1)
|
||||
return device
|
||||
}
|
||||
@@ -169,8 +168,6 @@ class MainActivity : AppCompatActivity() {
|
||||
requestRelevantRuntimePermissions()
|
||||
} else {
|
||||
connectionManager.startScan()
|
||||
// kirbyDevices.clear()
|
||||
//deviceListAdapter.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +329,7 @@ class MainActivity : AppCompatActivity() {
|
||||
@SuppressLint("MissingPermission")
|
||||
class DummyListEntry(override val address: String) : DeviceListEntry {
|
||||
|
||||
override var rssi: Int = -30
|
||||
override var rssi: Int? = -30
|
||||
|
||||
override val name: String = "Device 123"
|
||||
override val status: String
|
||||
|
||||
Reference in New Issue
Block a user