views:

6662

answers:

2

So, I was wondering if you NEED to use the Peer Picker to find peers in the new iPhone SDK 3.0. I don't really want to use it but I do want to use the peer-to-peer bluetooth connection. Is there any sample code that demonstrates the bluetooth connection without using Peer Picker? The game GKTank that Apple provides utilizes the Peer Picker, so I can't use that.

A: 

Why do you not want to use it?

I don't know there's a way to directly do a bluetooth connection yourself, and it presents an alternative for finding connections by other means. It provides a pretty nice system to set up a network between a number of iPod/Touches, and lets you define if the relation is truly peer or master / slave...

Kendall Helmstetter Gelner
Well, I am designing a mobile ad-hoc bluetooth network in which I will conduct distributed computing task with data mining techniques. I don't want the user(me) to be worried with selected a peer to connect to. I plan on setting it up so that all the iPod Touch just scans all available iPhones/iPod Touch devices and then offloads task to each one. When it comes to a peer, if the peer is "busy" already doing a task, then it should automatically move on to the next peer.
Josh Bradley
In that case build the clients to auto-accept invitations and treat the whole thing as a master-slave relationship.Everyone has to be running the app for this to work, bluetooth or WiFi (although actually you could base it around notificatons possibly, though there's no way to auto-accept a launch of your app from a notification if it's not already running).
Kendall Helmstetter Gelner
Yeah, that was the idea...to auto-accept connections, which will be my next step after I first establish a connection between two iPod touches. I'll have a total of eight to work with once everything is up and running.
Josh Bradley
+6  A: 

There are two ways to do this.

The first way uses GameKit API. You start by having two separate classes, one that implements the GKSessionDelegate protocol and acts as a GameKit/Bluetooth "handler" and the other as the presentation UI (most likely some sort of viewcontroller with a tableview). The way you would wire it up is the handler manages the GameKit notifications etc and then calls delegate methods on the UI to update the table view when a peer connects/drops off, etc. That way, as devices come and go, your picker list should update to show who's around.

Below is some code to get you started:

- (BOOL) startPeer
{
    BOOL result = NO;

    if (!_session) {
     _session = [[GKSession alloc] initWithSessionID:BLUETOOTHSESSION 
               displayName:nil 
               sessionMode:GKSessionModePeer];
     _session.delegate = self;
     [_session setDataReceiveHandler:self withContext:nil];
     _session.available = YES;
 result = YES;
    }
    return result;
}

- (void) stopPeer
{
    // Set up the session for the next connection
    //
    [_session disconnectFromAllPeers];
    _session.available = YES;

    [self cleanupProgressWindow];
}

- (void) loadPeerList 
{
    self.peerList = [[NSMutableArray alloc] initWithArray:[_session peersWithConnectionState:GKPeerStateAvailable]];
}


- (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state
{
    BOOL peerChanged = NO;

    switch(state) {

     // When peer list changes, we adjust the available list
     //
     case GKPeerStateAvailable:
      if (_peerList) {
       [_peerList addObject:peerID];
       peerChanged = YES;
      }
      break;

     // When peer list changes, we adjust the available list
     //
     case GKPeerStateUnavailable:
      if (_peerList) {
       [_peerList removeObject:peerID];
       peerChanged = YES;
      }
      break;


     // Called when the peer has connected to us.
     //
     case GKPeerStateConnected:
                    // start reading and writing
      break;

        case GKPeerStateDisconnected:
     {
      if (_isWriter) {
       _isConnected = NO;
       _deviceToSend = nil;
       [self cleanupProgressWindow];
      } else {
       // Other side dropped, clean up local data and reset for next connection
       self.dataRead = nil;
      }
     }
      break;
    }

    // Notify peer list delegate that the list has changed so they can update the UI
    //
    if (peerChanged)
     CALLDELEGATE(_peerListDelegate, peerListChanged);   
}

The second way to do it is to use standard Bonjour service selection mechanisms. GameKit is implemented on top of Bonjour (but over Bluetooth instead of WiFi) so once the two sides have gone through network reachability with each other and connected they are registered under Bonjour and act like any Bonjour service would. The GameKit way is probably a little easier, but if you already have code for WiFi it can be reused for Bluetooth as well.

Ramin
Hey, thanks so much for this template to build off of. One more question, I can see how the session:peer:didChangeState method would go in the delegate.h/.m file, but what about the other methods? Would the startPeer and stopPeer go in my viewcontroller.h/.m files or will the whole template go in the delegate file?
Josh Bradley
In this case, these are all assumed to be in the delegate handler since they deal with the underlying GameKit plumbing. There's no reason you can't put it all inside the viewcontroller but it's a good idea to keep UI code decoupled from networking code. After updating the array of peers, the 'handler' object invokes its own custom delegate method "peerListChanged" which notifies the viewcontroller that the list has changed so it can call for a table reload and show the new list to the user.
Ramin
Does this only work over Wifi or will it also find peers over bluetooth? Do you have to use the peer picker to use bluetooth?
Typeoneerror