diff --git a/android/src/main/java/com/capacitorjs/community/plugins/bluetoothle/Device.kt b/android/src/main/java/com/capacitorjs/community/plugins/bluetoothle/Device.kt index 4ea465b6..5f32fd2b 100644 --- a/android/src/main/java/com/capacitorjs/community/plugins/bluetoothle/Device.kt +++ b/android/src/main/java/com/capacitorjs/community/plugins/bluetoothle/Device.kt @@ -10,12 +10,33 @@ import android.os.Handler import android.os.Looper import com.getcapacitor.Logger import java.util.* +import java.util.concurrent.ConcurrentLinkedQueue +import java.util.concurrent.atomic.AtomicReference class CallbackResponse( val success: Boolean, val value: String, ) +class TimeoutHandler( + val key: String, + val handler: Handler +) + +fun ConcurrentLinkedQueue.popFirstMatch(predicate: (T) -> Boolean): T? { + synchronized(this) { + val iterator = this.iterator() + while (iterator.hasNext()) { + val nextItem = iterator.next() + if (predicate(nextItem)) { + iterator.remove() + return nextItem + } + } + return null + } +} + class Device( private val context: Context, bluetoothAdapter: BluetoothAdapter, @@ -35,7 +56,7 @@ class Device( private var device: BluetoothDevice = bluetoothAdapter.getRemoteDevice(address) private var bluetoothGatt: BluetoothGatt? = null private var callbackMap = HashMap Unit)>() - private var timeoutMap = HashMap() + private val timeoutQueue = ConcurrentLinkedQueue() private var bondStateReceiver: BroadcastReceiver? = null private var currentMtu = -1 @@ -510,20 +531,19 @@ class Device( private fun resolve(key: String, value: String) { if (callbackMap.containsKey(key)) { Logger.debug(TAG, "resolve: $key $value") + + timeoutQueue.popFirstMatch { it.key == key }?.handler?.removeCallbacksAndMessages(null) callbackMap[key]?.invoke(CallbackResponse(true, value)) callbackMap.remove(key) - timeoutMap[key]?.removeCallbacksAndMessages(null) - timeoutMap.remove(key) } } private fun reject(key: String, value: String) { if (callbackMap.containsKey(key)) { Logger.debug(TAG, "reject: $key $value") + timeoutQueue.popFirstMatch { it.key == key }?.handler?.removeCallbacksAndMessages(null) callbackMap[key]?.invoke(CallbackResponse(false, value)) callbackMap.remove(key) - timeoutMap[key]?.removeCallbacksAndMessages(null) - timeoutMap.remove(key) } } @@ -531,7 +551,7 @@ class Device( key: String, message: String, timeout: Long ) { val handler = Handler(Looper.getMainLooper()) - timeoutMap[key] = handler + timeoutQueue.add(TimeoutHandler(key, handler)) handler.postDelayed({ reject(key, message) }, timeout) @@ -544,7 +564,7 @@ class Device( timeout: Long, ) { val handler = Handler(Looper.getMainLooper()) - timeoutMap[key] = handler + timeoutQueue.add(TimeoutHandler(key, handler)) handler.postDelayed({ connectionState = STATE_DISCONNECTED gatt?.disconnect()