Edit: As noted in the comments, this technique no longer works in iPhone OS 3.1.
If you are writing an iPhone GameKit app without using GKPeerPickerController (as I did in PhotoBeamer), you need to detect when Bluetooth is disabled and ask the user to turn it on in the settings app. Apple doesn’t provide a way for a developer to enable Bluetooth other than through GKPeerPickerController.
This is pretty easy to do. First, create your GKSession and set it to be available:
session = [[GKSession alloc] initWithSessionID:kMyAppSessionID displayName:nil sessionMode:GKSessionModeClient]; session.delegate = self; [session setDataReceiveHandler:self withContext:nil]; session.available = YES;
Next, set up your - (void)session:(GKSession *)session didFailWithError:(NSError *)error delegate method to detect when Bluetooth is not available and alert the user:
// GKSessionErrorDomain causes link error (rdar://problem/7014349) #if 0 #define kGKSessionErrorDomain GKSessionErrorDomain #else #define kGKSessionErrorDomain @"com.apple.gamekit.GKSessionErrorDomain" #endif - (void)session:(GKSession *)session didFailWithError:(NSError *)error { if ([[error domain] isEqual:kGKSessionErrorDomain] && ([error code] == GKSessionCannotEnableError)) { // Bluetooth disabled, prompt the user to turn it on } else { // Some other error, get the description from the NSError object } // destroy the GKSession and clean up }
The GKSessionErrorDomain symbol causes a link error for me, so I’m temporarily using the constant string instead. When Apple fixes the SDK, I’ll change that #if 0 to use the official symbolic name.
Note that this error will sometimes occur on a reconnection attempt even when Bluetooth is enabled, presumably because the old session is still partially active.
It would be nice to have a more user-friendly way to turn on Bluetooth without leaving the app and without using the full GKPeerPickerController UI. I’ve filed a bug report (rdar://problem/7061502) asking for this functionality. You should file one too.
#1 by John on August 26th, 2009
| Quote
First, I wanted to say thank you for this great post!
I have question about GameKit framework.
Is there a way to disable or turn off the bluetooth with GameKit or any other available framework?
I would appreciate it if you have any info on this.
Thanks again,
John
#2 by Frank on August 27th, 2009
| Quote
Thanks John, glad you found it useful.
The only way to turn on Bluetooth from an app is through GKPeerPickerController, which will prompt the user if it sees Bluetooth is off. There is no way to get at this behavior alone, you have to use the whole Apple-provided GKPeerPickerController UI.
There is no way to turn Bluetooth off from an app.
#3 by Cliff on September 14th, 2009
| Quote
Thanks, John. Unfortunately, this technique seems to no longer work in iPhone OS 3.1 as didFailWithError seems to never get called anymore for this situation.
#4 by Marcus on September 16th, 2009
| Quote
I have the same Problem as Cliff.
Any idea why?
#5 by Frank on September 16th, 2009
| Quote
Thanks for the update. I don’t know offhand how to make this work in 3.1. I’ll be looking into it over the weekend and will update when I know more.
#6 by Cliff on September 16th, 2009
| Quote
Guys, I have submitted a Radar report (7228802) to Apple about this. My wish would be that we would not have to worry about whether Bluetooth was on. Instead, we could simply start a GKSession, and Apple would ask users if they want to allow a Bluetooth connection– similar to how they handle Location Manager requests.
#7 by Hannes on September 19th, 2009
| Quote
Indeed, doesn’t seem to work in 3.1. Hope we can find a workaround.
#8 by Matthew on November 10th, 2009
| Quote
I think the reason you don’t get the error on 3.1 is because gamekit now works over WiFi. Thus it is not an “error” if bluetooth is turned off.
#9 by Jesse on November 17th, 2009
| Quote
Yeah, even if both Bluetooth and WiFi are off, and the device has Airplane mode enabled, we still don’t get an error. I did notice that with WiFi off and Bluetooth enabled that in Apple’s Reachability example wrapper that it detects an adhoc link local route, but only once you’ve actually created the GKSession and have connected to another device.