Thursday, March 26, 2009

Sample Source Code : iPhone OS 3.0 peer to peer bluetooth connectivity

Just saw a sample source code from the apple dev forum to sharing the testing the p2p bluetooth

What you need to do is to create a new project from OpenGL ES Application of iPhone OS 3.0 SDK template called it BluetoothSample
and past the codes as below and test, it should work on 2 iPhone 3G and iPod Touch 2nd gen only.

Then you need to add GameKit framework to build and go

The source is from Travis True

BluetoothSampleAppDelegate.h Select all

//
// BluetoothSampleAppDelegate.h
// BluetoothSample
//

#import "EAGLView.h"
#import <GameKit/GameKit.h>

@interface BluetoothSampleAppDelegate : NSObject {
UIWindow *window;
EAGLView *glView;

GKPeerPickerController *picker;
GKSession *session;

int myNumber;
NSData *myData;
UILabel *textView;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet EAGLView *glView;
@property (nonatomic, retain) GKPeerPickerController *picker;
@property (nonatomic, retain) GKSession *session;

- (void)mySendData;

@end



BluetoothSampleAppDelegate.m Select all

//
// BluetoothSampleAppDelegate.m
// BluetoothSample
//

#import "BluetoothSampleAppDelegate.h"

@implementation BluetoothSampleAppDelegate

@synthesize picker;
@synthesize session;
@synthesize window;
@synthesize glView;

- (void)applicationDidFinishLaunching:(UIApplication *)application {

// setup the text view
myNumber = 0;
textView = [[UILabel alloc] initWithFrame:CGRectMake(10.0f, 10.0f, 640.0f, 12.0f)];
textView.text = [NSString stringWithFormat:@"myNumber: %i\n", myNumber];
[window addSubview:textView];
[window bringSubviewToFront:textView];

// start the EAGLView
glView.animationInterval = 1.0 / 60.0;
[glView startAnimation];

// allocate the NSData
myData = [[NSData alloc] initWithBytes:&myNumber length:sizeof(int)];


// allocate and setup the peer picker controller
picker = [[GKPeerPickerController alloc] init];
picker.delegate = self;
picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby | GKPeerPickerConnectionTypeOnline;
[picker show];
}


- (void)applicationWillResignActive:(UIApplication *)application {
glView.animationInterval = 1.0 / 5.0;
}


- (void)applicationDidBecomeActive:(UIApplication *)application {
glView.animationInterval = 1.0 / 60.0;
}


- (void)peerPickerController:(GKPeerPickerController *)picker didSelectConnectionType:(GKPeerPickerConnectionType)type {
if(type == GKPeerPickerConnectionTypeOnline) {
[self.picker dismiss];
[self.picker release];
self.picker = nil;
// Display your own UI here.
}
}


- (GKSession *) peerPickerController:(GKPeerPickerController *)picker
sessionForConnectionType:(GKPeerPickerConnectionType)type {
session = [[GKSession alloc] initWithSessionID:@"FR" displayName:nil sessionMode:GKSessionModePeer];
session.delegate = self;

return session;
}


- (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state {
switch (state) {
case GKPeerStateConnected:
[self.session setDataReceiveHandler :self withContext:nil];
[self mySendData]; // start off by sending data upon connection
break;

case GKPeerStateDisconnected:
break;
}
}


- (void)peerPickerController:(GKPeerPickerController *)picker didConnectToPeer:(NSString *)peerID {
printf("connection was successful! start the game.\n");
}


- (void)peerPickerControllerDidCancel:(GKPeerPickerController *)picker {
printf("connection attempt was canceled\n");
}


- (void)mySendData {
// allocate the NSData
myNumber++;
myData = [[NSData alloc] initWithBytes:&myNumber length:sizeof(int)];
[session sendDataToAllPeers :myData withDataMode:GKSendDataReliable error:nil];
printf("send data: %i\n", myNumber);
textView.text = [NSString stringWithFormat:@"myNumber: %i\n", myNumber];
}


- (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context
{
// Read the bytes in data and perform an application-specific action, then free the NSData object
[data getBytes:&myNumber length:sizeof(int)];
printf("received data: %i from: %s\n", myNumber, [peer UTF8String]);
textView.text = [NSString stringWithFormat:@"myNumber: %i\n", myNumber];

[self mySendData];
}


- (void)dealloc
{
[picker release];
[session release];
[textView release];
[glView release];
[window release];
[super dealloc];
}


@end

22 comments:

  1. Ok, so my question is, how do you actually test this? You can't deploy to a device yet. Does the SDK use the mac's bluetooth? Does it talk from one simulator to another?!

    ReplyDelete
  2. If you have two devices with OS 3.0 beta, you can test it.

    Or you can test one iPhone device with the iPhone Simulator, SDK beta 2 Simulator and iPhone OS 3.0 beta 2 support this.

    ReplyDelete
  3. Thanks for sharing the code. i was able to compile it just fine but I can't get the connection to work with an iPhone 3G with os3 and the newest SDK Simulator. is there any special trick to it or a special setting on the simulator I'm missing.

    ReplyDelete
  4. For me, the GameKit framework did not exist in the default location, but in Developer/Platforms/iPhoneOS.platform/Developer/SKDs/iPhoneOS3.0.skd/System/Library/Frameworks.

    Is this a problem? Does it conflict with the other framework's versions?

    Thanks a lot to anyone who can help.

    ReplyDelete
  5. You also need to have your interface implement the GKSessionDelegate and GKPeerPickerControllerDelegate protocols in order to get this to compile. I am trying this on two iPod touches. I can get them to send and receive data, but the Peer Picker dialog never goes away. I am dismissing and releasing it in the didConnectToPeer method, but it seems to never get called. Stepping through the code I can see that the state does change to connected, but I can't dismiss the dialog in order to return to my original view. Frustrating that there aren't more examples than this. There must be thousands of developers working on this right now.

    ReplyDelete
  6. Not only in opengl app,It aslo worked in viewcontroller.And it will also talk from simulator to simulator.I need to know that how we set a name for a particular bluetooth device(iphone/ipod)

    ReplyDelete
  7. Hey guys i am new to iphone programming. I tried to build this with iphone sdk 3.0 simulator and got these errors.


    ".objc_class_name_GKSession", referenced from:
    literal-pointer@__OBJC@__cls_refs@GKSession in BluetoothSampleAppDelegate.o
    ".objc_class_name_GKPeerPickerController", referenced from:
    literal-pointer@__OBJC@__cls_refs@GKPeerPickerController in BluetoothSampleAppDelegate.o
    ld: symbol(s) not found
    collect2: ld returned 1 exit status


    could some one help me on this

    ReplyDelete
  8. amm, nice tut... could you tell me, can i use it for connecting iphone with mac? not iphone2iphone

    ReplyDelete
  9. Mathew,what you need to do is add a GameKit framework as well as import a header file
    (#import GameKit/GameKit.h) in .h file

    in order to add a framework,open the frameworks folder in Groups & files at the left of the screen.
    Right click on any of the framework and choose
    "open with finder"

    Here you will see a list of frameworks,in that select
    Gamekit framework,Drag and Drop it in your frameworks folder,you will get a pop up window with checkbox at top left corner,"DONT CLICK THE
    CHECKBOX" .click Add,now build the code and it runs.

    ReplyDelete
  10. Does anyone else get a "error: 'expected specific-qualifier-list before 'GKPeerPickerController'" when they try and build this

    ReplyDelete
  11. Hey Matthew... ever solve your issue? I get the same error, and the GameKit framework was already added and I also have the import GameKit.h line in my .h file.. otherwise does anyone else have any ideas?

    ReplyDelete
  12. I have 2 warnings

    BluetoothSampleAppDelegate.m:35: warning: class 'BluetoothSampleAppDelegate' does not implement the 'GKPeerPickerControllerDelegate' protocol

    BluetoothSampleAppDelegate.m:64: warning: class 'BluetoothSampleAppDelegate' does not implement the 'GKSessionDelegate' protocol

    ReplyDelete
  13. Those two warnings, I've noticed, happen when I compile for the SIMULATOR, but not for an actual device. I think adding the gamekit library from the simulator directory (search for gamekit, you'll see there are copies for both "platforms") will fix that.

    Beyond that, this seems to be working for me -- on top of my original opengl, which I was worried about. Nice!

    ReplyDelete
  14. Hi there,

    I have different quetion. Is it possible with iPhone SDK somehow to just list (without connecting) MAC addresses of bluetooth devices in range?

    ReplyDelete
  15. I too get the warnings in the SDK, however it doesn't matter what you're running it on (device or sim) the build will always show the warnings unless you fix them.

    ReplyDelete
  16. Could i connect to iphone and other bluetooth device ?


    hi...
    i want to develop one iPhone application , it should be capable to connect and send data with other bluetooth device ( it may be iphone/ ipod touch,other mobile phone or any bluetooth device , such as PC, bluetooth sticker and so on..)

    is it possible in iphone using iPhone programming code.. ?

    is possible pls give the the way...

    pls help me ..

    ReplyDelete
  17. How to sovle the "error: EAGLView.h: No such file or directory"?
    In my code ,the "EAGLView *glView;" ,which about the forword thing(EAGLView) didn't change color. Who can tell me the reason?

    Thanks a lot~~

    ReplyDelete
  18. How to sovle the "error: request for member 'animationInterval' in something not a structure or union"?

    What's this sector meaning?

    // start the EAGLView
    glView.animationInterval = 1.0/60.0;
    [glView startAnimation];


    Thanks!

    ReplyDelete
  19. "How to sovle the "error: request for member 'animationInterval' in something not a structure or union"?"

    Change every instance of "animationInterval" to "animationFrameInterval" and see if that works. (Apparently the implementation of EAGLView.h has changed since this code was originally written.)

    ReplyDelete
  20. Hi,
    just change it to glView.animationFrameInterval

    It wil work (:

    ReplyDelete
  21. Picker Dialog dismisses as follows,


    switch (state) {
    case GKPeerStateConnected:
    [self.picker dismiss];// addtional line

    ReplyDelete
  22. I am new to iphone programmaing.I am implementing a Quiz app between number of users via bluetooth.My question is that when i establish connection between two iphones then when the view changes will the bluetooth connection will be ended. Will the classes with new view will be able to get data through bluetooth without re-establishing connection.

    ReplyDelete