您好,登錄后才能下訂單哦!
基于藍牙對等網(wǎng)絡(luò)通信就是使用Game Kit中的GKSession、GKSessionDelegate、 GKPeerPickerController和GKPeerPickerControllerDelegate來實現(xiàn)。開發(fā)過程分為3個步驟:連接、發(fā) 送數(shù)據(jù)和接收數(shù)據(jù)。
下面我們通過一個實例介紹一下基于藍牙對等網(wǎng)絡(luò)通信過程。用戶點擊“連接”按鈕,建立連接過程中會出現(xiàn)連接對話框,根據(jù)具體情況也會彈出其它的對話 框。這些都是針對藍牙對等網(wǎng)絡(luò)標準對話框,而Wifi對等網(wǎng)絡(luò)沒有標準對話框可以使用,需要開發(fā)者自己實現(xiàn)。當兩個設(shè)備連接好之后,兩個玩家就可以連續(xù)輕 點“點擊”按鈕,點擊的次數(shù)會傳遞給對方,倒計時時間是30秒。
1、連接
由于對等網(wǎng)絡(luò)連接過程有點復(fù)雜,貫穿了這些協(xié)議和類,我們繪制了連接過程的流程圖。
下面我們通過代碼直接介紹連接流程,其中ViewController.h代碼如下:
- #import <UIKit/UIKit.h>
- #import <GameKit/GameKit.h>
- #define GAMING 0 //游戲進行中
- #define GAMED 1 //游戲結(jié)束
- @interface ViewController : UIViewController <GKSessionDelegate, GKPeerPickerControllerDelegate>
- {
- NSTimer *timer;
- }
- @property (weak, nonatomic) IBOutlet UILabel *lblTimer;
- @property (weak, nonatomic) IBOutlet UILabel *lblPlayer2;
- @property (weak, nonatomic) IBOutlet UILabel *lblPlayer1;
- @property (weak, nonatomic) IBOutlet UIButton *btnConnect;
- @property (weak, nonatomic) IBOutlet UIButton *btnClick;
- @property (nonatomic, strong) GKPeerPickerController *picker;
- @property (nonatomic, strong) GKSession *session;
- - (IBAction)onClick:(id)sender;
- - (IBAction)connect:(id)sender;
- //清除UI畫面上的數(shù)據(jù)
- -(void) clearUI;
- //更新計時器
- -(void) updateTimer;
- @end
使用Game Kit需要引入頭文件<GameKit/GameKit.h>,之前需要把GameKit.framework框架添加 到工程中。而且定義類的時候需要實現(xiàn)協(xié)議GKSessionDelegate和GKPeerPickerControllerDelegate,并且定義 GKPeerPickerController類型的屬性picker,定義GKSession類型的屬性session。
ViewController.m中創(chuàng)建GKPeerPickerController對象的代碼如下:
- - (IBAction)connect:(id)sender {
- _picker = [[GKPeerPickerController alloc] init];
- _picker.delegate = self; ①
- _picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby; ②
- [_picker show];
- }
用戶點擊的連接按鈕時,觸發(fā)connect:方法。在該方法中創(chuàng)建GKPeerPickerController對象。創(chuàng)建完成不要忘記設(shè)置 GKPeerPickerController委托為self,第②行代碼所示。在第③行代碼中connectionTypesMask屬性是設(shè)置對等網(wǎng) 絡(luò)連接類型,其中有兩種類型選擇:GKPeerPickerConnectionTypeNearby和 GKPeerPickerConnectionTypeOnline,GKPeerPickerConnectionTypeNearby用于藍牙通訊也 是默認的通訊方法,GKPeerPickerConnectionTypeOnline用于Wifi通訊的局域網(wǎng)通訊,這種方式麻煩,需要開發(fā)人員自己設(shè) 計UI畫面,自己使用Bonjour服務(wù)發(fā)現(xiàn)管理連接,以及自己編寫輸入輸出流實現(xiàn)通訊。如果給用戶一個選擇對話框,代碼可以如下編寫:
_picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby | GKPeerPickerConnectionTypeOnline;
其中“在線”就是GKPeerPickerConnectionTypeOnline類型,“附近”就是GKPeerPickerConnectionTypeNearby類型。
連接成功之后回調(diào)ViewController.m中的回調(diào)委托方法peerPickerController:didConnectPeer:toSession:代碼:
- - (void)peerPickerController:(GKPeerPickerController *)pk didConnectPeer:(NSString *)peerID
- toSession:(GKSession *) session
- {
- NSLog(@”建立連接”);
- _session = session; ①
- _session.delegate = self; ②
- [_session setDataReceiveHandler:self withContext:nil]; ③
- _picker.delegate = nil;
- [_picker dismiss]; ④
- [_btnClick setEnabled:YES];
- [_btnConnect setTitle:@"斷開連接" forState:UIControlStateNormal];
- //開始計時
- timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self
- selector:@selector(updateTimer)
- userInfo:nil repeats:YES]; ⑤
- }
上述代碼第①行_session = session將委托方法中返回的會話參數(shù)賦值給成員變量,這樣我們就獲得了一個會話對象。這種方式中,會話 ID是應(yīng)用程序的包ID,如果想自己分配會話ID,可以實現(xiàn)下面委托方法,在方法中使用GKSession的構(gòu)造方法 initWithSessionID:displayName: sessionMode:,自己創(chuàng)建會話對象。
- - (GKSession *)peerPickerController:(GKPeerPickerController *)picker
- sessionForConnectionType:(GKPeerPickerConnectionType)type {
- GKSession *session = [[GKSession alloc] initWithSessionID: <自定義SessionID>
- displayName:<顯示的名字> sessionMode:GKSessionModePeer];
- return session;
- }
有的時候會話的狀態(tài)會發(fā)生變化,我們要根據(jù)狀態(tài)的變化做一些UI的清理和資源的釋放。監(jiān)測狀態(tài)變化在委托方法session:peer:didChangeState:中實現(xiàn),方法代碼如下:
- - (void)session:(GKSession *)session peer:(NSString *)peerID
- didChangeState:(GKPeerConnectionState)state
- {
- if (state == GKPeerStateConnected)
- {
- NSLog(@”connected”);
- [_btnConnect setTitle:@"斷開連接" forState:UIControlStateNormal];
- [_btnClick setEnabled:YES];
- } else if (state == GKPeerStateDisconnected)
- {
- NSLog(@”disconnected”);
- [self clearUI];
- }
- }
其中GKPeerStateConnected常量是已經(jīng)連接狀態(tài),GKPeerStateDisconnected常量是斷開連接狀態(tài)。
2、發(fā)送數(shù)據(jù)
發(fā)送數(shù)據(jù)的代碼如下:
- - (IBAction)onClick:(id)sender {
- int count = [_lblPlayer1.text intValue];
- _lblPlayer1.text = [NSString stringWithFormat:@"%i",++count];
- NSString *sendStr = [NSString
- stringWithFormat:@"{\"code\":%i,\"count\":%i}",GAMING,count]; ①
- NSData* data = [sendStr dataUsingEncoding: NSUTF8StringEncoding];
- if (_session) {
- [_session sendDataToAllPeers:data
- withDataMode:GKSendDataReliable error:nil]; ②
- }
- }
3、接收數(shù)據(jù)
為了接收數(shù)據(jù)首先需要在設(shè)置會話時候通過[_session setDataReceiveHandler:self withContext:nil]語句設(shè)置接收數(shù)據(jù)的處理程序是self。這樣當數(shù)據(jù)到達時候就會觸發(fā)下面的方法特定:
- - (void) receiveData:(NSData *)data fromPeer:(NSString *)peer
- inSession:(GKSession *)session context:(void *)context
- {
- id jsonObj = [NSJSONSerialization JSONObjectWithData:data
- options:NSJSONReadingMutableContainers error:nil];
- NSNumber *codeObj = [jsonObj objectForKey:@"code"];
- if ([codeObj intValue]== GAMING) {
- NSNumber * countObj= [jsonObj objectForKey:@"count"];
- _lblPlayer2.text = [NSString stringWithFormat:@"%@",countObj];
- } else if ([codeObj intValue]== GAMED) {
- [self clearUI];
- }
- }
上面的代碼是接收到數(shù)據(jù)之后,進行JSON解碼,取出游戲狀態(tài)和點擊次數(shù)。
主要的程序代碼就是這些,根據(jù)具體的業(yè)務(wù)情況還可以能有所變化,讀者可以下載完整代碼在兩臺之間設(shè)備或是一個設(shè)備一個模擬器之間進行測試。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。