Search code examples
c#uwpbluetoothrfcomm32feet

Unable to set SDP Record for Rfcomm Service Provider (InTheHand, uwp)


I want to create a two-way Bluetooth Rfcomm connection. The server side is implemented in UWP. Using InTheHand.Devices.Bluetooth (NuGet v4.0.1803.22-preview) I find no way to attach an SDP record to the service provider. This results in an error when trying to advertise the service.

I suppose one could cast the 'InTheHand' service provider to the Windows.Devices.Bluetooth.Rfcomm variety, but I'd prefer a solution within the InTheHand library if possible. Am I missing something?

private async void InitializeService(){
    var localRfcommServiceID = RfcommServiceId.FromUuid(uuid);
    var localRfcommService = await RfcommServiceProvider.CreateAsync(localRfcommServiceID);

//This is where I would expect to add SDP records to the service provider

    localRfcommService.StartAdvertising();
    localRfcommService.ConnectionReceived += LocalRfcommService_ConnectionReceived;
}

I get an exception when I try to start advertising. (Sorry for German error messages)

Exception thrown: 'System.IO.FileNotFoundException' in InTheHand.Devices.Bluetooth.dll
WinRT information: Der StreamSocketListener muss gebunden werden, bevor Sie mit der Ankündigung beginnen können.
Exception thrown: 'System.IO.FileNotFoundException' in System.Private.CoreLib.ni.dll
WinRT information: Der StreamSocketListener muss gebunden werden, bevor Sie mit der Ankündigung beginnen können.

Translated: The StreamSocketListener needs to be bound before advertising can begin.


Solution

  • I ended up casting the 'InTheHand' RfcommServiceProvider to a 'Windows.Devices.Bluetooth.Rfcomm.RfcommServiceProvider', then binding the service name to it and initializing the SDP attributes.

    async void InitializeService()
    {
        var localRfcommProvider = await RfcommServiceProvider.CreateAsync(Constants.RfcommServiceUuid);
        var rfcommServiceID = RfcommServiceId.FromUuid(Constants.RfcommServiceUuid);
        socketListener = new StreamSocketListener();
        socketListener.ConnectionReceived += SocketListener_ConnectionReceived;      
        await socketListener.BindServiceNameAsync(rfcommServiceID.AsString(),SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication);
        InitializeServiceSdpAttributes(localRfcommProvider);
    
        try
        {
            ((Windows.Devices.Bluetooth.Rfcomm.RfcommServiceProvider)localRfcommProvider).StartAdvertising(socketListener);  
        }
        catch (Exception e)
        {
                Debug.WriteLine(e.Message);
        }
    }
    
    
    void InitializeServiceSdpAttributes(Windows.Devices.Bluetooth.Rfcomm.RfcommServiceProvider provider)
        {
            var sdpWriter = new DataWriter();
    
            //Write the service name attribute
            sdpWriter.WriteByte(Constants.SdpServiceNameAttributeType);
    
            // The length of the UTF-8 encoded Service Name SDP Attribute.
            sdpWriter.WriteByte((byte)Constants.SdpServiceName.Length);
    
            // The UTF-8 encoded Service Name value.
            sdpWriter.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
            sdpWriter.WriteString(Constants.SdpServiceName);
    
            // Set the SDP Attribute on the RFCOMM Service Provider.
            provider.SdpRawAttributes.Add(Constants.SdpServiceNameAttributeId, sdpWriter.DetachBuffer());
        }
    

    An example of Initializing the SDP attributes was found in Microsoft's UWP samples.