You are on page 1of 20

1 | a g e

Project Report
Bluetooth interIace in C#

Supervised By: Submitted By:
Mr. Raheel Quraishi Ammara Javeed
AM(Tech) Nousheen Hashmi

Fatima Jinnah Women University



1uly 2011
Directorate of Human Resource Development
National Development Complex, Islamabad


2 | a g e

%ables of Contents
Abstract..................................3
Objective...................................4
Acknowledgment...............................5
2.1 Introduction.................................6
2.2 Requirements (Hardware and Software)...................6
2.3 How the Application works.......................6-18
2.3.1Connecting..........................6-8
2.3.2 Exploring the Device....................8-18
2.3.2.1 Displaying Folder Content...............8-9
2.3.2.2 Extracting Icon by Extension............9-10
2.3.2.3 Navigating through Folders...............................11
2.3.2.4 Determining the Clicked Item..............11
2.3.2.5 Moving to a Sub-folder...............11-12
2.3.2.6 Moving One Folder Up...............12-13
2.3.2.7 Refreshing the Current Folder..............13
2.3.2.8 Creating New Folders...............13-15
2.3.2.9 Deleting Folders and Files................15
2.3.2.10 Downloading and Uploading Files........16-18
2.3.2.11 Uploading Dropped Files.............18
2.4 Final Notes.............................19
2.5 Bibliography.............................20

3 | a g e



Abstract
The title oI our project is Bluetooth interfacing in c sharp (#).This will help to show how
to transIer data on Pc, Pocket-Pc and Mobiles etc. via Bluetooth. Sometimes there are
problems transIerring data between two Bluetooth devices. We can't TransIer some type
oI Iiles, we can't discover the data transIer service (protocols), Ior example the OBEX or
FTP protocol. II we have control over two devices, Ior example PC or Pocket PC, we can
create C# programs Ior Iile transIer. This project will show, how to transIer Iiles with
Bluetooth technology with the use oI additional soItware namely MicrosoIt Visual c#.












4 | a g e



Objectives
To create an interIace oI Bluetooth devices through soItware that will search Ior other
Bluetooth devices and then be able to transIer any kind oI data namely Iiles, images also
provides a complete view and control over other Bluetooth devices data.














3 | a g e




Acknowledgment
With sincere respect and gratitude, We would like to thank everybody who has helped us
in this project .Specially We would like to thank our supervisor Mr. Raheel Qureshi
without his humble and kind support it was not possible to complete this project. He
helped us in technical matter as well as mental encouragement. We reckon his extensive
support and guidance throughout the project and even in writing the report. It was a great
learning experience to work with him. Also, he has taught us many practical aspects oI
research.
In addition, We would like to thank Ior his precious guidance in writing this project
report. We would also like to thank Dr.Sikander Hayat Khayal, department chairperson
oI the SoItware Engineering and Computer Science Department, Ior his valuable
suggestions and support.
At same time we like to thank each other Ior making important contribution to this
project and thus producing desired.
Also, we are thankIul Ior all Iaculty members oI the SoItware Engineering and Computer
Science Department Ior helping us Iinish our requirements Ior graduation.








6 | a g e

2.1 Introduction
In this project, we will present a program that lets you browse any device connected to
your computer via Bluetooth and allows you to upload/download Iiles to/Irom the device,
also can delete Iiles and save Iiles. The device should have OBEX support. In order to
connect to a device via Bluetooth and to perIorm OBEX operations, we used these
libraries: 32Ieet.Net and Brecham OBEX
2.2 Requirements
In order Ior this application to Iunction, you need to have Bluetooth on your computer
that uses the MicrosoIt Bluetooth stack and another device with Bluetooth which you will
connect to use this program. II your Bluetooth device uses a non-MicrosoIt stack, then it
is possible to disable it and install the MicrosoIt stack. This program uses the OBEX
library that communicates to a device
Hardware used:
Bluetooth class1 billionton.
Software used:
MicrosoIt Visual C# Express edition 2008
2.3 How the Application Works
.. Connecting
When you run the application, the Iirst thing you should do is connect to the device. You
can choose the device you want to connect to using a dialog that shows the available
Bluetooth devices. AIter the device has been selected, we connect to it and initiate a new
session. The code snippet shows how it is done:
private void Connect()
,
using (SelectBluetoothDeviceDialog bldialog =
new SelectBluetoothDeviceDialog())
,
bldialog.ShowAuthenticated = true;
bldialog.ShowRemembered = true;
bldialog.ShowUnknown = true;

if (bldialog.ShowDialog() == DialogResult.JK)

7 | a g e

,
if (bldialog.SelectedDevice == null)
,
MessageBox.Show("No device selected", "Error",
MessageBoxButtons.JK, MessageBoxIcon.Error);
return;
,

//Create new end point for the selected device.
//BluetoothService.JbexFileTransfer means
//that we want to connect to Jbex service.
BluetoothDeviceInfo selecteddevice = bldialog.SelectedDevice;
BluetoothEndPoint remoteEndPoint = new
BluetoothEndPoint(selecteddevice.DeviceAddress,
BluetoothService.JbexFileTransfer);

//Create new Bluetooth client..
client = new BluetoothClient();
try
,
//... and connect to the end point we created.
client.Connect(remoteEndPoint);

//Create a new instance of JbexClientSession
session = new JbexClientSession(client.GetStream(),
UInt16.MaxValue);
session.Connect(JbexConstant.Target.FolderBrowsing);
,
catch (SocketException ex)
,
ExceptionHandler(ex, false);
return;
,
catch (JbjectDisposedException ex)
,
ExceptionHandler(ex, false);
return;
,
catch (IJException ex)
,
ExceptionHandler(ex, false);
return;
,

bgwWorker.RunWorkerAsync();
,
,
,
First, we show a dialog that displays the available Bluetooth devices. In addition to the
devices that are present at the moment, it will also show those that were connected to the
computer in the past but might not be available now. This can be turned oII by setting the

8 | a g e

ShowRemembered property oI SelectBluetoothDeviceDialog to false. However, in
that case, iI you want to connect to a remembered device, it will not be shown by the
dialog.
AIter the device has been selected, we create a remote end point based on the address oI
the device. The second parameter speciIies the service we want to connect to. In our case,
it is BluetoothService.JbexFileTransfer, meaning that we will be able to transIer
Iiles using the OBEX protocol. Next, we need to create an instance oI the
BluetoothClient class and connect to the end point we created earlier. When the
connection has been established, we create an instance oI the JbexClientSession class.
According to documentation, "|JbexClientSession is| A client-side connection to an
OBEX server, supports Put, Get, and most other operation types." The instance we create
will be used Ior all the OBEX operations we will perIorm. Next, we connect to the Iolder
browsing service so that we can browse the device using OBEX.
Now, when we are connected to the Iolder browsing service oI the device, we can start
exploring it. We will be able to show the Iiles and Iolders, create new Iolders, delete
existing ones, and reIresh Iolder content.
.. Exploring tbe Device
... lxpluylng FolJer Content
In order to get Iolder content, we need to send such a request to the device. Then, we
need to parse(separate) the response we get Irom the device and retrieve the inIormation
we need. The advantage oI the Brecham.Jbex library is that it hides all the low level
OBEX protocol speciIic stuII. It also provides a Iull parser Ior the OBEX Folder-Listing
objects. All we need to do is call the Get method oI the JbexClientSession class,
passing the necessary command and passing the result to the parser. We can then use the
items returned by the parser to populate the listview that shows the Iolder content. All
this is done using the BackGroundWorker class so that the UI is not blocked.

private void bgwWorker_DoWork(object sender, DoWorkEventArgs e)
,
DateTime old = DateTime.Now;
TimeSpan dr = TimeSpan.FromMilliseconds(200);

//Request current folder's content
using (JbexGetStream str = session.Get(null,
JbexConstant.Type.FolderListing))
,
//Pass the response stream to folder listing parser
JbexFolderListingParser parser = new JbexFolderListingParser(str);

9 | a g e

parser.IgnoreUnknownAttributeNames = true;

JbexFolderListingItem item = null;
List<ListViewItem items = new List<ListViewItem();

//Iterate through the items and construct listview items.
while ((item = parser.GetNextItem()) != null)
,
if (item is JbexParentFolderItem)
continue;

JbexFileJrFolderItem filefolderitem = item as
JbexFileJrFolderItem;

bool isfolder = filefolderitem is JbexFolderItem;
ListViewItem temp = new ListViewItem(new string,
,filefolderitem.Name,
FormatSize(filefolderitem.Size,isfolder),
FormatDate(filefolderitem.Modified),
FormatDate(filefolderitem.Accessed),
FormatDate(filefolderitem.Created),,

GetIconIndex(Path.GetExtension(filefolderitem.Name), isfolder));

temp.Tag = isfolder;
temp.Name = filefolderitem.Name;
items.Add(temp);

//Report progress
if (old.Add(dr) < DateTime.Now)
,
old = DateTime.Now;
bgwWorker.ReportProgress(0, temp.Text);
,
,
e.Result = items.ToArray();
,
,
As you can see Irom the above code, we pass null and
JbexConstant.Type.FolderListing to the Get method and then pass the response
stream to the Iolder object parser. We then iterate through the items returned by the
parser and construct the listview items.
... Fxtructlng Icon by Fxtenxlon
All oI the items in the listview have an image associated with them. The image is the icon
associated with the current item's extension, or iI it is a Iolder, then it is just a Iolder icon.
In order to retrieve the icon, I have used code Irom this article: IconHandler. The

10 | a g e

retrieved icon is stored in the imagelist associated with the listview. The icon Ior each
extension is not retrieved iI the imagelist already contains it
private int GetIconIndex(string extension, bool isFolder)
,
//If it is a folder just return index for the folder icon
if (isFolder)
,
return 1;
,

//If the icon for the extension has already
//been retrieved then return its index
if (imlSmall.Images.ContainsKey(extension))
,
return imlSmall.Images.IndexJfKey(extension);
,

//Retrieve small icon
Icon small = IconHandler.IconHandler.IconFromExtension(extension,
IconSize.Small);
if (small != null)
,
imlSmall.Images.Add(extension, small);
,

//Retrieve large icon
Icon large = IconHandler.IconHandler.IconFromExtension(extension,
IconSize.Large);
if (large != null)
,
imlLarge.Images.Add(extension, large);
,

//If we managed to retrieve only one icon, use it for both sizes.
if (small != null & large == null)
,
imlLarge.Images.Add(extension, small);
,
if (small == null & large != null)
,
imlSmall.Images.Add(extension, large);
,

int result = small == null & large == null . 0 :
imlSmall.Images.IndexJfKey(extension);

small.Dispose();
large.Dispose();

return result;
,

11 | a g e

... Nuvlgutlng through FolJerx
When a user double-clicks an item in the listview, the item is processed according to its
type. II it is a Iolder, the program moves into the chosen sub-Iolder and displays its
content. II it is a Iile, it is downloaded. But, beIore an item can be processed, it is Iirst
necessary to determine the item which was clicked.
...4 etermlnlng the CllckeJ Item
In order to determine which item was double-clicked, we can use the HitTest method oI
the ListView class. This method accepts a Point parameter, and returns an instance oI
the ListViewHitTestInfo class. This class has an Item property which, as you might
have already guessed, points to the item that was double-clicked.
prlvaLe vold lsvLxplorer_MouseuoubleCllck(ob[ecL sender MouseLvenLArgs e)
,
ListViewItem clicked = lsvExplorer.HitTest(e.Location).Item;

if (clicked != null)
,
if ((bool)clicked.Tag)
ProcessFolder(clicked.Text);
else
DownloadFiles();
,
,
...SMovlng to u Sub-folJer
II the clicked item represents a Iolder, we need to set the path on the connected device to
a sub-Iolder location. AIter that, we can display its content by starting a
BackGroundWorker like we did to display the initial view. But, beIore new content is
displayed, the current items displayed by the listview are pushed into a stack. They will
be used later when the user moves one Iolder up.
private void ProcessFolder(string folderName)
,
try
,
//Set path on the device
session.SetPath(folderName);
,
catch (IJException ex)
,
ExceptionHandler(ex);
return;

12 | a g e

,

//Push current items into stack
ListViewItem, previousItems =
new ListViewItemlsvExplorer.Items.Count,;
lsvExplorer.Items.CopyTo(previousItems, 0);
lsvExplorer.Items.Clear();
previousItemsStack.Push(previousItems);

SetControlState(false);
tsStatusLabel.Text = "Jperation started";

//Display current folder's content.
bgwWorker.RunWorkerAsync();
,
...6Movlng One FolJer Up
The user can move one Iolder up by clicking the 'Up' button on the menu. When this
button is clicked, we need to change the current path to the parent Iolder's path and
display its content. As we have pushed the parent Iolder's content into the stack, we don't
need to request items Ior the second time.
private void MoveUp()
,
//Check if we are at the topmost folder.
if (previousItemsStack.Count 0)
,
SetControlState(false);

try
,
//Set path to parent folder.
session.SetPathUp();
,
catch (IJException ex)
,
ExceptionHandler(ex);
return;
,

//Clear current items and display saved ones.
lsvExplorer.Items.Clear();
lsvExplorer.Items.AddRange(previousItemsStack.Pop());
SetControlState(true);
,
,

13 | a g e

As the items displayed by the listview were Ietched some time ago, the Iolder's content
may not reIlect the current content. In order to view the current items, you can click the
'ReIresh' button.
...7Refrexhlng the Current FolJer
ReIreshing the current Iolder's content is quite easy as the path is already set. We just
need to run our BackGroundWorker once again.
private void RefreshFolder()
,
SetControlState(false);
tsStatusLabel.Text = "Jperation started";
lsvExplorer.Items.Clear();

bgwWorker.RunWorkerAsync();
,
...8Creutlng New FolJerx
Creating a new Iolder is a little bit trickier than any other operation. BeIore we can create
a new Iolder, we should make sure that such a Iolder does not already exist. II the Iolder
does not exist, we can create it. When a user clicks the 'New Folder' button, a new item is
added to the listview and the BeginEdit() method is called Ior the item.
private void CreateNewFolder()
,
ListViewItem newitem = new ListViewItem("", 1);

lsvExplorer.Items.Add(newitem);
lsvExplorer.LabelEdit = true;

newitem.BeginEdit();
,
When the user ends typing the name Ior the new Iolder, the AfterLabelEdit event oI the
ListView class is Iired. In the event handler, we check whether the Iolder exists or not,
and create it, iI it does not exist
private void lsvExplorer_AfterLabelEdit(object sender,
LabelEditEventArgs e)
,
if (string.IsNullJrEmpty(e.Label))
,
e.CancelEdit = true;
lsvExplorer.Items.RemoveAt(e.Item);
return;
,

14 | a g e


//If folder already exists show a messagebox.
if (lsvExplorer.Items.ContainsKey(e.Label))
,
if (MessageBox.Show(string.Format("There is already a folder called
,0,",
e.Label), "Error", MessageBoxButtons.JKCancel,
MessageBoxIcon.Error) == DialogResult.JK)
,
//If JK is clicked continue editing the item.
e.CancelEdit = true;
lsvExplorer.Itemse.Item,.BeginEdit();
,
else
,
//If Cancel is clicked, we need to remove item from the
listview.
lsvExplorer.LabelEdit = false;
lsvExplorer.BeginInvoke((MethodInvoker)(() =
,
lsvExplorer.Items.RemoveAt(e.Item);
,));
,
,
//Folder does not exist.
else
,
e.CancelEdit = false;
lsvExplorer.LabelEdit = false;
lsvExplorer.Itemse.Item,.Name = e.Label;

SetControlState(false);
try
,
//Create new folder and move up one folder
//so that path is not set to newly created folder.
session.SetPath(BackupFirst.DoNot, e.Label,
IfFolderDoesNotExist.Create);
session.SetPathUp();
,
catch (IJException ex)
,
ExceptionHandler(ex);
return;
,
catch (JbexResponseException ex)
,
ExceptionHandler(ex);
,
SetControlState(true);
,
,

13 | a g e

As you can see Irom the above code, we Iirst check iI a Iolder with such a name already
exists. II yes, we show a message box inIorming the user about it. II the user clicks OK,
then editing continues, and a new name can be speciIied Ior the Iolder. II Cancel is
clicked, we need to remove the item which we added. As you can see, it is done on
another thread. The reason Ior such a behavior is that iI you try to remove it in the event
handler, you will get an exception that you will be unable to catch. In case the Iolder does
not exist, we create it by calling the SetPath method and passing the name oI the new
Iolder. As we want to create a Iolder, we also speciIy IIFolderDoesNotExist.Create
indicating that a Iolder should be created iI it does not exist. AIter that, the current path is
set to the newly created Iolder, so we need to move one Iolder up.
...9eletlng FolJerx unJ Fllex
In order to delete Iiles or Iolders Irom the device, we can use the Delete method oI the
JbexClientSession class and pass the name oI the item we want to delete. When
deleting a Iolder, its contents are deleted too, so be careIul.
private void DeleteSelectedItems()
,
if (MessageBox.Show("Do you really want to delete selected items.",
"Confirm", MessageBoxButtons.JKCancel,
MessageBoxIcon.Question) == DialogResult.JK)
,
lsvExplorer.BeginUpdate();

SetControlState(false);
foreach (ListViewItem item in lsvExplorer.SelectedItems)
,
try
,
session.Delete(item.Text);
,
catch (IJException ex)
,
ExceptionHandler(ex);
return;
,
item.Remove();
,

lsvExplorer.EndUpdate();
SetControlState(true);
,
,

16 | a g e

... ownlouJlng unJ UplouJlng Fllex
In order to download or upload Iiles, you can use the GetTo or PutFrom methods.
However, to report progress, you will need to create a new stream type and use it in
conjunction with the Decorator Pattern. A simpler way Ior progress reporting is to use the
Get and Put methods. Both oI them return a Stream object. In the case oI downloading,
we should read Irom the returned stream and write to the FileStream object, and in the
case oI uploading, we should read Irom the FileStream and write to the stream returned
by the Put method. In both cases, we can count how many bytes we have read and report
progress depending on it. This is done using the BackgroundWorker too.
private void bgwWorker_DoWork(object sender, DoWorkEventArgs e)
,
long progress = 0;
DateTime start = DateTime.Now;

for (int i = 0; i < filesToProcess.Count; i++)
,
string currentfile = filesToProcessi,;

//Report that we started downloading new file
bgwWorker.ReportProgress((int)(((progress 100) / totalsize)), i +
1);

string filename = download . Path.Combine(dir, currentfile) :
currentfile;

//Stream on our file system. We will need to either read from it or
write to it.
FileStream hoststream = download .
new FileStream(filename, FileMode.Create, FileAccess.Write,
FileShare.None)
: new FileStream(filename, FileMode.Jpen, FileAccess.Read,
FileShare.None);

AbortableStream remotestream = null;
try
,
//Stream on our device. We will need to either read from it or
write to it.
remotestream = download .
(AbortableStream)currentSession.Get(currentfile, null)
:
(AbortableStream)currentSession.Put(Path.GetFileName(currentfile),
null);
,
catch (IJException ex)
,
exceptionoccured = true;
ExceptionMethod(ex);

17 | a g e

return;
,
catch (JbexResponseException ex)
,
exceptionoccured = true;
ExceptionMethod(ex);
return;
,
using (hoststream)
,
using (remotestream)
,
//This is the function that does actual reading/writing.
long result = download .
ProcessStreams(remotestream, hoststream, progress,
currentfile)
:ProcessStreams(hoststream, remotestream,
progress, currentfile);

if (result == 0)
,
e.Cancel = true;
//Even if we are cancelled we need to report how many files
we have already
//uploaded so that they are added to the listview. Jr if it
is download we
//need to delete the partially downloaded last file.
filesProcessed = i;
return;
,
else
progress = result;
,
,
,
DateTime end = DateTime.Now;
e.Result = end - start;
,
As the process is similar in both cases, there is one Iunction that does the actual work.
The Iunction reads Irom the source stream and writes to the destination stream. This is
how it works.
private long ProcessStreams(Stream source, Stream destination, long
progress,
string filename)
,
//Allocate buffer
byte, buffer = new byte1024 4,;
while (true)
,
//Report downloaded file size

18 | a g e

bgwWorker.ReportProgress((int)(((progress 100) / totalsize)),
progress);

if (bgwWorker.CancellationPending)
,
currentSession.Abort();
return 0;
,

try
,
//Read from source and write to destination.
//Break if finished reading. Count read bytes.
int length = source.Read(buffer, 0, buffer.Length);
if (length == 0) break;
destination.Write(buffer, 0, length);
progress += length;
,
//Return 0 as if operation was cancelled so that processedFiles is
set.
catch (IJException ex)
,
exceptionoccured = true;
ExceptionMethod(ex);
return 0;
,
catch (JbexResponseException ex)
,
exceptionoccured = true;
ExceptionMethod(ex);
return 0;
,
,
return progress;
,
... UplouJlng roppeJ Fllex
When Iiles are dropped on the main Iorm Irom Windows Explorer, they are automatically
uploaded to the device. In order to detect dropped Iiles, We just need to subscribe to the
FileDropped event.
private void DragDrop_FileDropped(object sender, FileDroppedEventArgs
e)
,
UploadFiles(e.Filenames);
,
That's all Ior downloading and uploading. The download/upload dialog reports the time
spent and the average speed.

19 | a g e

2.4 Final Notes
We have tested this application with Bluetooth device attached with laptop and it works
well. We have not done anything to target it speciIically Ior above scenario, so it should
work with other too, though we have not tested. Future work requires simulation in the
above code.




20 | a g e

2.5 Biblography
1. Frequently Asked Questions About USB Flash Drives. Peripherals.about.com
(2010-06-17). Retrieved on 2011-05-18.
2. MobileWhack-Kingston-256GB "Kingston unveils 256GB thumb",
MobileWhack.com, July 20, 2009
3. AboutCom-Swivel-Pro-Flash "Imation Swivel Pro Flash Drive", About.com,
2008

You might also like