蓝牙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中提供了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框架,可以在游戏中增加对等连接,又称对端连接或点对点连接,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方法恢复数据
//显示可以连接的蓝牙设备列表
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;
只能用于iOS设备之间的连接
只能用于同一个应用程序之间的连接
最好别利用蓝牙发送比较大的数据
#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
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/wangzi11322/article/details/49420497