Friday 22 April 2011

BlueTooth Programming


iPhone BlueTooth Programming

One of the neat features available in iPhone OS 3.0 is the GameKit framework. The GameKit framework contains APIs to allow communications over a Bluetooth network. Using these APIs, you can create peer-to-peer games and applications with ease. Unlike other mobile platforms, using Bluetooth as a communication channel in iPhone is way easier than expected. Hence, in this article, I will show you how to build a simple application that allows two iPhone or iPod Touch devices to communicate with each other.

All the various APIs for accessing the Bluetooth is located in the GameKit framework. Hence, you need to add this framework to your project.

In the BluetoothVC.h file, declare the following object, outlets, and actions:

#import "UIKit/UIKit.h"

#import "GameKit/GKSession.h"
#import "GameKit/GKPeerPickerController.h"

@interface BluetoothVC : UIViewController {

GKSession *currentSession;
UITextField *textField;


}

@property (nonatomic, retain) GKSession *currentSession;

-(void)setBlueToothConnection;

@end

The GKSession object is used to represent a session between two connected Bluetooth devices. You will make use of it to send and receive data between the two devices.

In the BluetoothVC.m file, add in the following statements in bold: 

#import "BluetoothVC.h"

@implementation BluetoothVC
@synthesize currentSession;

GKPeerPickerController *picker;

- (void)loadView {

UIView *mainView=[[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];

mainView.backgroundColor=[UIColor grayColor];

self.view= mainView;

[mainView release];


textField= [[UITextField alloc] initWithFrame:CGRectMake(10, 8, 120, 30)];
textField.backgroundColor = [UIColor clearColor];
[textField setFont:[UIFont boldSystemFontOfSize:12]];
textField.placeholder = @"Enter First Name";
//textField.tag = kFieldTag;
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
textField.text = kEmptyText;

textField.autocorrectionType= UITextAutocorrectionTypeNo;
textField.autocapitalizationType = UITextAutocapitalizationTypeWords;
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;

[self.view addSubview:textField];


UIButton *mButton= [[UIButton alloc]initWithFrame:CGRectMake(5, 45, 120 , 35)];
[mButton addTarget:self action:@selector(ButtonAction:) forControlEvents:UIControlEventTouchUpInside];
//[mButton setTag:kButtonTag];
[mButton setTitle:@"send" forState:UIControlStateNormal];

[self.view addSubview:mButton];
[mButton release];

UIButton *mButton1= [[UIButton alloc]initWithFrame:CGRectMake(5, 45, 120 , 35)];
[mButton1 addTarget:self action:@selector(ButtonAction1:) forControlEvents:UIControlEventTouchUpInside];
[mButton1 setTag:1];
[mButton1 setTitle:@"Connect" forState:UIControlStateNormal];

[self.view addSubview:mButton1];
[mButton1 release];

UIButton *mButton2= [[UIButton alloc]initWithFrame:CGRectMake(5, 85, 120 , 35)];
[mButton2 addTarget:self action:@selector(ButtonAction2:) forControlEvents:UIControlEventTouchUpInside];
[mButton2 setTag:2];
[mButton2 setTitle:@"Connect" forState:UIControlStateNormal];
[mButton2 setHidden:YES];     
[self.view addSubview:mButton2];
[mButton2 release];

}

- (void)dealloc {
[super dealloc];
[textField release];
}
Here it look like this:


Button Actions perfromed Here:
Connect Funcationality
-(void)ButtonAction1:(id)sender {

picker = [[GKPeerPickerController alloc] init];
picker.delegate = self;
picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby;
uiButton *button1 = (uibutton *) [self.view viewWithTag:1];
uiButton *button2 = (uibutton *) [self.view viewWithTag:2];
[button1 setHidden:YES];
[button2 setHidden:NO];  
[picker show];
}

   
Send Functionality:


-(void)ButtonAction:(id) sender
{
//---convert an NSString object to NSData---
NSData* data;
NSString *str = [NSString stringWithString:textField.text];
data = [str dataUsingEncoding: NSASCIIStringEncoding];

if (currentSession)
[self.currentSession sendDataToAllPeers:data withDataMode:GKSendDataReliable
error:nil];
}


Disconnect Functionality:
-(void) ButtonAction2:(id) sender {
[self.currentSession disconnectFromAllPeers];
[self.currentSession release];
currentSession = nil;

uiButton *button1 = (uibutton *) [self.view viewWithTag:1];
uiButton *button2 = (uibutton *) [self.view viewWithTag:2];
[button1 setHidden:NO];
[button2 setHidden:YES];
}


General Functionality:

When data is received from the other device, the receiveData:fromPeer:inSession:context: method will be called. Implement this method as follows:

Note: maintain SessionID unique between devices. Otherwise device doesn't identify the other device.
- (GKSession *)peerPickerController: (GKPeerPickerController *) picker
sessionForConnectionType: (GKPeerPickerConnectionType) type {

GKSession* session = [[GKSession alloc] initWithSessionID: @"HelloWorldID"
displayName: [mAppDelegate uID]
sessionMode: GKSessionModePeer];
[session autorelease];
return session;
}

- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session {
self.currentSession = session;
session.delegate = self;
[session setDataReceiveHandler:self withContext:nil];
picker.delegate = nil;

[picker dismiss];
[picker autorelease];
}

- (void)peerPickerControllerDidCancel:(GKPeerPickerController *)picker
{
picker.delegate = nil;
[picker autorelease];
}


- (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state {

switch (state)
{
case GKPeerStateConnected:
NSLog(@"connected");
break;
case GKPeerStateDisconnected:
NSLog(@"disconnected");
[self.currentSession release];
currentSession = nil;
break;

default:
break;
}
}

- (void) receiveData:(NSData *)data
fromPeer:(NSString *)peer
inSession:(GKSession *)session
context:(void *)context {

NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
NSDictionary *myDictionary = [[unarchiver decodeObjectForKey:@"points"] retain];
[unarchiver finishDecoding];
[unarchiver release];

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Data received"
message:[myDictionary valueForKey:@"eventid"]
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}

    

Here, the received data is in the NSData format. To display it using the UIAlertView class, you need to convert it to an NSString object.

 

3 comments:

  1. wow! very nice article.. this will be a great help for me in the furture.

    cheers!

    ReplyDelete
  2. I have a question and the question is that I want to connect multiple iPhone's or iPod's thorugh bluetooth only once, and after that I want to send the data from any where view. it is possible...???

    is you have know this answer then give it to my mail address (rejected_boy@live.com)

    ReplyDelete
  3. @chandaboy Only one device can be connected at once. To connect two or more devices Connect Functionality should be recursively. I hope I have explained enough you to understand

    ReplyDelete