iOS GameKit – iPhone to iPhone communication

Digging around the internet I’ve seen some snippets of code here and there with errors and that were outdated so I present to you here a quick tutorial for quickly getting two iOS devices (iOS 3.0+) to connect and talk with one another, sending a simple string.

Actually, instead of explaining, you’ll be copying and pasting and hooking up XIB elements and you’ll see for yourself. Make sure you have at least two iOS devices and install your application on them.

Create a simple view-based application in Xcode. Make sure to add the GameKit framework to your project. If you’re using Xcode 4, select the project and under Build Phases open up Link Binary with Libraries. Click the + button and choose GameKit.framework.

In your viewController’s .h file make sure it looks like this (lots of people leave out the defined delegates I have noticed in old code):

#import <UIKit/UIKit.h>
#import <GameKit/GameKit.h>

@interface BluetoothViewController : UIViewController <GKPeerPickerControllerDelegate, GKSessionDelegate> {
    GKSession *currentSession;
    IBOutlet UITextField *txtMessage;
    IBOutlet UIButton *connect;
    IBOutlet UIButton *disconnect;
}

@property (nonatomic, retain) GKSession *currentSession;
@property (nonatomic, retain) UITextField *txtMessage;
@property (nonatomic, retain) UIButton *connect;
@property (nonatomic, retain) UIButton *disconnect;

-(IBAction) btnSend:(id) sender;
-(IBAction) btnConnect:(id) sender;
-(IBAction) btnDisconnect:(id) sender;

@end

Now in your .m, use this code (and make sure to create the 4 elements in your XIB file… hook them up appropriately).

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

@implementation BluetoothViewController

@synthesize currentSession;
@synthesize txtMessage;
@synthesize connect;
@synthesize disconnect;

GKPeerPickerController *picker;

-(IBAction) btnConnect:(id) sender {
    picker = [[GKPeerPickerController alloc] init];
    picker.delegate = self;
    picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby;
    [connect setHidden:YES];
    [disconnect setHidden:NO];
    [picker show];
}

- (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];

    [connect setHidden:NO];
    [disconnect setHidden:YES];
}

-(IBAction) btnDisconnect:(id) sender {
    [self.currentSession disconnectFromAllPeers];
    [self.currentSession release];
    currentSession = nil;

    [connect setHidden:NO];
    [disconnect setHidden:YES];
}

- (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;

            [connect setHidden:NO];
            [disconnect setHidden:YES];
            break;
        case GKPeerStateAvailable:
        case GKPeerStateConnecting:
        case GKPeerStateUnavailable:
            break;
    }
}

- (void) mySendDataToPeers:(NSData *) data
{
    if (currentSession)
        [self.currentSession sendDataToAllPeers:data
                                   withDataMode:GKSendDataReliable
                                          error:nil];
}

-(IBAction) btnSend:(id) sender
{
    //---convert an NSString object to NSData---
    [txtMessage resignFirstResponder];
    NSData* data;
    NSString *str = [NSString stringWithString:txtMessage.text];
    data = [str dataUsingEncoding: NSASCIIStringEncoding];
    [self mySendDataToPeers:data];
}

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

    //---convert the NSData to NSString---
    NSString* str;
    str = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Data received"
                                                    message:str
                                                   delegate:self
                                          cancelButtonTitle:@"OK"
                                          otherButtonTitles:nil];
    [alert show];
    [alert release];
}

- (void)dealloc
{
    [txtMessage release];
    [currentSession release];
    [super dealloc];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
    [connect setHidden:NO];
    [disconnect setHidden:YES];
    [super viewDidLoad];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

@end

If you hooked up the items properly you should be good to go. Run the application on at least two devices. Hit “Connect” on both devices. On one of the devices select the name of the other device. The other device will ask if it’s okay to connect. Choose Accept. You can now send strings back and forth between the iOS devices using BlueTooth and the GameKit framework. It’s not as elegant as anonymous or transparent connection, but it works.

Related Posts Plugin for WordPress, Blogger...

22 thoughts on “iOS GameKit – iPhone to iPhone communication

    1. Brian Vaughn

      Hey mate. To use Wifi/internet, you’d need to configure your picker by changing…

      picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby;

      …to…

      picker.connectionTypesMask = GKPeerPickerConnectionTypeOnline;

      Reply
  1. Kasper

    Hi – Thanks for the article

    I wonder if it is possible to create two apps, that connect to each other with GameKit. That is 2 apps with different App ID.

    In my scenario I would like to send an image taken from an iPhone, to a app created for iPad – Do you think that is possible?

    Cheers

    Reply
    1. Kasper

      Found the answer. I just had to put this in the GKPeerPickerDelegate:

      #pragma mark – GKPeerPickerControllerDelegate
      – (GKSession *)peerPickerController:(GKPeerPickerController *)picker sessionForConnectionType:(GKPeerPickerConnectionType)type {
      // Create a session with a unique session ID – displayName:nil = Takes the iPhone Name
      GKSession* session = [[GKSession alloc] initWithSessionID:@”customName” displayName:nil sessionMode:GKSessionModePeer];
      return [session autorelease];
      }

      Have a nice day

      Reply
  2. Arun

    Thus the above code simply crashing when i changed the connection type to online from NearBy.Can any body help me with this

    Reply
  3. Shatthi

    The tutorial is very helpful in understanding bluetooth communication between two appliactions using Gamekit.
    Is it possible to initiate bluetooth communication from iphone application to another iphone’s bluetooth feature (without having an application installed in it) ?

    Reply
  4. Chris

    Hi,

    I’m a bit of a programming beginner, but for a project I’m looking to use this basic idea to send information between 2 devices. I notice that you say to include the 4 elements in you XIB file but I can only see 3 elements being synthesized? Unless GKsession is an element in which case what do I have to put there? Also, where would the send actrion be connected to?

    Again, I apologise if these are obvious questions, I’ve got 3 weeks to complete this project and I’m starting to struggle!

    Thanks

    Reply
  5. Garrett

    Thanks for the tutorial…is it possible to connect more than two devices?

    If so, what would be the max number of devices?

    Thanks

    Reply
  6. Ryan

    Hi Eric,
    I am pretty new to programming so I was wondering if you could either show/explain to me what the user interface should look like. Thank you for your help.

    Reply
  7. GW

    Hello! thank u so much for the great tutorial!
    I have one question though ;) if you don’t mind.
    will it be possible that if I send back and forth audio files? not txt.
    if I can, where should I implement or save audio files?
    thank you!

    Reply
  8. CJ

    Hello great tutorial,

    Just wondering i have two labels that have different text that i want to send. how would i go about doing this?

    Reply
      1. CJ

        Sorry,

        what i mean is say i have label one and label 2, label one has say the number 123 and label two has got the number 456 in it. When i press send i want the labels on the other screen to change to this as they do not have those values but im not sure how to create two nstrings in two nsdatas and send and then recieve the two as right now it only sends the first label but i cant get and set the second data.

        Reply
        1. Eric Post author

          Combine into one string with a delimiter (say a comma or something that makes sense), send once. On your receiveData just split at the delimiter and use the two strings. Save yourself a data send.

          Reply
  9. Steve

    Eric,

    Is it possible to connect multiple devices (ie more than two?) For example, I’m wanting to connect 3 ipods/iphones up to an iPad. The iPhones/pods will send date to specific fields on the iPad. Do you know if this is possible? If so, how do I create the connections for each of the devices? Your code works great for a simple tutorial…just not sure how to extend.

    Any help would be great!

    Thanks!

    Reply
    1. Eric Post author

      Yes – since it’s using GameKit, you can have many devices connected. The limit is 16 connected devices. I have started to abstract the whole thing and placed it on GitHub. If you’ve created connections for two I believe you would execute a join on another device and once approved it would be part of the same ring of communication. You shouldn’t need to do anything different than what’s already coded.

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *


− 2 = one

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>