Xamarin.Forms Android project: BluetoothSocket.Connect throws Exception every time

DonR 26 Reputation points
2021-03-16T19:05:02.927+00:00
read failed, socket might closed or timeout, read ret: -1 

I've seen many versions of this question, and I've tried all the proposed answers but I, like what seems like most of the posters, have had no joy with any of them. I am getting a BluetoothDevice from a scan filtered on a known UUID with no apparent problem, but when I try to connect a socket created on that device the connection attempt times out (seemingly; it tries for about 10 seconds first) and throws a Java.IO.IOException with the message read failed, socket might closed or timeout, read ret: -1. As you can see in the code for the function where I'm trying to test making a connection, this happens with sockets from both CreateRfcommSocketToServiceRecord and createRfcommSocket. I have also tried the "Insecure" versions of both with the same results.

I've tried confirming that the device offers the expected UUID, but calling GetUuids() returns null; maybe that's a clue? FetchUuidsWithSdp() returns true, so I'm guessing the scanned device is still visible at that point. Also, both devices prompt to confirm pairing, so that supports the theory that they are communicating OK. I don't understand how I can successfully scan the device filtered on that service UUID if it doesn't actually offer it, though?

Here's the function that tries to make the connection:

public void Connect(BluetoothDevice device) 
{ 
    if (device.BondState != Bond.Bonded) 
    { 
        device.CreateBond(); 
    } 

    ParcelUuid[] uuids = null; 
    if (device.FetchUuidsWithSdp()) 
    { 
        uuids = device.GetUuids(); 
    } 
    //if (null == uuids || 0 == uuids.GetLength(0)) 
    //{ 
    //    throw new System.Exception("No service UUIDs found for peripheral device"); 
    //} 
    //UUID uuid = uuids[0].Uuid; // There should be only one service offered by one of our devices 
    BluetoothSocket socket; 
    try 
    { 
        socket = device.CreateRfcommSocketToServiceRecord(UUID.FromString(BluetoothConstants.MY_SERVICE_UUID)); 
        if (null == socket) 
        { 
            throw new Exception("Failed to create socket"); 
        } 
        socket.Connect(); 
    } 
    catch (IOException x) 
    { 
        Method method = device.Class.GetMethod("createRfcommSocket", Integer.Type); 
        socket = (BluetoothSocket)method.Invoke(device, 1); 
        if (null == socket) 
        { 
            throw new Exception("Failed to create socket"); 
        } 
        socket.Connect(); 
    } 
    if (false == socket.IsConnected) 
    { 
        throw new System.Exception(string.Format("Failed to connect to service {0}", device.Name)); 
    } 
} 

Has anyone found a reliable way to get around this? Surely we are not the first team to try using a Xamarin.Forms-based project for Bluetooth communication among mobile devices.

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,297 questions
{count} vote