32feet
32feet copied to clipboard
"BluetoothClient.DiscoverDevicesAsync" This method does not work correctly on the Android platform
I'm using classic bluetooth, developing on the Android platform, and my intended goal is to call my callback method when a bluetooth device is discovered, but using the DiscoverDevicesAsync method doesn't work. Using DiscoverDevices is correct, but need to wait 30 seconds before the results are returned, and I don't want to use such a synchronous method.
Can you explain "does not work correctly" in more detail please?
"does not work correctly" It means I cannot receive any BluetoothDeviceInfo, if I use sync method I can receive the BluetoothDeviceInfo discovered by the device as expected.
So I checked the code and I found something...... In the class '../Platforms/Android/BluetoothClient.android.cs'. public async IAsyncEnumerable<BluetoothDeviceInfo> DiscoverDevicesAsync([EnumeratorCancellation] CancellationToken cancellationToken) { if (InTheHand.AndroidActivity.CurrentActivity == null) throw new NotSupportedException("CurrentActivity was not detected or specified");
List<BluetoothDeviceInfo> devices = new List<BluetoothDeviceInfo>();
var waitable = new AutoResetEvent(false);
HandlerThread handlerThread = new HandlerThread("ht");
handlerThread.Start();
Looper looper = handlerThread.Looper;
Handler handler = new Handler(looper);
BluetoothDiscoveryReceiver receiver = new BluetoothDiscoveryReceiver();
IntentFilter filter = new IntentFilter();
filter.AddAction(BluetoothDevice.ActionFound);
filter.AddAction(BluetoothAdapter.ActionDiscoveryFinished);
filter.AddAction(BluetoothAdapter.ActionDiscoveryStarted);
InTheHand.AndroidActivity.CurrentActivity.RegisterReceiver(receiver, filter, null, handler);
EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.AutoReset);
receiver.DeviceFound += (s, e) =>
{
var bdi = new AndroidBluetoothDeviceInfo(e);
if (cancellationToken.IsCancellationRequested)
{
((BluetoothAdapter)_radio).CancelDiscovery();
}
else
{
if (!devices.Contains(bdi))
{
devices.Add(bdi);
waitable.Set();
}
}
};
((BluetoothAdapter)_radio).StartDiscovery();
receiver.DiscoveryComplete += (s, e) =>
{
InTheHand.AndroidActivity.CurrentActivity.UnregisterReceiver(receiver);
handle.Set();
handlerThread.QuitSafely();
waitable.Set();
};
handle.WaitOne();
while(((BluetoothAdapter)_radio).IsDiscovering && !cancellationToken.IsCancellationRequested)
{
waitable.WaitOne();
if(devices.Count > 0)
{
yield return devices[devices.Count - 1];
}
}
yield break;
}
I think the code "handle.WaitOne();" should not be used. It will block the current thread and prevent the subsequent While loop from being executed. what you think?
Is this still an issue?
Fixed in 4.0.36