GameKit的蓝牙开发注意

● 只能用于iOS设备之间的连接
● 只能用于同一个应用程序之间的连接
● 最好别利用蓝牙发送比较大的数据

/*
 关于蓝牙的数据传输
 
 1. 一次性传送,没有中间方法,所谓中间方法值得是,传输进度比例
 对于用户而言,选择了传输,就需要等待传输完成,或者传输以失败告终
 这就意味着,在实际开发过程中,最好不要用蓝牙传输太大的文件
 
 在实际应用中,蓝牙通常用于传递游戏数据模型,用于联机对战,譬如点对点的棋牌类游戏。
 */

 
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的蓝牙开发步骤

● 显示可以连接的蓝牙设备列表
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;

实例1:

#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

实例2:

/*
> 讲解相片选择器
*先不设置代理,创建后直接运行
*从选择相片后需要关闭控制器引出代理
*实现代理方法展示数据
*PPT讲解蓝牙连接(不是所有应用都可以用蓝牙传输东西,必须相同应用事先写好如何处理. 苹果蓝牙传输非常满, 而且传输过程中没有进度)
*在storyboard中添加按钮, 点击按钮后创建对端选择控制器, 设置代理,显示视图控制器
*在代理方法中打印peerID, 讲解session用途查看头文件引出利用传递数据
*定义属性保存session , 在storyboard中添加按钮监听按钮点击利用session传递图片
*讲解传递数据方法两种模式区别
*设置数据处理者, 讲解如何找到数据处理方法,在数据处理方法中打印LOG运行验证
*将接收到的数据转换为图片后现实在界面上
*总结蓝牙传输
*/ #import "CZViewController.h"
#import <GameKit/GameKit.h> @interface CZViewController ()<UIImagePickerControllerDelegate, UINavigationControllerDelegate, GKPeerPickerControllerDelegate> /**
* 现实相片
*/
- (IBAction)selectPhoto; @property (weak, nonatomic) IBOutlet UIImageView *imageView; /**
* 蓝牙连接
*/
- (IBAction)connectBtnClick; /**
* 会话对象
*/
@property (nonatomic, strong)GKSession *session; /**
* 发送相片
*/
- (IBAction)sendPhoto; @end @implementation CZViewController #pragma mark 选择照片
/*
照片源类型 UIImagePickerControllerSourceTypeCamera 照相机
UIImagePickerControllerSourceTypePhotoLibrary 照片库(通过同步存放的,用户不能删除)
UIImagePickerControllerSourceTypeSavedPhotosAlbum 保存的照片(通过拍照或者截屏保存的,用户可以删除)
*/
- (IBAction)selectPhoto
{ // 1.判断照片源是否可用
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
// 1.1实例化控制器
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
// 1.2设置照片源
[picker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
// 1.3设置允许修改
picker.allowsEditing = YES;
// 1.4设置代理
picker.delegate = self;
// 1.5显示控制器
[self presentViewController:picker animated:YES completion:^{ }];
}else
{
// 2.照片源不可用
NSLog(@"照片源不可用");
}
} #pragma mark - imagePicker代理方法
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// NSLog(@"%@", info);
// 获取相片
UIImage *image = info[@"UIImagePickerControllerEditedImage"];
// 设置相片
self.imageView.image = image; // 关闭相片选择器
[self dismissViewControllerAnimated:YES completion:^{ }]; } #pragma mark - 蓝牙连接
- (IBAction)connectBtnClick
{
// 1.创建对端选择控制器
GKPeerPickerController *picker = [[GKPeerPickerController alloc] init]; // 2.设置代理
picker.delegate = self; // 3.显示试图控制器
[picker show]; } #pragma mark - GKPeerPickerControllerDelegate
// 完成对端连接
// GKSession对象用于表现两个蓝牙设备之间连接的一个会话,你也可以使用它在两个设备之间发送和接收数据。
- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session
{
NSLog(@"连接成功 %@", peerID);
// 保存会话
self.session = session; // 设置数据处理对象,类似于delegate
[self.session setDataReceiveHandler:self withContext:nil]; // 关闭对端选择控制器
[picker dismiss];
} // 取消对端选择控制器
- (void)peerPickerControllerDidCancel:(GKPeerPickerController *)picker
{
NSLog(@"取消蓝牙选择器");
} // 发送相片
- (IBAction)sendPhoto { NSData *imageData = UIImagePNGRepresentation(self.imageView.image); // 利用session发送相片
// self.session sendData:<#(NSData *)#> toPeers:<#(NSArray *)#> withDataMode:<#(GKSendDataMode)#> error:<#(NSError *__autoreleasing *)#>
/*
TCP协议、UDP协议 1. 要发送的数据(二进制的)
2. 数据发送模式
GKSendDataReliable :确保数据发送成功(TCP协议,对网络压力大)
GKSendDataUnReliable :只管发送不管成功(UDP协议,对数据完整性要求不高,对网络压力下)
*/
[self.session sendDataToAllPeers:imageData withDataMode:GKSendDataReliable error:nil]; } // 数据接受处理方法,此方法需要从文档中粘贴出来,没有智能提示
- (void)receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context
{
NSLog(@"接收到数据");
// 将NSData转换成UIImage
UIImage *image = [UIImage imageWithData:data];
self.imageView.image = image;
} /*
关于蓝牙的数据传输 1. 一次性传送,没有中间方法,所谓中间方法值得是,传输进度比例
对于用户而言,选择了传输,就需要等待传输完成,或者传输以失败告终
这就意味着,在实际开发过程中,最好不要用蓝牙传输太大的文件 在实际应用中,蓝牙通常用于传递游戏数据模型,用于联机对战,譬如点对点的棋牌类游戏。
*/ @end
Core Bluetooth
● Core Bluetooth测试比较麻烦,正常情况下,得至少有2台真实的蓝牙4.0设备
● 如何让iOS模拟器也能测试蓝牙4.0程序?
● 买一个CSR蓝牙4. USB适配器,插在Mac上
● 在终端输入sudo nvram bluetoothHostControllerSwitchBehavior="never"
● 重启Mac
● 用Xcode .6调试代码,将程序跑在iOS .1的模拟器上 (苹果把iOS .0模拟器对BLE的支持移除掉了)
● Core Bluetooth的使用场景
● 运动手环、智能家居、嵌入式设备等等(金融刷卡器、心电测量器)
Core Bluetooth的基本常识
● 每个蓝牙4.0设备都是通过服务(Service)和特征(Characteristic)来展示自己 的
● 一个设备必然包含一个或多个服务,每个服务下面又包含若干个特征 ● 特征是与外界交互的最小单位
• 比如说,一台蓝牙4.0设备,用特征A来描述自己的出厂信息,用特征B来收发 数据
● 服务和特征都是用UUID来唯一标识的,通过UUID就能区别不同的服务和特征 ● 设备里面各个服务(service)和特征(characteristic)的功能,均由蓝牙设备硬件厂
商提供,比如哪些是用来交互(读写),哪些可获取模块信息(只读)等
Core Bluetooth的开发步骤

● 建立中心设备
● 扫描外设(Discover Peripheral)
● 连接外设(Connect Peripheral)
● 扫描外设中的服务和特征(Discover Services And Characteristics)
● 利用特征与外设做数据交互(Explore And Interact)
● 断开连接(Disconnect)
实例:
#import "ViewController.h"
#import <CoreBluetooth/CoreBluetooth.h> @interface ViewController ()<CBCentralManagerDelegate, CBPeripheralDelegate>
/**
* 外设
*/
@property (nonatomic, strong) NSMutableArray *peripherals;
/**
* 中心管理者
*/
@property (nonatomic, strong) CBCentralManager *mgr;
@end @implementation ViewController - (NSMutableArray *)peripherals
{
if (!_peripherals) {
_peripherals = [NSMutableArray array];
}
return _peripherals;
} - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. // 1.创建中心设备
CBCentralManager *mgr = [[CBCentralManager alloc] init];
self.mgr = mgr; // 设置代理
mgr.delegate = self; // 2.利用中心设备扫描外部设备
/*
如果指定数组代表只扫描指定的设备
*/
[mgr scanForPeripheralsWithServices:nil options:nil];
}
#pragma mark - CBCentralManagerDelegate
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{ // 保存扫描到得外部设备
// 判断如果数组中不包含当前扫描到得外部设置才保存
if (![self.peripherals containsObject:peripheral]) { peripheral.delegate = self;
[self.peripherals addObject:peripheral];
}
} /**
* 模拟点击, 然后连接所有的外设
*/
- (void)start
{
for (CBPeripheral *peripheral in self.peripherals) {
/**
* 连接外设
*/
[self.mgr connectPeripheral:peripheral options:nil];
}
}
/**
* 连接外设成功调用
*/
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
// 扫描外设中得服务
[peripheral discoverServices:nil];
}
/**
* 连接外设失败调用
*/
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{ } #pragma makr - CBPeripheralDelegate
/**
* 只要扫描到服务就会调用
*
* @param peripheral 服务所在的外设
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{ // 获取外设中所有扫描到得服务
NSArray *services = peripheral.services;
for (CBService *service in services) {
// 拿到需要的服务
if ([service.UUID.UUIDString isEqualToString:@""])
{
// 从需要的服务中查找需要的特征
// 从peripheral中得service中扫描特征
[peripheral discoverCharacteristics:nil forService:service];
}
}
} /**
* 只要扫描到特征就会调用
*
* @param peripheral 特征所属的外设
* @param service 特征所属的服务
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{ // 拿到服务中所有的特诊
NSArray *characteristics = service.characteristics;
// 遍历特征, 拿到需要的特征处理
for (CBCharacteristic * characteristic in characteristics) {
if ([characteristic.UUID.UUIDString isEqualToString:@""]) {
NSLog(@"设置闹钟"); }
}
}
@end
蓝牙的现状
● 绝大多数智能手机支持蓝牙 4.0(BLE)
● 蓝牙芯片发展迅速,在性能和效率方面都有很大提高,且不断变得更小更便宜
● iBeacon + 蓝牙,前景一片光明
● 应用之一:室内导航
● Estimote公司为iBeacon提供基站
● 3个iBeacon基站的预购价格为99美元(约合人民币610元)
● Estimote公司推出的iBeacon基站的最远传输距离为50m,但是他们推荐在10m 范围内的使用效果最好
● 一块纽扣电池就能为一个iBeacon基站提供长达 年的使用寿命,而且是在设 备不断对外发射信号的情况下

IOS 蓝牙(GameKit、Core Bluetooth)的更多相关文章

  1. iOS 上的蓝牙框架 - Core Bluetooth for iOS

    原文: Core Bluetooth for iOS 6 Core Bluetooth 是在iOS5首次引入的,它允许iOS设备可以使用健康,运动,安全,自动化,娱乐,附近等外设数据.在iOS 6 中 ...

  2. iOS 蓝牙(GameKit CoreBluetooth)

    利用GameKit框架实现ios设备的蓝牙通讯,导入框架:#import <GameKit/GameKit.h>  , 注意: 此框架只能用于ios设置间蓝牙通讯 如今苹果开放了接口来实现 ...

  3. Core BlueTooth官方文档翻译

    本⽂文是苹果<Core Bluetooth Programming Guide>的翻译. 关于Core Bluetooth Core Bluetooth 框架提供了蓝⽛牙低功耗⽆无线设备与 ...

  4. core Bluetooth(蓝牙4.0)

    蓝牙4.0以低功耗著称,一般也叫BLE(Bluetooth Low Energy). 目前主要应用的场景有:智能家居.运动手环和室内导航等. 利用core Bluetooth框架可以实现苹果设备与第三 ...

  5. 轻量级iOS蓝牙库:LGBluetooth(项目中用过的)

    LGBluetooth 是个简单的,基于块的,轻量级 CoreBluetooth 库: iOS 6引入了Core Bluetooth,让低功耗蓝牙设备之间的通信变得简单.但如果CoreBluetoot ...

  6. 【转】Core Bluetooth框架之一:Central与Peripheral

    原文网址:http://southpeak.github.io/blog/2014/07/29/core-bluetoothkuang-jia-zhi-%5B%3F%5D-:centralyu-per ...

  7. Core Bluetooth【官方文档翻译】【02】

    1.中心设备和外围设备以及它们在蓝牙通讯中的角色. 在所有的BLE( Bluetooth low energy,下文简称蓝牙4.0 )通讯中都涉及2个主要的角色:中心设备和外围设备.它是基于传统的客户 ...

  8. Core Bluetooth 概述 【官方文档翻译】

    Core Bluetooth 框架在Mac和iOS平台,为配备了低功耗蓝牙无线技术的设备提供了进行通信所需要的类.例如,您的应用程序可以发现,探索,和低功耗的外围设备进行交互,如心率监视器.数字温控器 ...

  9. Delphi IOS 蓝牙锁屏后台运行

    Delphi IOS 后台运行 同样的程序,编译成android,锁屏后继续运行正常,蓝牙通讯正常,但在IOS下锁屏后程序的蓝牙就中断通讯了? IOS的机制就是这样,锁屏就关闭了. 音乐播放器是怎么做 ...

随机推荐

  1. 基于Map的用户注册、登录、抽奖系统

    期望功能 方法设计 1.类的设计: 定义两个参与者的属性: private String username; private String userpassword; 2.注册方法: public v ...

  2. archlinux升级firefox的flash插件

    参考:http://blog.csdn.net/kingolie/article/details/53066415 1. 在https://get.adobe.com/flashplayer/下载文件 ...

  3. 将libFM模型变换成tensorflow可serving的形式

    fm_model是libFM生成的模型 model.ckpt是可以tensorflow serving的模型结构 亲测输出正确. 代码: import tensorflow as tf # libFM ...

  4. linux 运维基础之http协议详解

    引言 这尼玛博客还得自己在这里写,难受一匹本来排版好的...每次都这样嗨....本内容属于借鉴资源,侵权删! HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系 ...

  5. python-URL转jpg图片

    问题描述 有图片地址,可以在网页打开 URL:https://bdfile.bluemoon.com.cn/group2/M00/0A/BA/wKg_HlwzY1SAIdXDAAFyo-ZOLKQ39 ...

  6. jQuery.Flot开发手记

    目录 介绍 使用 自定义参数 自定义图例 自定义坐标 自定义数据序列 自定义网格 其他 鼠标停留在图表节点时显示tooltip 介绍 项目地址:http://www.flotcharts.org/ A ...

  7. nodejs基础知识查缺补漏

    1. 单线程.异步I/O.对比php nodejs是单线程的,但是是异步I/O,对于高并发时,它也能够快速的处理请求,100万个请求也可以承担,但是缺点是非常的耗内存,但是我们可以加大内存, 所以能用 ...

  8. VMware虚拟网卡设置问题

    具体操作过程如下: (1)为虚拟机添加虚拟网卡 (2)添加后会自动分配子网ip,不用修改.点击应用,确定. (3)添加完成后本机的网络上会多出一个网络适配器,根据虚拟机器中的ip设置此ip地址, 这里 ...

  9. 02-使用注解配置spring

    1 准备工作 1.导包 4+2+spring-aop[新版本需要导入 spring-aop 包] 2.为主配置文件引入新的命名空间(约束) [context] 3.开启使用注解代理配置文件 4.在类中 ...

  10. jquery返回顶部和底部插件和解决ie6下fixed插件

    (function($){ //返回顶部和底部插件 $.fn.extend({ goTopBootom:function (options){ //默认参数 var defaults = { &quo ...