iOS蓝牙

Posted 顺手给我new一个对象

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS蓝牙相关的知识,希望对你有一定的参考价值。

ios中进行蓝牙传输应用开发常用的框架有如下几种:

GameKit.framework:iOS7之前的蓝牙通讯框架,从iOS7开始过期,但是目前多数应用还是基于此框架。

MultipeerConnectivity.framework:iOS7开始引入的新的蓝牙通讯开发框架,用于取代GameKit。

CoreBluetooth.framework:功能强大的蓝牙开发框架,要求设备必须支持蓝牙4.0。

前两个框架使用起来比较简单,但是缺点也比较明显:仅仅支持iOS设备,传输内容仅限于沙盒或者照片库中用户选择的文件,并且第一个框架只能在同一个应用之间进行传输(一个iOS设备安装应用A,另一个iOS设备上安装应用B是无法传输的)。当然CoreBluetooth就摆脱了这些束缚,它不再局限于iOS设备之间进行传输,你可以通过iOS设备向android、Windows Phone以及其他安装有蓝牙4.0芯片的智能设备传输,因此也是目前智能家居、无线支付等热门智能设备所推崇的技术。

GameKit

其实从名称来看这个框架并不是专门为了支持蓝牙传输而设计的,它是为游戏设计的。而很多游戏中会用到基于蓝牙的点对点信息传输,因此这个框架中集成了蓝牙传输模块。前面也说了这个框架本身有很多限制,但是在iOS7之前的很多蓝牙传输都是基于此框架的,所以有必要对它进行了解。GameKit中的蓝牙使用设计很简单,并没有给开发者留有太多的复杂接口,而多数连接细节开发者是不需要关注的。GameKit中提供了两个关键类来操作蓝牙连接:

GKPeerPickerController:蓝牙查找、连接用的视图控制器,通常情况下应用程序A打开后会调用此控制器的show方法来展示一个蓝牙查找的视图,一旦发现了另一个同样在查找蓝牙连接的客户客户端B就会出现在视图列表中,此时如果用户点击连接B,B客户端就会询问用户是否允许A连接B,如果允许后A和B之间建立一个蓝牙连接。

GKSession:连接会话,主要用于发送和接受传输数据。一旦A和B建立连接GKPeerPickerController的代理方法会将A、B两者建立的会话(GKSession)对象传递给开发人员,开发人员拿到此对象可以发送和接收数据。

其实理解了上面两个类之后,使用起来就比较简单了,下面就以一个图片发送程序来演示GameKit中蓝牙的使用。此程序一个客户端运行在模拟器上作为客户端A,另一个运行在iPhone真机上作为客户端B(注意A、B必须运行同一个程序,GameKit蓝牙开发是不支持两个不同的应用传输数据的)。两个程序运行之后均调用GKPeerPickerController来发现周围蓝牙设备,一旦A发现了B之后就开始连接B,然后iOS会询问用户是否接受连接,一旦接受之后就会调用GKPeerPickerController的-(void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session代理方法,在此方法中可以获得连接的设备id(peerID)和连接会话(session);此时可以设置会话的数据接收句柄(相当于一个代理)并保存会话以便发送数据时使用;一旦一端(假设是A)调用会话的sendDataToAllPeers: withDataMode: error:方法发送数据,此时另一端(假设是B)就会调用句柄的- (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context方法,在此方法可以获得发送数据并处理。下面是程序代码:

 

详细代码:

 1 #import "ViewController.h"
 2 #import <GameKit/GameKit.h>
 3 
 4 @interface ViewController ()<GKPeerPickerControllerDelegate,UIImagePickerControllerDelegate,UINavigationBarDelegate>
 5 
 6 @property (weak, nonatomic) IBOutlet UIImageView *imageView;
 7 
 8 @property (nonatomic,strong) GKSession * session;//蓝牙连接会话
 9 
10 @end
11 
12 @implementation ViewController
13 
14 - (void)viewDidLoad {
15     [super viewDidLoad];
16 
17     GKPeerPickerController * pearPickerController = [[GKPeerPickerController alloc] init];
18     pearPickerController.delegate = self;
19     
20     [pearPickerController show];
21 }
22 
23 
24 #pragma mark - UI事件
25 //选择相片
26 - (IBAction)selectClick:(id)sender {
27     
28     UIImagePickerController * imagePickerController = [[UIImagePickerController alloc] init];
29     imagePickerController.delegate = self;
30     
31     [self presentViewController:imagePickerController animated:YES completion:nil];
32 }
33 
34 //发送相片
35 - (IBAction)sendClick:(id)sender {
36     
37     NSData * data = UIImagePNGRepresentation(self.imageView.image);
38     NSError * error = nil;
39     [self.session sendDataToAllPeers:data withDataMode:GKSendDataReliable error:&error];
40     
41     if (error) {
42         NSLog(@"发送图片过程中发生错误,错误信息:%@",error.localizedDescription);
43     }
44 }
45 
46 #pragma mark - GKPeerPickerController delegate
47 /**
48  *连接到某个设备
49  *
50  *@param picker  蓝牙点对点连接控制器
51  *@param peerID  连接设备蓝牙传输ID
52  *@param session 连接会话
53  */
54 - (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session{
55     
56     NSLog(@"已连接客户端设备:%@.",peerID);
57     
58     //设置数据接收处理句炳,相当于代理,一旦数据接收完成调用它的-receiveData:fromPeer:inSession:context:方法处理数据
59     [self.session setDataReceiveHandler:self withContext:nil];
60     
61     [picker dismiss];//一旦连接成功关闭窗口
62 }
63 
64 #pragma mark - 蓝牙数据接收发放
65 - (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context{
66     
67     UIImage *image=[UIImage imageWithData:data];
68     
69     self.imageView.image=image;
70     
71     UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
72     
73     NSLog(@"数据发送成功!");
74 }
75 
76 #pragma mark - UIImagePickerController delegate
77 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
78     
79     self.imageView.image = [info objectForKey:UIImagePickerControllerOriginalImage];
80     
81     [self dismissViewControllerAnimated:YES completion:nil];
82 }
83 
84 - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
85     [self dismissViewControllerAnimated:YES completion:nil];
86 }

 

效果图

技术分享技术分享技术分享

 

 

MultipeerConnectivity

前面已经说了GameKit相关的蓝牙操作类从iOS7已经全部过期,苹果官方推荐使用MultipeerConnectivity代替。但是应该了解,MultipeerConnectivity.framework并不仅仅支持蓝牙连接,准确的说它是一种支持Wi-Fi网络、P2P Wi-Fi以及蓝牙个人局域网的通信框架,它屏蔽了具体的连接技术,让开发人员有统一的接口编程方法。通过MultipeerConnectivity连接的节点之间可以安全的传递信息、流或者其他文件资源而不必通过网络服务。此外使用MultipeerConnectivity进行近场通信也不再局限于同一个应用之间传输,而是可以在不同的应用之间进行数据传输(当然如果有必要的话你仍然可以选择在一个应用程序之间传输)。

要了解MultipeerConnectivity的使用必须要清楚一个概念:广播(Advertisting)和发现(Disconvering),这很类似于一种Client-Server模式。假设有两台设备A、B,B作为广播去发送自身服务,A作为发现的客户端。一旦A发现了B就试图建立连接,经过B同意二者建立连接就可以相互发送数据。在使用GameKit框架时,A和B既作为广播又作为发现,当然这种情况在MultipeerConnectivity中也很常见。

明天再更......

以上是关于iOS蓝牙的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式在 iOS 11 中打开蓝牙设置

Android 蓝牙 LE - 读取浮动特性

SPP配置文件蓝牙iOS

iOS蓝牙未发现设备

IOS核心蓝牙:为特性编写NSData

iOS蓝牙架构搭建-2