注意:如果要測試本文所介紹的内容,需要兩部iPhone(3G或3GS),或使用iPhone OS 3.0或更高版本的iPod裝置(二代或更新版本)。
建立一個項目
使用Xcode,建立一個新的基于視圖的應用程式項目,取名為Bluetooth。通路藍牙的各種API位于GameKit架構中,是以,你需要将這個架構添加到剛剛建立的項目中,在Xcode的架構組上點右鍵,選擇“添加”*“現有架構”,選擇GameKit架構,如圖1所示。

圖 1 添加GameKit架構
在BluetoothViewController.h檔案中,聲明下面的對象,outlet和行為:
1 #import
2
3 #import
4
5 @interface BluetoothViewController : UIViewController {
6
7 GKSession *currentSession;
8
9 IBOutlet UITextField *txtMessage;
10
11 IBOutlet UIButton *connect;
12
13 IBOutlet UIButton *disconnect;
14
15 }
16
17 @property (nonatomic, retain) GKSession *currentSession;
18
19 @property (nonatomic, retain) UITextField *txtMessage;
20
21 @property (nonatomic, retain) UIButton *connect;
22
23 @property (nonatomic, retain) UIButton *disconnect;
24
25 -(IBAction) btnSend:(id) sender;
26
27 -(IBAction) btnConnect:(id) sender;
28
29 -(IBAction) btnDisconnect:(id) sender;
30
31 @end
32
33
GKSession對象用于表現兩個藍牙裝置之間連接配接的一個會話,你也可以使用它在兩個裝置之間發送和接收資料。
在BluetoothViewController.m檔案中,添加下面的代碼:
1 #import "BluetoothViewController.h"
5 @implementation BluetoothViewController
7 @synthesize currentSession;
9 @synthesize txtMessage;
11 @synthesize connect;
13 @synthesize disconnect;
15
輕按兩下BluetoothViewController.xib在Interface Builder中編輯它,在視圖視窗中添加以下視圖,如圖2所示。
文本區域(Text Field)
圓形按鈕(Round Rect Button)
圖 2在視圖視窗中填充文本區域和圓形按鈕視圖
執行以下行為:
按住CTRL鍵,在檔案所有者項目上點選,将其拖放到文本區域視圖上,選擇txtMessage;
按住CTRL鍵,在檔案所有者項目上點選,将其拖放到連接配接按鈕上,選擇connect;
按住CTRL鍵,在檔案所有者項目上點選,将其拖放到斷開連接配接按鈕上,選擇disconnect;
按住CTRL鍵,在發送按鈕上點選,将其拖放到檔案所有者項目上,選擇btnSend;
按住CTRL鍵,在連接配接按鈕上點選,将其拖放到檔案所有者項目上,選擇btnConnect;
按住CTRL鍵,在斷開連接配接按鈕上點選,将其拖放到檔案所有者項目上,選擇btnDisconnect;
在檔案所有者項目上點選右鍵,驗證所有連接配接是否正常,如圖3所示。
圖 3 驗證所有連接配接是否正常
傳回Xcode,在BluetoothViewController.m檔案中,添加以下代碼:
1 - (void)viewDidLoad {
3 [connect setHidden:NO];
5 [disconnect setHidden:YES];
7 [super viewDidLoad];
9 }
11 - (void)dealloc {
13 [txtMessage release];
15 [currentSession release];
17 [super dealloc];
19 }
21
搜尋對等裝置
現在所有準備工作已經就緒,接下來介紹一下通路其它藍牙裝置的API。
在BluetoothViewController.h檔案中,聲明一個GKPeerPickerController對象:
15 GKPeerPickerController *picker;
17
GKPeerPickerController類提供了一個标準的UI讓你的應用程式發現并連接配接到其它藍牙裝置,連接配接方法并不難,首先實作一個btnConnect:類:
1 -(IBAction) btnConnect:(id) sender {
3 picker = [[GKPeerPickerController alloc] init];
5 picker.delegate = self;
7 picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby;
9 [connect setHidden:YES];
11 [disconnect setHidden:NO];
13 [picker show];
connectionTypesMask屬性指出使用者可以選擇的連接配接類型,包括兩種類型:GKPeerPickerConnectionTypeNearby和GKPeerPickerConnectionTypeOnline。對于藍牙通信,使用GKPeerPickerConnectionTypeNearby常量,GKPeerPickerConnectionTypeOnline常量表示基于網際網路的連接配接。
檢測到遠端藍牙裝置,使用者選擇并連接配接到其中一個藍牙裝置時,調用peerPickerController:didConnectPeer:toSession:方法,這個方法的實作如下:
1 - (void)peerPickerController:(GKPeerPickerController *)picker
3 didConnectPeer:(NSString *)peerID
5 toSession:(GKSession *) session {
7 self.currentSession = session;
9 session.delegate = self;
11 [session setDataReceiveHandler:self withContext:nil];
13 picker.delegate = nil;
15 [picker dismiss];
17 [picker autorelease];
當使用者已經連接配接到對等藍牙裝置後,可以将GKSession對象儲存到currentSession屬性中,這樣你可以使用GKSession對象與遠端裝置通信。
如果使用者取消了藍牙選擇器,調用peerPickerControllerDidCancel:方法,其定義如下:
1 - (void)peerPickerControllerDidCancel:(GKPeerPickerController *)picker
3 {
5 picker.delegate = nil;
7 [picker autorelease];
9 [connect setHidden:NO];
11 [disconnect setHidden:YES];
13 }
如果要從一個裝置斷開連接配接,使用來自GKSession對象的disconnectFromAllPeers方法,btnDisconnect:方法的實作如下:
1 -(IBAction) btnDisconnect:(id) sender {
3 [self.currentSession disconnectFromAllPeers];
5 [self.currentSession release];
7 currentSession = nil;
連接配接裝置或斷開連接配接時,調用session:peer:didChangeState:方法,其實作如下:
1 - (void)session:(GKSession *)session
3 peer:(NSString *)peerID
5 didChangeState:(GKPeerConnectionState)state {
7 switch (state)
9 {
11 case GKPeerStateConnected:
13 NSLog(@"connected");
15 break;
17 case GKPeerStateDisconnected:
19 NSLog(@"disconnected");
21 [self.currentSession release];
23 currentSession = nil;
25 [connect setHidden:NO];
27 [disconnect setHidden:YES];
29 break;
31 }
33 }
34
35
處理這個事件你将知道連接配接是什麼時候建立的,或斷開是什麼時候發生的。例如,當建立一個連接配接時,你可能想要立即向對方發送資料。
發送資料
為了向連接配接的藍牙裝置發送資料,需要使用到GKSession對象的sendDataToAllPeers:方法,你發送的資料是通過NSData對象傳輸的,是以你可以自定義你的應用程式協定和發送的資料類型(如二進制資料),mySendDataToPeers:方法的定義如下:
1 - (void) mySendDataToPeers:(NSData *) data
5 if (currentSession)
7 [self.currentSession sendDataToAllPeers:data
9 withDataMode:GKSendDataReliable
11 error:nil];
15 再定義btnSend:方法,以便使用者輸入的資料能夠發送到遠端裝置:
17 -(IBAction) btnSend:(id) sender
19 {
21 //---convert an NSString object to NSData---
23 NSData* data;
25 NSString *str = [NSString stringWithString:txtMessage.text];
27 data = [str dataUsingEncoding: NSASCIIStringEncoding];
29 [self mySendDataToPeers:data];
接收資料
當裝置接收到資料時,調用receiveData:fromPeer:inSession:context:方法,其實作如下:
1 - (void) receiveData:(NSData *)data
3 fromPeer:(NSString *)peer
5 inSession:(GKSession *)session
7 context:(void *)context {
9 //---convert the NSData to NSString---
11 NSString* str;
13 str = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
15 UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Data received"
17 message:str
19 delegate:self
21 cancelButtonTitle:@"OK"
23 otherButtonTitles:nil];
25 [alert show];
27 [alert release];
29 }
31
這裡接收到的資料是NSData格式,為了使用UIAlertView類顯示它,你需要将其轉換為NSString對象。
測試應用程式
就是這麼簡單!現在可以開始測試了,在Xcode中按下Command-R,将程式部署到iPhone/iPod上,本文假設你有兩部iPhone或兩部iPod,為了運作剛剛建立的程式,這兩台裝置上都需要運作iPhone OS 3.0。
部署好程式後,在兩台裝置上啟動好程式,在任一裝置上點選連接配接按鈕,GKPeerPickerController将會顯示标準的UI發現其它裝置,如圖4所示。
圖 4 GKPeerPickerController查找其它裝置
等待一會兒後,兩邊的程式應該都能夠發現對方,如圖5所示,當你在發現的裝置名稱上輕輕點選,程式就會開始連接配接。
圖 5 顯示發現的裝置名稱
注意:如果你在iPhone模拟器上測試這個程式,應該會檢測到兩個裝置,但卻無法連接配接到任何裝置。
當其它裝置試圖連接配接到你的裝置時,你将會看到如圖6所示的彈出提示,點選“接受”允許其連接配接,點選“拒絕”拒絕其連接配接。
圖 6 其它裝置試圖連接配接到你時的提示
如果成功與你建立了連接配接,你就可以輸入一些文本資訊發給對方了,從其它裝置接收到資料将會以一個警告視圖顯示,如圖7所示。
圖 7 接收到其它裝置發來的資料
小結
通過本文的介紹,你會發現使用藍牙連接配接兩台iPhone/iPod是多麼的簡單,使用本文所介紹的内容,你可以輕松建構一個網絡遊戲或其它有趣的應用。在下一篇文章中,我将會介紹如何使用藍牙連接配接傳輸語音資料,請密切關注。