iOS开发 -GameKit蓝牙开发
2015-10-26 09:47
381 查看
蓝牙4.0
蓝牙4.0是2012年最新蓝牙版本,是3.0的升级版本;较3.0版本更省电、成本低、3毫秒低延迟、超长有效连接距离、AES-128加密等;通常用在蓝牙耳机、蓝牙音箱等设备上。 蓝牙技术联盟(Bluetooth SIG)2010年7月7日宣布,正式采纳蓝牙4.0核心规范(Bluetooth Core Specification Version 4.0 ),并启动对应的认证计划。会员厂商可以提交其产品进行测试,通过后将获得蓝牙4.0标准认证。 该技术拥有极低的运行和待机功耗,使用一粒纽扣电池甚至可连续工作数年之久。
iOS中蓝牙的实现方案
iOS中提供了4个框架用于实现蓝牙连接GameKit.framework(用法简单)
只能用于iOS设备之间的连接,多用于游戏(比如五子棋对战),从iOS7开始过期
MultipeerConnectivity.framework
只能用于iOS设备之间的连接,从iOS7开始引入,主要用于文件共享(仅限于沙盒的文件)
ExternalAccessory.framework
可用于第三方蓝牙设备交互,但是蓝牙设备必须经过苹果MFi认证(国内较少)
CoreBluetooth.framework(时下热门)
可用于第三方蓝牙设备交互,必须要支持蓝牙4.0
硬件至少是4s,系统至少是iOS6
蓝牙4.0以低功耗著称,一般也叫BLE(Bluetooth Low Energy)
目前应用比较多的案例:运动手坏、嵌入式设备、智能家居
GameKit框架简介
使用GameKit框架,可以在游戏中增加对等连接,又称对端连接或点对点连接,Peer To Peer。使用GameKit框架中的对等网络连接API,可以在游戏玩家之间建立一个对等网络,并在游戏/应用实例之间交换数据。
GameKit框架可以使用蓝牙在玩家之间创建网络,玩家甚至不需要连接到互联网,就可以彼此对战。
通过蓝牙实现对等网络连接
为玩家双方呈现一个GKPeerPickerController,提供了一个标准的用户界面连接两台设备ViewControoler遵循GKPeerPickerControllerDelegate协议,处理来自GKPeerPickerController(对端选择器)的信息
建立连接后,使用GKSession类可以向对端设备发送数据
在receiveData:fromPeer:inSession:context代理方法中编写代码来处理接收到的数据
//发送数据方法 [_peerSession sendDataToAllPeers:data withDataMode:GKSendDataReliable error:&error]; //接收数据方法 - (void)receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context;
如果要通过网络发送自定义对象,需要使用NSKeyedArchiver方法归档自定义对象,然后再发送归档后的NSData
自定义对象需要遵从NSCoding协议,并实现相应的归档和恢复方法
接收端接收到数据之后,使用NSKeyedUnarchiver方法恢复数据
GameKit的蓝牙开发步骤
//显示可以连接的蓝牙设备列表 GKPeerPickerController *ppc = [[GKPeerPickerController alloc] init]; ppc.delegate = self; [ppc show]; //在代理方法中监控蓝牙的连接 - (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session { NSLog(@"连接到设备:%@", peerID); // 关闭蓝牙设备显示界面 [picker dismiss]; // 设置接收到蓝牙数据后的监听器 [session setDataReceiveHandler:self withContext:nil]; // 保存session self.session = session; }
//处理接收到的蓝牙数据 - (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context { } 利用GKSession给其他设备发送数据 //给指定的连接设备发送数据 - (BOOL)sendData:(NSData *) data toPeers:(NSArray *)peers withDataMode:(GKSendDataMode)mode error:(NSError **)error; //给所有连接的设备发送数据 - (BOOL)sendDataToAllPeers:(NSData *) data withDataMode:(GKSendDataMode)mode error:(NSError **)error;
GameKit的蓝牙开发注意
只能用于iOS设备之间的连接只能用于同一个应用程序之间的连接
最好别利用蓝牙发送比较大的数据
GameKit蓝牙开发实例
#import "ViewController.h" #include <GameKit/GameKit.h> @interface ViewController ()<UINavigationControllerDelegate, UIImagePickerControllerDelegate, GKPeerPickerControllerDelegate> /** * 连接 */ - (IBAction)connect; /** * 选择图片 */ - (IBAction)selectedPhoto; /** * 发送 */ - (IBAction)send; @property (weak, nonatomic) IBOutlet UIImageView *customIV; /** * 会话 */ @property (nonatomic, strong) GKSession *session; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (IBAction)connect { // 1.创建选择其他蓝牙设备的控制器 GKPeerPickerController *peerPk = [[GKPeerPickerController alloc] init]; // 2.成为该控制器的代理 peerPk.delegate = self; // 3.显示蓝牙控制器 [peerPk show]; } #pragma mark - GKPeerPickerControllerDelegate // 4.实现dialing方法 /** * 当蓝牙设备连接成功就会调用 * * @param picker 触发时间的控制器 * @param peerID 连接蓝牙设备的ID * @param session 连接蓝牙的会话(可用通讯), 以后只要拿到session就可以传输数据 */ - (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session { NSLog(@"%@", peerID); // 1.保存会话 self.session = session; // 2.设置监听接收传递过来的数据 /* Handler: 谁来处理接收到得数据 withContext: 传递数据 */ [self.session setDataReceiveHandler:self withContext:nil]; // 2.关闭显示蓝牙设备控制器 [picker dismiss]; } /** * 接收到其它设备传递过来的数据就会调用 * * @param data 传递过来的数据 * @param peer 传递数据设备的ID * @param session 会话 * @param context 注册监听时传递的数据 */ - (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context { // NSLog(@"%s", __func__); // 1.将传递过来的数据转换为图片(注意: 因为发送的时图片, 所以才需要转换为图片) UIImage *image = [UIImage imageWithData:data]; self.customIV.image = image; } - (void)peerPickerControllerDidCancel:(GKPeerPickerController *)picker { } - (IBAction)send { // 利用session发送图片数据即可 // 1.取出customImageView上得图片, 转换为二进制 UIImage *image = self.customIV.image; NSData *data = UIImagePNGRepresentation(image); /* GKSendDataReliable, 数据安全的发送模式, 慢 GKSendDataUnreliable, 数据不安全的发送模式, 快 */ /* data: 需要发送的数据 DataReliable: 是否安全的发送数据(发送数据的模式) error: 是否监听发送错误 */ [self.session sendDataToAllPeers:data withDataMode:GKSendDataReliable error:nil]; } - (IBAction)selectedPhoto { // 1.创建图片选择控制器 UIImagePickerController *imagePk = [[UIImagePickerController alloc] init]; // 2.判断图库是否可用打开 if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum]) { // 3.设置打开图库的类型 imagePk.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; imagePk.delegate = self; // 4.打开图片选择控制器 [self presentViewController:imagePk animated:YES completion:nil]; } } #pragma mark - UIImagePickerControllerDelegate - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { // NSLog(@"%@", info); self.customIV.image = info[UIImagePickerControllerOriginalImage]; [picker dismissViewControllerAnimated:YES completion:nil]; } @end