Essentially what the subject says. I have a bluetooth device which displays a PIN on its screen every time I try to pair with it using my windows 10 machine. I need to display some sort of popup dialog in my .Net8 MAUI app for the user to type said PIN so as to submit it to the BLE stack of windows. My current code looks like this:
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.Enumeration;
public static class BluetoothPairing
{
public async Task<bool> PairAsync(BluetoothLEDevice bluetoothLeDevice, DevicePairingProtectionLevel devicePairingProtectionLevel = DevicePairingProtectionLevel.Default)
{
if (bluetoothLeDevice.DeviceInformation.Pairing.IsPaired) //order
return true;
var canPair = bluetoothLeDevice.DeviceInformation.Pairing.CanPair; //order
if (!canPair)
return false;
try
{
bluetoothLeDevice.DeviceInformation.Pairing.Custom.PairingRequested += PairingRequestedHandler_;
const DevicePairingKinds allowedDevicePairingKinds = DevicePairingKinds.ConfirmOnly
| DevicePairingKinds.DisplayPin
| DevicePairingKinds.ProvidePin
| DevicePairingKinds.ConfirmPinMatch
| DevicePairingKinds.ProvidePasswordCredential; //supported only by Windows10.0.18362.0 and later
var pairingStatus = DevicePairingResultStatus.Failed;
var pairingResult = await bluetoothLeDevice.DeviceInformation.Pairing.Custom.PairAsync(
pairingKindsSupported: allowedDevicePairingKinds,
minProtectionLevel: devicePairingProtectionLevel
);
pairingStatus = pairingResult?.Status ?? DevicePairingResultStatus.Failed;
return pairingStatus is DevicePairingResultStatus.Paired or DevicePairingResultStatus.AlreadyPaired;
}
finally
{
bluetoothLeDevice.DeviceInformation.Pairing.Custom.PairingRequested -= PairingRequestedHandler_;
}
}
}
My main issue is that I can’t find a proper way to display a MAUI input-dialog inside PairingRequestedHandler_() because no matter what I do the UI hangs – which is expected because I try to block-and-wait in the event-handler as shown below. However I can’t find a way around this seemingly trivial problem and I’m at the end of my witts:
static async void PairingRequestedHandler_(DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs ea)
{
//var deferral = ea.GetDeferral();
// var tcs = new TaskCompletionSource();
var appCurrent = Application.Current;
if (appCurrent == null)
return;
var mainPage = Application.Current?.MainPage;
if (mainPage == null)
return;
await appCurrent.Dispatcher.DispatchAsync(async () =>
{
//var deferral = ea.GetDeferral();
try
{
var typedPin = await mainPage.DisplayPromptAsync(
title: "Enter Pairing PIN",
message: $"Type the PIN (ea.Pin='{ea.Pin}') displayed on the device to proceed:",
accept: "OK",
cancel: "Cancel"
);
if (string.IsNullOrEmpty(typedPin))
return;
ea.Accept(typedPin);
}
catch (Exception ex) //if a dialog is already open we will definitely get an exception
{
//tcs.TrySetException(ex);
}
finally
{
//deferral.Complete();
// if (!tcs.Task.IsFaulted)
// {
// tcs.TrySetCompleted(); // deferral.Complete();
// }
}
});
// tcs.Task.GetAwaiter().GetResult(); //couldnt find a different way to wait for the async code to finish inside the handler
// await tcs.Task;
}