Problem: On Android when pairing with Bluetooth device is in progress this popup is shown to enter pin code:
This is fine, except there is an awkward message “Usually 000 or 1234“. Some end users just type 0000 or 1234 as suggested on the pairing form. Of course, pairing failed due to wrong pin entered.
Solution: I wanted to create custom entry form to collect pin and do automatic pairing, if possible. After a quick research I found some useful resources here.
First, I declared simple method TryAutomaticPairing(string pin)
inside Xamarin Forms Android project. Crucial code excerpt from my BluetoothConnectionManager
class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public void TryAutomaticPairing(string pin) { try { var bluetoothDeviceReceiver = new BluetoothDiscoveryReceiver(pin); var intentFilter = new Android.Content.IntentFilter(Android.Bluetooth.BluetoothDevice.ActionPairingRequest); intentFilter.Priority = (int)Android.Content.IntentFilterPriority.HighPriority; var intent = MainActivity.Instance.RegisterReceiver(bluetoothDeviceReceiver, intentFilter); } catch { // log error } } |
where BluetoothDiscoveryReceiver
class inherits from BroadcastReceiver
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
using Android.App; using Android.Content; namespace Jenx.AutomaticBluetoothPairDemo.Droid.Services { [BroadcastReceiver] [IntentFilter(new[ ] { Android.Bluetooth.BluetoothDevice.ActionPairingRequest }, Priority = (int)IntentFilterPriority.HighPriority)] public class BluetoothDiscoveryReceiver : BroadcastReceiver { private readonly string _pin; public BluetoothDiscoveryReceiver() { } public BluetoothDiscoveryReceiver(string pin) { _pin = pin; } public override void OnReceive(Context context, Intent intent) { string action = intent.Action; if (action == Android.Bluetooth.BluetoothDevice.ActionPairingRequest) { var device = (Android.Bluetooth.BluetoothDevice)intent.GetParcelableExtra(Android.Bluetooth.BluetoothDevice.ExtraDevice); var extraPairingVariant = intent.GetIntExtra(Android.Bluetooth.BluetoothDevice.ExtraPairingVariant, 0); switch (extraPairingVariant) { case Android.Bluetooth.BluetoothDevice.PairingVariantPin: if (TrySetPin(device, _pin)) InvokeAbortBroadcast(); break; case Android.Bluetooth.BluetoothDevice.PairingVariantPasskeyConfirmation: break; } } } private static bool TrySetPin(Android.Bluetooth.BluetoothDevice device, string pin) { try { return device.SetPin(PinToByteArray(pin)); } catch { return false; } } private static byte[] PinToByteArray(string pin) { return System.Text.Encoding.UTF8.GetBytes(pin); } } } |
Voila!
After scanning neighborhood for BLE devices, selecting one of them, request pin from user, application automatically pairs with my BLE device.
On some Android devices SetPin()
fails i.e. false if returned. In that case, normal pair popup is displayed because I did not stop pairing process by executing InvokeAbortBroadcast()
.
If you have similar problems/solutions give me a ping and share your ideas.
Happy coding!
7 thoughts on “Xamarin Forms: Automatic pairing with Bluetooth device on Android”
Why did you must pairing with Bluetooth device on Android?
Thank you.
@Joze Thanks Joze it’s very helpful for me.
same implementation needed for iOS or UWP platforms or it’s handled by the Plugin.BLE itself?
This example here is only for Android. On iOS there is no such solution (at least I dont know of). On iOS, in general, when you app needs BLE device with pair functionality, iOS will automatically popup pairing window so you can enter pin and pair with device…
@Joze we are developing BLE communication app in Xamarin Forms.
We are facing the following problem while pairing the device.
1. We are calling ConnectedToDeviceAsync from PCL. on that time its invoking Pairing key pop, but its not Stable since some times its asking for Passkey or some times its showing message Allow Device to Access for Android .Here is my code in BroadCast Receiver.
2. PairingVariantPin somtimes its called but sometimes its not getting called. Eventhough im calling ConnectToDeviceAsync from PCl
if (action == BluetoothDevice.ActionPairingRequest)
{
BluetoothDevice device = (BluetoothDevice)intent.GetParcelableExtra(BluetoothDevice.ExtraDevice);
var extraPairingVariant = intent.GetIntExtra(Android.Bluetooth.BluetoothDevice.ExtraPairingVariant, 0);
switch (extraPairingVariant)
{
case Android.Bluetooth.BluetoothDevice.PairingVariantPin:
if (TrySetPin(device, pin))
InvokeAbortBroadcast();
break;
case Android.Bluetooth.BluetoothDevice.PairingVariantPasskeyConfirmation:
break;
}
Hi @Kingsley
For 100% correct answer I would need to double check, but:
1) Pairing/BroadCastReceiver “OnReceive” event is invoked when you first access restricted characteristics on GATT, and not when you connect to device (as said, I am not 100% sure, but you can check this)
2) If you want automatic Pin-Bound device and not showing pass-key popup in adroid, play around and try this code:
public class PairingReceiver : BroadcastReceiver
{
...
public override void OnReceive(Context context, Intent intent)
{
var bluetoothDevice = (BluetoothDevice)intent.GetParcelableExtra(BluetoothDevice.ExtraDevice);
// check for nulls....
bluetoothDevice.SetPin(Encoding.ASCII.GetBytes("pin-pass-key"));
bluetoothDevice.CreateBond();
InvokeAbortBroadcast();
}
....
}
Yes it’s works fine ..Thank you@ joze..
@ joze and @Kingsley
yeah, it’s working, but not for Samsung m20, android 10.
don’t know what happen but sometimes paired sometimes not.
any suggestions @joze