iOS Using Bluetooth to talk to other iOS Devices

Stephen Zaharuk / Friday, May 17, 2013

So here's the scenario. You're writing an app, and you realize that it would be really cool if the stuff your app creates could be shared with other people. Sure you can go down the typical root of sharing through e-mail, dropbox, iMessage, etc.. 

However, your app is a collaborative tool, and the person who you want to share with, sits right across from you. It seems kind of silly to send your file to some server somewhere and bounce it back to them. 

Well, today i'm going to show you a cool way to share your files via Bluetooth!

It turns out, Apple made this pretty easy. They created a class called GKSession which lives in the GameKit.Framework. 

Now GKSession, provides the means to setup communication, but there is a bit of setup and management that you have to do. So to make things SUPER easy, i created a helper class which will take care of everything else so that you can focus on your application.

So, before we get started make sure you add GameKit.framework to your project.

Next, download my helper classes, unzip them, and add them to your project.(Make sure you mark the .m file to be compiled.)

Now lets get down to coding!!

1. Add an import statement for the btmanager: 

#import "BTManager.h"

2. Create an instance of the BTManager. Note: It's important that you create the BTManager when your application first opens. It will need to always exist, so that a line of communication can be established between other devices that have your app open. 

You can optionally create an instance of the BTManager with an identifier. This identifier is used to identify/locate other apps that have the same identifier. If you do not specify an identifier  your app bundle identifier is used instead. 

_btManager = [[BTManager alloc]initWithSessionID:@"myApp"];
_btManager.delegate = self;

3. If you noticed i set the delegate to the class that i'm currently on. The delegate you need to implement is called: BTManagerDelegate. This delegate is what you'll use to be notified when you are sending/receiving data. You can use these methods to find out when you've received all of the data, and to track the progress of data being sent/received. 

4. So now everything is setup!. So lets say i want to send a message to another device. The first thing i need to do is look for any devices(aka peers) that currently have an app open with the same identifier that i passed into the initializer of my BTManager. To do that, i'll call "lookForPeers" which will return an NSArray* of BTPeer objects. A BTPeer object has 2 properties: an identifier which is some unique id of a device and a name. The name is the actual human readable name of the device.  Note: if no devices are found then the array is empty. 

NSArray* peers = [_btManager lookForPeers];

5. Now, with that list of peers, i could create a UI for the user to select the peer to send my data to. But, for the sake of simplicity, we'll send our data to the first device we find:

if(peers.count > 0)
   NSData* data = [@"Hello World" dataUsingEncoding:NSUTF8StringEncoding];
   [_btManager sendData:data toPeer:peers[0]];

6. As long as both devices are still active, the data will be sent. And we can track the status via the various methods on the BTManagerDelegate that i mentioned earlier. However, the one that we really care about in this case is: btManager:finishedReceivingData:

-(void)btManager:(BTManager*)btManager finishedReceivingData:(NSData*)data
    NSString* val = [NSString stringWithUTF8String:[data bytes]];

And voila, you've just sent a message to another device!

It's worth nothing that BTManager does some useful things, such as breaking your data down into smaller packets, so that you're not sending really large files in one massive chunk. It also disconnects it's bluetooth handler when your app goes into the background, and likewise starts it back up when it comes back into the foreground.

Now what are you waiting for?! Download the code and have some fun! Feel free to modify the code to fit your own projects as needed. 

By Stephen Zaharuk (SteveZ)