Windows Store and Windows Phone App-to-App communication over Bluetooth

Introduction

This article describes how to create Windows 8.1 and Windows Phone 8 applications supporting App-to-App communication over Bluetooth. With these applications, the user can:
- send and receive text messages
- send pictures (Windows Phone 8 Application)
- receive and save pictures (Windows 8.1 Application)
The Windows Store application is running as a Bluetooth server and the Windows Phone application is running as a Bluetooth client.

In order to successfully support App-to-App communication over Bluetooth, you don’t need any specific peripherals like Wi-Fi router, USB cable. The Windows Phone and the computer or tablet running Windows 8.1 are self-sufficient regarding the Bluetooth communication.

Initially, when I started to write these samples, I wanted to use the PeerFinder API which is available on both platforms, unfortunately I didn't find any way to use this API to allow a communication between a computer running Windows 8.1 and a Windows Phone 8. Finally I decided to use Bluetooth Rfcomm for the communication between both platforms. This approach requires to pair both devices at least one time before launching the applications.

Once you are able to create a Windows Store application and a Windows Phone application talking to each other over Bluetooth, you can bundle a Windows Store application with a Windows Phone application which could be a companion application of the Windows Store application.

To build the sample the Visual Studio 2013, the Windows Phone 8 SDK are required.

Pairing devices

Before launching the applications you need to pair over Bluetooth the Windows Phone and the computer running Windows 8.1.

1. On the computer running Windows 8.1, select ”PC and Devices” settings page. Select “Bluetooth” settings page.
           clip_image002

2. On the Windows Phone, ensure Bluetooth is ON. Select “Bluetooth” settings page and turn on Bluetooth.
                   clip_image004                clip_image006

3. On the computer, select the Windows Phone in the list of the Bluetooth device, and tap on the “Pair” button.
                          clip_image008

4. On the Windows Phone, accept the pair request.
                                               clip_image010

5. On the computer, confirm the pairing.
                              clip_image012

6. On both devices, the peer devices should be displayed as connected.
                               clip_image014
                                                clip_image016

7. The devices are now paired, you can launch the applications on both platforms.

Connecting the applications

1. On the computer running Windows 8.1, launch the Bluetooth Server application.
                                               clip_image018
clip_image020

2. On the Windows Phone, launch the Bluetooth client application.
                                         clip_image022

3. Check in the Settings section that the “Service Name” are the same, it’s mandatory to successfully connect the client application with the server application. The GUID is defined in the application source code and in the Windows 8 application manifest.
        clip_image024              clip_image026

4. On the Windows Phone application navigate to “Connection” pivot. Select the computer name in the list of paired devices and tap on the “Connect” button.
                                                   clip_image028

5. As it’s the first application connection a dialog box appears on the computer running the server application. Allow the Windows application to use your Windows Phone
                       clip_image030

6. Once the connection is accepted on the server side, the client application state is displayed as “Connected”
                                                    clip_image032

7. The server application state is also displayed as “Connected”
                                     clip_image034

8. The applications are now connected, you can exchange text messages and pictures between both applications.

Sending and receiving text messages

1. On the Windows Phone, navigate to the Messages pivot, enter a text and tap on “Send” button.
                       clip_image036              clip_image038

2. You should receive the same message on your application running on Windows 8.1.
                           clip_image040

3. You can also send a message from the Windows application towards the Windows Phone application.
                          clip_image042

4. And receive the message on the Windows Phone.
                                              clip_image044

Sending and receiving pictures

1. On the Windows Phone, navigate to the “Files” pivot, and tap on “Select Picture” button.
                                               clip_image046

2. Navigate among the albums and select the picture you want to send to the Windows Application.
                              clip_image048             clip_image050

3. Once the picture is selected, the path and the size of the picture are displayed on the screen.
                                                               clip_image052

4. Tap on the “Send Picture” button to send the picture.
                                                             clip_image054

5. On the computer screen the picture is displayed in the Files section
                                    clip_image056

6. If you double-tap on the picture, the picture is displayed in full screen. At least you can save the picture on your hard drive if you tap on the “Save Image” button.

                clip_image058        clip_image060

Using Bluetooth Rfcomm for the communication between Windows and Windows Phone applications

Once the connection is established between the Windows Phone application and the Windows application using Windows.Networking.Sockets.StreamSocket, both applications can exchange commands over Bluetooth Rfcomm.
With the current applications, a command can be a text message, a picture.
The syntax associated with a command is the following:

command=<BluetoothCommand>|[[<Attribute0Key>=<Attribute0>]|[<Attribute1Key>=<Attribute1>] ... |[<AttributeNKey>=<AttributeN>]...]]

For instance:
Message Command:
command=message|content=<Message Content>
Picture File Command:
command=picture|path=<Picture Path>|size=<Picture Size>|content=<Picture Content>

This model can be extended to support new companion scenarios, a command could transport Audio files, Video files, keyboard events, …
clip_image062

Building the sample applications

In order to build the Bluetooth server sample application for Windows Store and the Bluetooth client sample application for Windows Phone, make sure you have the basics installed:
1. a computer running Windows 8.1
2. a Windows Phone running Windows Phone 8 
3. Visual Studio 2013,
4. Windows Phone 8 SDK.

Exploring the Windows Store Application project

The Windows Store Application project is a XAML based project. 
                                 clip_image064

  • MainPage.xaml.cs contains the main page source code.
  • App.xaml.cs contains the implementation of the App class.
  • WindowsBluetoothRfcommServer.cs contains the implementation of the WindowsBluetoothRfcommServer class.
  • ApplicationConfiguration.cs contains the source code used to store and retrieve the application settings in the local app store.

         Shared source code between Windows and Windows Phone

  • BluetoothService.cs contains the Service ID used for the Bluetooth Communication.

  • BluetoothServer.cs contains the definition of the Bluetooth Server Interface.

  • BluetoothDevice.cs contains the definition of the BluetoothDevice class.

  • BluetoothCommand.cs contains the definition of the BluetoothCommand, BluetoothCommandMessage, BluetoothCommandPicture classes.

    WindowsBluetoothRfcommServer states:  
     
                                              image

WindowsBluetoothRfcommServer Initialization method:
This method creates the RfcommServiceProvider and check if Bluetooth is not off on the computer

 public async Task<BluetoothServerReturnCode> Initialization()
{
    try
    {
        rfcommProvider = await RfcommServiceProvider.CreateAsync(
            RfcommServiceId.FromUuid(_BluetoothServiceUuid));
        if (rfcommProvider != null)
        {
            SetState(BluetoothServerState.Stopped);
            return BluetoothServerReturnCode.Success;
        }
        else
            return BluetoothServerReturnCode.InitError;

    }
    catch (Exception e)
    {
        if ((uint)e.HResult == ERR_BLUETOOTH_OFF)
            return BluetoothServerReturnCode.InitBluetoothOff;
        else if ((uint)e.HResult == ERR_MISSING_CAPS)
            return BluetoothServerReturnCode.InitMissingCaps;
        else if ((uint)e.HResult == ERR_NOT_ADVERTISING)
            return BluetoothServerReturnCode.InitNotAdvertising;

        NotifyLog("Error", "Exception in Initialization - " + e.Message);
        return BluetoothServerReturnCode.InitException;
    }
}

WindowsBluetoothRfcommServer Start method:
This method creates a listener and start listening. It also starts advertising for the Rfcomm Service.

 public async Task<BluetoothServerReturnCode> Start()
{
    try
    {
        NotifyLog("Information", "Starting the server...");
        if (rfcommProvider == null)
            rfcommProvider = await RfcommServiceProvider.CreateAsync(
                RfcommServiceId.FromUuid(_BluetoothServiceUuid));

        if (rfcommProvider != null)
        {
            if (socketListener != null)
            {
                socketListener.Dispose();
                socketListener = null;
            }


            // Create a listener for this service and start listening
            socketListener = new StreamSocketListener();
            socketListener.ConnectionReceived += OnConnectionReceived;

            await socketListener.BindServiceNameAsync(rfcommProvider.ServiceId.AsString(),
                SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication);

            // Set the SDP attributes and start Bluetooth advertising
            DataWriter sdpWriter = new DataWriter();

            // Write the Service Name Attribute.
            sdpWriter.WriteByte(SdpServiceNameAttributeType);

            // The length of the UTF-8 encoded Service Name SDP Attribute.
            sdpWriter.WriteByte((byte)BluetoothServiceDisplayName.Length);

            // The UTF-8 encoded Service Name value.
            sdpWriter.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
            sdpWriter.WriteString(BluetoothServiceDisplayName);

            // Set the SDP Attribute on the RFCOMM Service Provider.
            if(rfcommProvider.SdpRawAttributes.ContainsKey(SdpServiceNameAttributeId))
                rfcommProvider.SdpRawAttributes.Remove(SdpServiceNameAttributeId);
            rfcommProvider.SdpRawAttributes.Add(SdpServiceNameAttributeId, sdpWriter.DetachBuffer());
            // Start Bluetooth advertising
            SetState(BluetoothServerState.Started); 
            rfcommProvider.StartAdvertising(socketListener);
            NotifyLog("Information", "Server Started");
            return BluetoothServerReturnCode.Success;
        }
    }
    catch(Exception e)
    {
        if ((uint)e.HResult == ERR_BLUETOOTH_OFF)
            return BluetoothServerReturnCode.StartBluetoothOff;
        else if ((uint)e.HResult == ERR_MISSING_CAPS)
            return BluetoothServerReturnCode.StartMissingCaps;
        else if ((uint)e.HResult == ERR_NOT_ADVERTISING)
            return BluetoothServerReturnCode.StartNotAdvertising;
        NotifyLog("Error", "Exception in Start - " + e.Message);
        return BluetoothServerReturnCode.StartException;
    }
    return BluetoothServerReturnCode.StartError;
}

WindowsBluetoothRfcommServer OnConnectionReceived method:
This method is called when the server receives a connection request. It saves the information of the Bluetooth Client device. At least, it calls the method ReceiveIncommingCommands to receive commands.

 private void OnConnectionReceived(StreamSocketListener sender, 
    StreamSocketListenerConnectionReceivedEventArgs args)
{
    try
    {
        // Don't need the listener anymore
        socketListener.Dispose();
        socketListener = null;

        socket = args.Socket;
        if((socket!=null) && (socket.Information!=null))
        {
            _connectedDeviceDisplayName = "Remote Address: " + socket.Information.RemoteAddress.DisplayName + " Remote Port: " + socket.Information.RemotePort + " Remote Service: " + socket.Information.RemoteServiceName;
            _connectedDeviceHostName = socket.Information.RemoteHostName.DisplayName;
            _connectedDeviceServiceName = socket.Information.RemoteServiceName;
        }

        SetState(BluetoothServerState.Connected);
        NotifyLog("Information", "Client connected" );

        if (ConnectionReceived != null)
        {
            BluetoothDevice device = new BluetoothDevice(_connectedDeviceHostName,_connectedDeviceServiceName,_connectedDeviceDisplayName);
            ConnectionReceived(this, device);
        }
    }
    catch (Exception e)
    {
        NotifyLog("Error", "Exception in OnConnectionReceived - " + e.Message);
        return;
    }
    ReceiveIncomingCommands();
}

WindowsBluetoothRfcommServer Disconnect method:
This method calls ForceDisconnect to disconnect the current connection, it creates a new listener and start listening for the next connection.

 public async Task<BluetoothServerReturnCode> Disconnect()
{
    try
    {
        ForceDisconnect();
        // Create a listener for this service and start listening
        if(socketListener==null)
        {
            socketListener = new StreamSocketListener();
            socketListener.ConnectionReceived += OnConnectionReceived;

            await socketListener.BindServiceNameAsync(rfcommProvider.ServiceId.AsString(),
                SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication);
        }
        NotifyLog("Information", "Client Disconnected");
      
    }
    catch (Exception e)
    {
        NotifyLog("Error", "Exception in Disconnect - " + e.Message);
        return BluetoothServerReturnCode.DisconnectException;
    }
    finally
    {
        reader = null;
        writer = null;
        socket = null;
    }
    return BluetoothServerReturnCode.Success;
}

WindowsBluetoothRfcommServer Stop method:
IF the server was connected this method call ForceDisconnect to disconnect the current connection, it stops Bluetooth advertising and clears all the sockets.

 public  BluetoothServerReturnCode Stop()
{
    try
    {
        NotifyLog("Information", "Stopping the server..." );
        if (GetState() == BluetoothServerState.Connected)
        {
            ForceDisconnect();
        }
        SetState(BluetoothServerState.Stopped);
        if (rfcommProvider != null)
        {
            rfcommProvider.StopAdvertising();
            rfcommProvider = null;
        }

        if (socketListener != null)
        {
            socketListener.Dispose();
            socketListener = null;
        }
        NotifyLog("Information", "Server stopped");
    }
    catch (Exception e)
    {
        NotifyLog("Error", "Exception in Stop - " + e.Message);
        return BluetoothServerReturnCode.StopException;
    }
    finally
    {
        rfcommProvider = null;
        socketListener = null;
        writer = null;
        socket = null;
    }
    return BluetoothServerReturnCode.Success;
}

The Windows Application and the Windows Phone Application use the same Service Uuid to enable the communication between both applications. For the Windows Store application the Service Uuid is defined in the application manifest and in the source code.
The following section is added in the Capabilities of the manifest:

 <Capabilities>
  <Capability Name="internetClient" />
  <Capability Name="picturesLibrary" />
  <m2:DeviceCapability Name="bluetooth.rfcomm">
    <m2:Device Id="any">
      <m2:Function Type="serviceId:17890000-0068-0069-1532-1992D79BE4D8" />
    </m2:Device>
  </m2:DeviceCapability>
</Capabilities>

The file BluetoothService.cs contains the declaration of the ServiceID as well:

 public class BluetoothRfcommGlobal
{
   // Service uuid: shared between the bluetooth server (Windows 8 Application) and the bluetoth client (Windows Phone Application)
   public static Guid BluetoothServiceUuid = new Guid("17890000-0068-0069-1532-1992D79BE4D8");
   // Service display name: shared between the bluetooth server (Windows 8 Application) and the bluetoth client (Windows Phone Application)
   public static string BluetoothServiceDisplayName = "My Bluetooth Rfcomm Service";
}

The WindowsBluetoothRfcommServer is instantiated in the App constructor. 

 public App()
{
    this.InitializeComponent();

    this.Suspending += OnSuspending;
    this.Resuming += OnResuming;
    BluetoothRfcommServer = new WindowsBluetoothRfcommServer(BluetoothServiceUuid, BluetoothServiceDisplayName, ApplicationConfiguration.AutoStart);
}

The WindowsBluetoothRfcommServer is Initialized and Started in the method OnNavigatedTo of MainPage class.

 // Initialize Blutooth Server to check whether the bluetooth is on
if (((App.Current as App).BluetoothRfcommServer != null) && ((App.Current as App).BluetoothRfcommServer.GetState() == BluetoothServerState.Created))
{
    BluetoothServerReturnCode r = await(App.Current as App).BluetoothRfcommServer.Initialization();
    if ((r == BluetoothServerReturnCode.Success) && ((App.Current as App).BluetoothRfcommServer.AutoStart == true))
    {
        r = await(App.Current as App).BluetoothRfcommServer.Start();
    }
    if (r != BluetoothServerReturnCode.Success)
    {
        if ((r == BluetoothServerReturnCode.InitMissingCaps) || (r == BluetoothServerReturnCode.StartMissingCaps))
        {
            Windows.UI.Popups.MessageDialog messageDialog = new Windows.UI.Popups.MessageDialog("bluetooth.rfcomm Capability missing in the application manifest", "Windows Bluetooth Server");
            await messageDialog.ShowAsync();
        }
        else if ((r == BluetoothServerReturnCode.InitBluetoothOff) || (r == BluetoothServerReturnCode.StartBluetoothOff))
        {
            Windows.UI.Popups.MessageDialog messageDialog = new Windows.UI.Popups.MessageDialog("Bluetooth is off, bluetooth is required to launch the server", "Windows Bluetooth Server");
            await messageDialog.ShowAsync();
        }
        else if (r == BluetoothServerReturnCode.StartNotAdvertising)
        {
            Windows.UI.Popups.MessageDialog messageDialog = new Windows.UI.Popups.MessageDialog("Bluetooth Advertising Error, restart the application", "Windows Bluetooth Server");
            await messageDialog.ShowAsync();
        }
        else
        {
            Windows.UI.Popups.MessageDialog messageDialog = new Windows.UI.Popups.MessageDialog("Error occurs while initializing the server", "Windows Bluetooth Server");
            await messageDialog.ShowAsync();
        }
    }
}

Once the WindowsBluetoothRfcommServer is started, it’s waiting for incoming connection requests from client devices. When the application is connected, the WindowsBluetoothRfcommServer calls the method WindowsBluetoothRfcomm_ConnectionReceived.

 void BluetoothRfcommServer_ConnectionReceived(IBluetoothServer sender, BluetoothDevice args)
{
    ClearMessage();
    AddLog("Connected with " + (App.Current as App).BluetoothRfcommServer.ConnectedDeviceDisplayName);
}

When the WindowsBluetoothRfcommServer is connected, it can receive Bluetooth commands, in that case the WindowsBluetoothRfcommServer calls the method BluetoothRfcommServer_CommandReceived.

 void BluetoothRfcommServer_CommandReceived(IBluetoothServer sender, BluetoothCommand args)
 {
     AddLog("Command received " + args.ToString());
     
     if (args.GetType() == typeof(BluetoothCommandMessage))
     {
         BluetoothCommandMessage bm = args as BluetoothCommandMessage;
         if(bm!=null)
             AddMessage("Message Received: " + bm.MessageContent);
     }
     else if (args.GetType() == typeof(BluetoothCommandPicture))
     {
         RunOnDispatcherThread(() =>
         {
             BluetoothCommandPicture bp = args as BluetoothCommandPicture;
             if (bp != null)
             {
                 DisplayImage(bp.PictureContent);
                 if (bp.PictureContent.Length > 0)
                 {
                     _ImageBuffer = new byte[bp.PictureSize];
                     if (_ImageBuffer != null)
                         Array.Copy(bp.PictureContent, _ImageBuffer, bp.PictureContent.Length);
                 }
             }
         }); 

     }
 }

Exploring the Windows Phone 8 Application project

The Windows Phone 8 Application project is a XAML based project. 
                                          clip_image066

  • MainPage.xaml.cs contains the main page source code.
  • App.xaml.cs contains the implementation of the App class.
  • WindowsBluetoothRfcommClient.cs contains the implementation of the WindowsBluetoothRfcommClient class.
  • ApplicationConfiguration.cs contains the source code used to store and retrieve the application settings in the local app store.

         Shared source code between Windows and Windows Phone

  • BluetoothService.cs contains the Service ID used for the Bluetooth Communication.
  • BluetoothClient.cs contains the definition of the Bluetooth Client Interface.
  • BluetoothDevice.cs contains the definition of the BluetoothDevice class.
  • BluetoothCommand.cs contains the definition of the BluetoothCommand, BluetoothCommandMessage, BluetoothCommandPicture classes.

BluetoothRfcommClient states:

                                              image

WindowsPhoneBluetoothRfcommClient Initialization method:
This method checks if  the application is not running in the Windows Phone Emulator, it also checks if Bluetooth is not off on the Windows Phone. 

 public async Task<BluetoothClientReturnCode> Initialization()
{
    if (Microsoft.Devices.Environment.DeviceType == Microsoft.Devices.DeviceType.Emulator)
    {
        return BluetoothClientReturnCode.InitEmulator;
    }

    try
    {
        PeerFinder.AlternateIdentities["Bluetooth:Paired"] = "";
        var Peers = await PeerFinder.FindAllPeersAsync();
    }
    catch (Exception ex)
    {
        if ((uint)ex.HResult == ERR_BLUETOOTH_OFF)
        {
            return BluetoothClientReturnCode.InitBluetoothOff;
        }
        else if ((uint)ex.HResult == ERR_MISSING_CAPS)
        {
            return BluetoothClientReturnCode.InitMissingCaps;
        }
        else if ((uint)ex.HResult == ERR_NOT_ADVERTISING)
        {
            return BluetoothClientReturnCode.InitNotAdvertising;
        }
        else
        {
            return BluetoothClientReturnCode.InitError;
        }
    }
    finally
    {
        PeerFinder.Stop();
    }
    SetState(BluetoothClientState.Initialized);
    return BluetoothClientReturnCode.Success;

}

WindowsPhoneBluetoothRfcommClient Connect method:
This method creates a StreamSocket used to create a connection with the Bluetooth Device. If the connection is sucessful, It saves the information of the Bluetooth Server device. At least it calls the method ReceiveIncommingCommands to receive commands.

 public async Task<BluetoothClientReturnCode> Connect(BluetoothDevice device)
{
    NotifyLog("Information", "Connecting Client...");
    if (socket == null)
        socket = new StreamSocket();
    try
    {
        await socket.ConnectAsync(new Windows.Networking.HostName(device.HostName), BluetoothServiceName);
    }
    catch (Exception ex)
    {
        NotifyLog("Error", "Exception in Connect - " + ex.Message);
        return BluetoothClientReturnCode.ConnectError;
    }
    SetState(BluetoothClientState.Connected);

    // Connected no need for advertising anymore
    PeerFinder.Stop();
    _connectedDeviceDisplayName = device.DisplayName;
    _connectedDeviceHostName = device.HostName;
    _connectedDeviceServiceName = BluetoothServiceName;
    NotifyLog("Information", "Client connected");

    // Reception loop
    ReceiveIncomingCommands();

    return BluetoothClientReturnCode.Success;
}

WindowsPhoneBluetoothRfcommClient Disconnect method:
This method clears the StreamSocket to disconnect the current connection.

 public BluetoothClientReturnCode Disconnect()
{
    try
    {
        NotifyLog("Information", "Disconnecting Client...");
        SetState(BluetoothClientState.Initialized);

        _connectedDeviceDisplayName = "";
        _connectedDeviceHostName = "";
        _connectedDeviceServiceName = "";

        if (socket != null)
        {
            socket.Dispose();
            socket = null;
        }

        if (writer != null)
        {
            writer.DetachStream(); 
            writer.Dispose();
            writer = null;
        }
        if (reader != null)
        {
            
            reader.Dispose();
            reader = null;
        }
        NotifyLog("Information", "Client Disconnected");

    }
    catch (Exception e)
    {
        NotifyLog("Error", "Exception in Disconnect - " + e.Message);
        return BluetoothClientReturnCode.DisconnectException;
    }
    finally
    {
        reader = null;
        writer = null;
        socket = null;
    }
    return BluetoothClientReturnCode.Success;
}

The Windows Application and the Windows Phone Application use the same Service Uuid to enable the communication between both applications. For the Windows Phone application the Service Uuid is defined in the source code in the file BluetoothService.cs which contains the declaration of the ServiceID as well:

 public class BluetoothRfcommGlobal
{
   // Service uuid: shared between the bluetooth server (Windows 8 Application) and the bluetoth client (Windows Phone Application)
   public static Guid BluetoothServiceUuid = new Guid("17890000-0068-0069-1532-1992D79BE4D8");
   // Service display name: shared between the bluetooth server (Windows 8 Application) and the bluetoth client (Windows Phone Application)
   public static string BluetoothServiceDisplayName = "My Bluetooth Rfcomm Service";
}

The WindowsBluetoothRfcommClient is instantiated in the App constructor.

 public App()
{
    // Global handler for uncaught exceptions.
    UnhandledException += Application_UnhandledException;

    // Standard XAML initialization
    InitializeComponent();

    // Phone-specific initialization
    InitializePhoneApplication();

    // Language display initialization
    InitializeLanguage();

    // Show graphics profiling information while debugging.
    if (Debugger.IsAttached)
    {
        // Display the current frame rate counters
        Application.Current.Host.Settings.EnableFrameRateCounter = true;

        // Show the areas of the app that are being redrawn in each frame.
        //Application.Current.Host.Settings.EnableRedrawRegions = true;

        // Enable non-production analysis visualization mode,
        // which shows areas of a page that are handed off to GPU with a colored overlay.
        //Application.Current.Host.Settings.EnableCacheVisualization = true;

        // Prevent the screen from turning off while under the debugger by disabling
        // the application's idle detection.
        // Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run
        // and consume battery power when the user is not using the phone.
        PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
    }
    // Call BluetoothRfcommClient constructor
    BluetoothRfcommClient = new WindowsPhoneBluetoothRfcommClient(BluetoothServiceUuid, BluetoothServiceDisplayName, ApplicationConfiguration.AutoStart);
}

  
The WindowsBluetoothRfcommClient is Initialized in the method OnNavigatedTo of MainPage class. 

 protected override async void OnNavigatedTo(NavigationEventArgs e)
{
    // Check if BluetoothRfcommClient instance
    if ((App.Current as App).BluetoothRfcommClient == null)
        return;
    // Check BluetoothRfcommClient State
    // If State == BluetoothClientState.Created, the bluetooth client didn't start
    if ((App.Current as App).BluetoothRfcommClient.GetState() == BluetoothClientState.Created)
    {
        BluetoothClientReturnCode r = await(App.Current as App).BluetoothRfcommClient.Initialization();
        if (r != BluetoothClientReturnCode.Success)
        {
            if ((r == BluetoothClientReturnCode.InitMissingCaps) || (r == BluetoothClientReturnCode.StartMissingCaps))
            {
                MessageBox.Show("bluetooth.rfcomm Capability missing in the application manifest", "Windows Phone Bluetooth Client", MessageBoxButton.OK);
            }
            else if ((r == BluetoothClientReturnCode.InitBluetoothOff) || (r == BluetoothClientReturnCode.StartBluetoothOff))
            {
                MessageBox.Show("Bluetooth is off, bluetooth is required to launch the client", "Windows Phone Bluetooth Client", MessageBoxButton.OK);
                {
                    ConnectionSettingsTask connectionSettingsTask = new ConnectionSettingsTask();
                    connectionSettingsTask.ConnectionSettingsType = ConnectionSettingsType.Bluetooth;
                    connectionSettingsTask.Show();
                }
            }
            else if (r == BluetoothClientReturnCode.StartNotAdvertising)
            {
                MessageBox.Show("Bluetooth Advertising Error, restart the application", "Windows Phone Bluetooth Client", MessageBoxButton.OK);
            }
            else
            {
                MessageBox.Show("Error occurs while initializing the client", "Windows Phone Bluetooth Client", MessageBoxButton.OK);
            }
            return;
        }
    }

    // Subscribe to CommandReceived, LogReceived and StateChanged
    (App.Current as App).BluetoothRfcommClient.LogReceived += BluetoothRfcommClient_LogReceived;
    (App.Current as App).BluetoothRfcommClient.CommandReceived += BluetoothRfcommClient_CommandReceived;
    (App.Current as App).BluetoothRfcommClient.StateChanged += BluetoothRfcommClient_StateChanged;

    // Update IsConnected state
    UpdateIsConnectedAndImageLoaded();

    // Fill the list of Paired Devices 
    FillListPairedDevices();

}

Once the WindowsBluetoothRfcommClient is initialized, the user can connect the application with the service running on a device running Windows 8.1 in that case the application calls the method ButtonConnect_Click.

 private async void ButtonConnect_Click(object sender, RoutedEventArgs e)
{
    if ((ListDevices.SelectedIndex >= 0) && (ListDevices.SelectedIndex < ListDevices.Items.Count))
    {
        BluetoothDevice d = ListDevices.Items[ListDevices.SelectedIndex] as BluetoothDevice;
        if(d!=null)
        {
            BluetoothClientReturnCode r = await (App.Current as App).BluetoothRfcommClient.Connect(d);
            if(r == BluetoothClientReturnCode.Success)
            {
                // Start Message loop
                ClearMessage();
                ClearFile();
            }
        }
    };
}

When the WindowsBluetoothRfcommClient is connected, it can receive Bluetooth commands, in that case the WindowsBluetoothRfcommClient calls the method BluetoothRfcommClient_CommandReceived.

 void BluetoothRfcommClient_CommandReceived(IBluetoothClient sender, BluetoothCommand args)
{
    AddLog("Command received " + args.ToString());
    if (args.GetType() == typeof(BluetoothCommandMessage))
    {
        BluetoothCommandMessage bm = args as BluetoothCommandMessage;
        if(bm!=null)
            AddMessage("Message Received: " + bm.MessageContent);
    }
    else if (args.GetType() == typeof(BluetoothCommandPicture))
    {
        BluetoothCommandPicture bp = args as BluetoothCommandPicture;
        if(bp!=null)
            AddFile("File Received: " + bp.PicturePath);
    }
}

When the WindowsBluetoothRfcommClient is connected, the user can send Bluetooth commands as well, in that case the application calls the method ButtonSend_Click.

 private async void ButtonSend_Click(object sender, RoutedEventArgs e)
{
    if (!string.IsNullOrEmpty(Message.Text))
    {
        BluetoothCommandMessage bm = new BluetoothCommandMessage();
        if (bm != null)
        {
            bm.CreateMessageCommand(Message.Text);
            BluetoothClientReturnCode r = await (App.Current as App).BluetoothRfcommClient.SendCommand(bm);
            if (r == BluetoothClientReturnCode.Success)
                AddMessage("Message Sent: " + Message.Text);
        }
    }
}

Downloading the projects

Download:        C# (200 KB)
Requires:           Windows 8.1, Windows Phone 8, Visual Studio 2013, Windows Phone 8 SDK
Last updated:    12/13/2013
License:              MS-LPL
Technologies:    Bluetooth, Rfcomm, StreamSocket, PeerFinder, C#, XAML
Topics:               Windows Store and Windows Phone App-to-App communication over Bluetooth