Bluetooth ScreenLock
 | Bluetooth ScreenLock is a sample application built on top of the Bluetooth managed wrappers that are included in the Coding4Fun Developer Toolkit. |
| Jerry Brunning Difficulty: Easy Time Required: 1-3 hours Cost: Free Hardware: Bluetooth-enabled laptop and phone. |
The Coding4Fun Developer Kit that was released to CodePlex last month contains a bunch of neat libraries and components for jumpstarting development against some of the new features of Vista. Included in the kit is a managed wrapper around Bluetooth communication that is designed to run in non-mobile environments – something that has not previously been widely available. With most newer laptops shipping with Bluetooth radios, and the proliferation of Bluetooth devices and receivers, I looked forward to trying this out. To get familiar with the managed wrappers, I built a simple screen locking application that I call Bluetooth Screenlock. The Bluetooth ScreenLock application runs on your PC, connects to your phone, and when it detects that you’ve walked out of range, locks your workstation. Using the Bluetooth wrappers included in the Coding4Fun Developer Toolkit makes this pretty simple.
Bluetooth Profiles
The managed Bluetooth wrapper classes that are part of the Coding4Fun Developer Kit (C4F Kit) contain libraries for connecting to three different Bluetooth profiles: Serial Port, File Transfer and Object Push. A profile is a standardized interface specification that devices comply to in order to communicate with each other. For the Bluetooth ScreenLock application I used the Serial Port profile to establish a connection and then send heartbeat messages across the Bluetooth channel periodically. If any heartbeat were to fail, the program will lock the user’s workstation.
Discovery and Pairing
Discovery is the process of detecting nearby Bluetooth devices and potentially asking them to enumerate their supported services. In order to discover a device and enumerate its services, one of two things must happen: The phone must be set to discovery mode, which enables any other Bluetooth device to see it, or the two devices must be paired. Note for security reasons you generally don’t want to leave your phone set up as discoverable.
Pairing is the process of establishing a trust relationship between two devices. Pairing usually involves the exchange of a key pair – a pin-like series of digits that must be entered on both devices before the trust relationship is established. In order to use the Bluetooth ScreenLock application you must pair your phone to your PC. You can start this from the PC, or from your phone. In Vista you can start the pairing process by opening the Bluetooth Devices utility and clicking the Add button on the Devices tab (see Figure 1). Note that I built and tested the application with a Motorola Q smartphone.
Figure 1 - The Bluetooth Devices utility in Vista
Once you’ve paired your phone to your PC, you can use the application. I decided to build the application as a Windows Forms application, but it just as easily could have been a Windows Service set to start automatically. The form is simple – just a combo box listing nearby devices and a button to enable the ScreenLock feature. It would be a pretty easy exercise to configure the application to automatically enable itself at Windows startup.
Figure 2 - The ScreenLock window
Connecting to a device
The code for the ScreenLock application uses just two of the functions in the C4F toolkit – DiscoverDeviceByName and DiscoverServicesByType. DiscoverDeviceByName is used to get an instance of a Device, which is a managed class exposed through the C4F.DevKit.Bluetooth.DeviceAndServiceDiscovery assembly.
C#
public bool DiscoverDevice(string deviceName)
{
bool returnValue = false;
try
{
DeviceServicesManager _manager = new DeviceServicesManager();
SelectedDevice = _manager.DiscoverDeviceByName(deviceName);
if (SelectedDevice != null)
{
returnValue = true;
}
}
catch (Exception ex)
{
throw new Exception("An unexpected error was raised during device discovery." + Environment.NewLine + ex.Message);
}
return returnValue;
}
VB.Net
Public Function DiscoverDevice(ByVal deviceName As String) As Boolean
Dim returnValue As Boolean = False
Try
Dim _manager As DeviceServicesManager = New DeviceServicesManager()
SelectedDevice = _manager.DiscoverDeviceByName(deviceName)
If Not SelectedDevice Is Nothing Then
returnValue = True
End If
Catch ex As Exception
Throw New Exception("An unexpected error was raised during device discovery." & Environment.NewLine & ex.Message)
End Try
Return returnValue
End Function
Once you have an instance of a Device, you can get a handle to the serial port service by calling DiscoverServicesByType. After that you could connect directly to the service on the device:
C#
public bool Connect()
{
bool returnValue = false;
List<RemoteService> serviceList = _manager.DiscoverServicesByType(SelectedDevice, ServiceType.SerialPortProfile);
RemoteService remoteService = null;
try
{
remoteService = serviceList[0];
_stream = remoteService.Connect();
_connectedService = remoteService;
returnValue = true;
}
catch (ServiceConnectionException servEx)
{
throw new Exception("An error occurred while trying to connect to " + remoteService.Name + Environment.NewLine + "Error Details: " + servEx.Message);
}
catch
{
throw;
}
return returnValue;
}VB.Net
Public Function Connect() As Boolean
Dim returnValue As Boolean = False
Dim serviceList As List(Of RemoteService) = _manager.DiscoverServicesByType(SelectedDevice, ServiceType.SerialPortProfile)
Dim remoteService As RemoteService = Nothing
Try
remoteService = serviceList(0)
_stream = remoteService.Connect()
_connectedService = remoteService
returnValue = True
Catch servEx As ServiceConnectionException
Throw New Exception("An error occurred while trying to connect to " & remoteService.Name & Environment.NewLine & "Error Details: " & servEx.Message)
Catch
Throw
End Try
Return returnValue
End Function
Bluetooth devices are recognized by their 48-bit address, but most devices use a friendly name to identify themselves. The friendly name can usually be changed by the owner of the device. The ScreenLock application allows the user to specify the friendly name to use to connect, or to search for paired devices (in the case where they don’t know the device name). To search for nearby devices the app uses the DiscoverAllDevices function with returns a list of Device objects. Since we only need the device names to populate our combo box, we use a simple LINQ query to extract the names and project them into a List of type string:
C#
public List<string> DiscoverDevices()
{
var q =
from device in _manager.DiscoverAllDevices()
select device.Name;
return q.ToList<string>();
}
VB.Net
Public Function DiscoverDevices() as List(Of String)
Dim result As List(Of String) = New List(Of String)
For Each d As Device in _manager.DiscoverAllDevices()
result.Add(d.Name)
Next
Return result
End Function
Once a device is connected to the serial port profile, the application simply uses a timer to periodically write a byte of text to the port. If the transmission fails for any reason, the application will lock the workstation by calling the LockWorkstation API call from user32.dll.
C#
public bool Ping()
{
bool returnValue = true;
if (!object.Equals(_stream,null)) {
try
{
_stream.WriteByte(1);
}
catch (Exception ex)
{
returnValue = false;
}
}
return returnValue;
}
VB.Net
Public Function Ping() As Boolean
Dim returnValue As Boolean = True
If (Not Object.Equals(_stream,Nothing)) Then
Try
_stream.WriteByte(1)
Catch ex As Exception
returnValue = False
End Try
End If
Return returnValue
End Function
The excellent Coding4Fun Developer Toolkit hides all of the complexity of setting up socket connections using the Bluetooth protocol and exposes a few simple but useful functions for interacting with Bluetooth devices from managed code. If you’re interested in writing Bluetooth apps in managed code, I suggest you take a look at it – it includes several detailed samples. In addition to the Bluetooth wrapper, there several other cool samples, such as those showing you how to write your own Preview Handlers and interact with Windows Vista Contacts.