(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Windows Phone 8: Bluetooth

(7 votes)
Peter Kuhn
>
Peter Kuhn
Joined Jan 05, 2011
Articles:   44
Comments:   29
More Articles
1 comments   /   posted on Feb 05, 2013
Categories:   Windows Phone
Tweet

When we talk about Bluetooth support in Windows Phone, we really have to look at two different sides of the same medal: user experience and features as well as developer opportunities. Windows Phone 7 had basic support for Bluetooth from the beginning, however more advanced options were not available to the user. For developers, the situation was even worse, as there was no public available API to support Bluetooth features in your apps at all. Both situations have changed and improved dramatically in Windows Phone 8, however, as we will see in this article, the situation is still not perfect.

What Bluetooth Is

Bluetooth is a wireless communication standard that has been around since the late nineties and evolved over the last decade into one of the most important technologies for short-distance data exchange between both fixed and mobile devices. It allows, for example, to create ad-hoc networks between devices like your phone, and gadgets. Typical use cases you may know are:

  • Use of hands-free kits to transport audio (speaker and microphone), data (e.g. caller information) as well as commands (e.g. for dialing)
  • Remote game controllers (e.g. the Wii and PS3 controllers use it) and other input devices (e.g. wireless keyboards)
  • Local communication sets (e.g. for motorcycle drivers etc.)

Apart from these there are a lot more applications, both in the industry and consumer areas, like home automation or in the medical field.

Bluetooth works with so-called profiles to add support for typical application-level features on top of the low-level technology infrastructure. For example, the possibility to exchange data does not guarantee that two devices really know how to talk to each other correctly. To solve the problem that each and every vendor potentially creates their own application-level protocols for basically identical features, profiles were created. These describe how certain functionality has to be implemented, so that e.g. devices across multiple vendors can talk to each other in a standardized way. Today, a great variety of profiles exist [1], for example for audio, image and video exchange, remote control, hands-free features, input devices and even things like printing or data synchronization. This means that "Bluetooth support" alone is not a suitable term to describe a device's capabilities. You always have to be aware of what profiles are supported to understand what actual features a device really offers.

End User Bluetooth Features in Windows Phone

The first thing we need to do hence is look at what Bluetooth profiles are actually supported from the consumer's point of view. From the very beginning, Windows Phone 7 supported typical scenarios where you wanted to hook your phone to car audio systems or headsets. However, support for other important profiles like those used for data exchange or input devices were missing. Only some of these missing features have been added to Windows Phone 8. Let's take a look at the following table to understand what Windows Phone devices actually support:

 

Windows Phone 7

Windows Phone 8

Advanced Audio Distribution Profile
(audio streaming)

Yes (1.2)

Yes (1.2)

Audio/Video Remote Control Profile
(controlling A/V equipment)

Yes (1.3)

Yes (1.4)

Hands Free Profile
(e.g. car systems for hands-free calls)

Yes (1.5)

Yes (1.5)

Headset Profile
(basic headset features)

Yes (1.1)

No*

Phone Book Access Profile
(exchange of phone book data)

Yes (1.1)

Yes (1.1)

Object Push Profile
(pushing files, images etc. to others)

No

Yes (1.1)

Human Interface Device Profile
(mice, joysticks, keyboards etc.)

No

No

*It's interesting that by the time of writing the official documentation [2] does not list the Headset Profile for Windows Phone 8 anymore (as it explicitly was in that for Windows Phone 7 [3]). Of course this does not mean that Windows Phone 8 doesn't support headsets anymore. Headsets are also part of the audio distribution profile and hands-free profile. I don't know whether the specific profile is just missing from the documentation or support for it has been explicitly dropped.

I've highlighted the changes in Windows Phone 8 as well as other interesting details. The support for a newer version of the remote control profile should add more options to situations when you control A/V equipment with the phone. A lot more important however is the newly added support for the "Object Push Profile". This is something that was requested a lot, and it finally allows you to share data like contacts, photos, music and office documents between devices. Detailed instructions for end users can be found on the Windows Phone web site [4].

Sadly, one of the most important profiles, namely the "Human Interface Device Profile", still is not supported on Windows Phone 8, just like it wasn't on version 7 of the platform. This profile is responsible for the support of external input devices, like game controllers and keyboards. It's not only relevant for end users to e.g. make gaming more enjoyable, but also a big issue for enterprise software development. For example, in one of my current projects it really would be nice for users of a enterprise software on Windows Phone 8 to be able to use an external keyboard, so input of large amounts of data when they are on the road becomes easier and more practicable. Support for this was expected by many, and consequently the corresponding User Voice feature has gained a lot of traction already [5]. If you want to see support for things like these in Windows Phone, go and vote there!

Developer Bluetooth Features in Windows Phone

The options for developers regarding Bluetooth on Windows Phone 7 were, frankly, non-existent. No public APIs existed that third-party app developers could use to add Bluetooth features to their software. In Windows Phone 8, this situation was improved a lot, and the newly available APIs now support both custom device to device communication as well as interacting with any device the phone previously has paired with. It's noteworthy though that "device to device" mainly means communication between instances of your app running on multiple devices at the same time.

The Setup

The fundamental namespace involved with the peer communication features of Windows Phone 8, not only Bluetooth but e.g. also NFC, is Windows.Network.Proximity [6] which contains types that are available similarly on Windows Phone 8 and Windows 8. The idea here is to provide both a unified API for all the flavors of short distance communication as well as to keep those APIs consistent across both operating systems by making them part of the Windows Runtime APIs. This helps you creating portable code and spares you from learning multiple APIs depending on the platform you work with. The same is true for another part of the puzzle, the namespace Windows.Networking.Sockets [7]. It provides types like the StreamSocket [8] which is the common type used for the actual communication (connect, read and write data) in both Bluetooth scenarios. By the way, direct communication between Windows 8 and Windows Phone 8 versions of your app is an explicitly mentioned scenario that is supported through details like the "alternate identities" concept. 

To make use of Bluetooth or NFC features, you need to specify the corresponding capability "ID_CAP_PROXIMITY" in your WMAppManifest.xml. For networking features, you additionally need to use the networking capability too. You can set those capabilities either through the visual editor:

… or directly in XML:

image

 

Phone to Device

You cannot establish arbitrary connections to any Bluetooth devices within reach of the current phone. Instead, the user first has to pair with such devices using the phone's Bluetooth settings first. This obviously is a security precaution. For you as a developer this means that you can only iterate the paired Bluetooth devices and then pick one that you want to connect to. To do this, you have to make use of the alternate identities feature I already mentioned briefly above to indicate that you are interested only in peers that are paired through Bluetooth. Here is a complete sample snippet:

   1: // set this to find all paired bluetooth devices
   2: PeerFinder.AlternateIdentities["Bluetooth:Paired"] = "";
   3:  
   4: // do the actual discovery
   5: var peers = await PeerFinder.FindAllPeersAsync();
   6:  
   7: // select one of the paired devices based on the
   8: // data provided by the returned peers
   9: var peer = SelectPeer(peers);
  10: if (peer != null)
  11: {
  12:     // create and connect a socket
  13:     using (var socket = new StreamSocket())
  14:     {
  15:         await socket.ConnectAsync(peer.HostName, "[desired service]");
  16:  
  17:         // write some data to the socket
  18:         var buffer = GenerateData();
  19:         await socket.OutputStream.WriteAsync(buffer);
  20:     }
  21: }

Once you have obtained the list of available peers, you typically select the one you want based on the information returned, for example the display or host names. Of course you can also give the user the opportunity to select the peer they want. The next step then is to create a socket that connects to the peer. For paired Bluetooth devices, the "ServiceName" property of the peer data is empty, so you need to know up-front what value to pass in to the "ConnectAsync" method of the socket. This shouldn't be a problem though, as this service name does not change and can safely be hard-coded for the devices you support.

Once you are connected, you can use the "OutputStream" property of the socket to write data to the device, and of course the corresponding "InputStream" to read, if applicable. These streams work with "IBuffer" instances, something that you may not be familiar with if you haven't worked with Windows 8 and/or the Windows Runtime before. The following snippet gives you an idea how you can use the "DataWriter" helper class [9] to easily obtain an "IBuffer" suitable to use with these APIs.

   1: private IBuffer GenerateData()
   2: {
   3:     // generate some sample data from the string "Hallo World!"
   4:     using (var dataWriter = new DataWriter())
   5:     {
   6:         dataWriter.UnicodeEncoding = UnicodeEncoding.Utf8;
   7:         dataWriter.WriteString("Hallo World!");
   8:         return dataWriter.DetachBuffer();
   9:     }
  10: }

Of course, the details about what data to send to the paired device depends on the situation and it's up to you to implement this correctly based on its specification.

Phone to Phone

For Bluetooth communication between phones, you can send data back and forth between instances of your app running on multiple devices. Even though these instances may look as equal partners in the communication, technically still the usual same client/server concept is used to bring them together. You as app developer hence are responsible for implementing both the server and client side in your app.

The client side is almost identical to what we have seen above in the phone to device communication scenarios. The difference is that you are not enumerating the paired devices, but instead you will try to find a corresponding instance of your app running on another device directly. As mentioned above, by using the "alternate identities" approach you could also establish connections between apps that do not have the same identity, which typically will be the case if you're trying to e.g. connect to a Windows 8 version of your app from Windows Phone. More on this can be found in the above linked MSDN documentation.

   1: // simply start the peer finder
   2: PeerFinder.Start();
   3:  
   4: // do the actual discovery of our app running on another device
   5: var peers = await PeerFinder.FindAllPeersAsync();
   6:  
   7: // select one of the available peers
   8: var peer = SelectPeer(peers);
   9: if (peer != null)
  10: {
  11:     // create and connect a socket
  12:     using (var socket = new StreamSocket())
  13:     {
  14:         await socket.ConnectAsync(peer.HostName, "[desired service]");
  15:  
  16:         // write some data to the socket
  17:         var buffer = GenerateData();
  18:         await socket.OutputStream.WriteAsync(buffer);
  19:     }
  20: }

The server side is a bit more complex. You need to listen for incoming connections and then connect a corresponding socket that you can use to read whatever data the client has to send. If you are familiar with networking, this won't be new to you except for the involved types.

   1: private void StartBluetoothServer()
   2: {
   3:     // start and listen for connection requests
   4:     PeerFinder.Start();
   5:     PeerFinder.ConnectionRequested += PeerFinder_ConnectionRequested;
   6: }
   7:  
   8: private async void PeerFinder_ConnectionRequested(object sender, ConnectionRequestedEventArgs args)
   9: {
  10:     // retrieve the peer information
  11:     var peer = args.PeerInformation;
  12:  
  13:     // ... and connect
  14:     using (var socket = await PeerFinder.ConnectAsync(peer))
  15:     {
  16:         // required buffer
  17:         var buffer = new Windows.Storage.Streams.Buffer(1024);
  18:                 
  19:         // read back the data
  20:         var readBytes = socket.InputStream.ReadAsync(buffer, 
  21:             buffer.Capacity, 
  22:             InputStreamOptions.Partial);
  23:  
  24:         // process the data contained in "buffer"
  25:     }
  26: }

Once again the details about what kind of data is transferred between both peers is up to you to define. Thinking about and specifying the involved structures is the challenging part when you build that kind of applications. You need to create a protocol for your app that is capable of transferring all the information you need but at the same time does not waste bandwidth and is robust enough to handle typical networking problems. Typically you would e.g. prefix the data that is sent with the amount that is to follow so the receiving side knows how many bytes to read from the stream. This however is a whole other topic and way beyond the scope of this article.

Testing Bluetooth

Bluetooth features in your app require lots of manual testing. The emulators that ship with the phone SDK do not have built-in support for Bluetooth, which means that using any APIs like the PeerFinder will immediately result in exceptions.

Unlike with NFC, where people already came up with solutions for this problem (more on this in the next part of this series), there's no way around this limitation for Bluetooth at the moment. So make sure that your Bluetooth features are encapsulated properly if you want to ensure aspects like good testability of your app. Also, plan ahead for the manual testing efforts.

Conclusion

From a consumer's point of view, Bluetooth improvements in Windows Phone 8 are a bit disappointing at first glance, in particular because of the still missing HID profile support. However, on the other hand third-party developers now have access to the involved APIs and can achieve things that simply weren't possible before. All in all, this will likely result in a greater variety of features and richer apps. And I'm sure that future versions of the platform also will bridge the remaining gaps in Bluetooth profile support.


Subscribe

Comments

  • MikeGH

    Re: Windows Phone 8: Bluetooth


    posted by MikeGH on Feb 06, 2013 16:12
    It's a shame they don't also have SPP support, for a really simple protocol for external devices to work with it is hard to beat.

Add Comment

Login to comment:
  *      *       

From this series