2.OC蓝牙功能

一.  最早的蓝牙框架是GameKit,iOS7之前用的比较多,它有只能支持iOS设备间的传输,但是使用步骤简单,我们只需要搞清楚两个类就可以了。

GKPeerPickerController:熟称浏览器,调用此控制器的show方法来显示当前的蓝牙热点,一旦发现有另一页在查找蓝牙的用户,之间就能实链接。

GKSession:连接会话,主要用于发送和接受传输数据。档两个程序进行连接时,GKPeerPickerController的代理方法会将两者建立的会话(GKSession)对象传递给制定的对象。就能实现数据传输。

下面构建一个简单简单的蓝牙发送

1.1首先构建一个能显示区域的蓝牙控制器。

- (void) connectToOtherBluetoolth {
    //1.首先构建一个区域内能显示其它蓝牙的控制器,我们手机上选择蓝牙列表其实对应的操作就是这个控制器,它可以对我的操作进行监听。
    GKPeerPickerController* peerVC = [GKPeerPickerController new];
    peerVC.delegate = self;
    [peerVC show];
}

1.2 通过这个现实控制器的代理方法来监听链接是否成功,如果成功就讲链接的管道保存下来,并为它设计一个句bin

- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session {
    //2. 通过实现GKPeerPickerController 的代理方法对链接成功后的消息进行处理;这里首先我们需要吧会话对象session保存下来,应为它就相当于一个传输的管道,功能和二维码扫描的管道差不多。
    self.session = session;
    //3. 此时我们还需要制定一个用哪个方法来接收数据。这个功能可以简单的理解为类似代理的功能,此处表示给session管道对象设置一个hander(句bin),这个句bin必须实现一个接收到数据的方法。
    [session setDataReceiveHandler:self withContext:nil];
}

1.3 实现这个句bin的方法,可以简单的把它理解为类似于一个协议方法

//4. 使用self对象 实现句bin规定的方法
- (void) recevieData:(NSData *)data fromPeer:(NSString*)peer inSession:(GKSession*)session context:(void *)context {
    UIImage* image = [UIImage imageWithData:data];
    self.imageView.image = image;
}

1.4 接着我们只需要在链接成功后发送图片及可  创建图片控制器->设定代理,是否支持选择方式,制定图片的选择方式-》实现选择完成的方法,从字典内获取选择的图片

- (void)chooserImage {
     /*从相册选择图片的方法
      创建一个图片选择控制器-》判断是否可以用-》设置打开图片库的类型-》处理完这个动作需要执行相关方法,所以此处需要设置图片控制器的代理
      */
    UIImagePickerController* imagePiker = [UIImagePickerController new];
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum]) {
        imagePiker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
        imagePiker.delegate = self;
    }
}
#pragma mark - UIImagePikerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
   //此处为选择择完某一张图片后的方法,选中的图片可以从一个key中取出来。
    self.imageView.image = info[UIImagePickerControllerOriginalImage];
    //将弹出的控制器关闭。
    [picker dismissViewControllerAnimated:YES completion:nil];

}

// 3. 发送图片数据
-(void) sendimage {
    //利用链接成功的session会话对象发送
    UIImage* image = self.imageView.image;
    NSData* data = UIImagePNGRepresentation(image);
    [self.session sendData:data toPeers:nil withDataMode:GKSendDataReliable error:nil];
}

二. MutipeerConnectivity:

字面意思多热点链接。这个事苹果研究出来的真对于GameKit的替代品。它不仅仅支持蓝牙连接。它属于一个局域网的痛惜狂减,屏蔽了具体的链接技术。 通过MultipeerConnectivity链接节点之间可使文件资源传递不依赖于网络。它的实现方式主要是通过adveristing和disconvering,类似于客户端和服务器端之间的交互响应。通过一个对象发送广播发送消息,而另一个对象作为客户接受消息。经过两者之间的同意认可后就实现了对接。通GameKit它门之间的链接也需要一个专门的管道MCSession。用于接收和传递数据。而管道的两端分别对应的是MCPeerID,及两台设备之间的标示。

我们只需要设置会话对象的代理,并监听会话的状态(是否联机诶),是否有接收数据 。 其实这个和socket的套字节的用法差不多。

搞清楚了基本原理name我们就只需要熟悉下几个方法和关键单词就能熟练运动了。

2.1 设置基本的属性和控件。

@interface ViewController ()<MCSessionDelegate,MCAdvertiserAssistantDelegate,MCBrowserViewControllerDelegate,UITextFieldDelegate>
@property (weak, nonatomic) IBOutlet UIButton *browserButton;
@property (weak, nonatomic) IBOutlet UITextField *chatBox;
@property (weak, nonatomic) IBOutlet UITextView *textBox;
// 设备id,用来表示发送广播和接受广播消息的设备标示信息
@property (strong,nonatomic) MCPeerID *myPerrID;
// 连接会话,用于维持当前会话持续链接
@property(strong,nonatomic) MCSession *mySession;
// 广播对象,创建后需要开启才会发送广播,它有两个协议方法,将要发送广播和已经发送广播
@property(strong,nonatomic) MCAdvertiserAssistant *advertiserAssistant;
// 选择会话控制器,时机上就是选择蓝牙热点的列表,它可以监听我们选择的哪个热点
@property (strong,nonatomic) MCBrowserViewController *browserViewController;
@end

2.2 设置MCPeerID,MCAdvertiserAssistant(广播对象创建并启动)

static NSString *ServiceType = @"chat";
- (void) setupMutipeer{
    self.myPerrID = [[MCPeerID alloc]initWithDisplayName:[UIDevice currentDevice].name];
    self.mySession = [[MCSession alloc]initWithPeer:self.myPerrID];
    self.advertiserAssistant = [[MCAdvertiserAssistant alloc]initWithServiceType: ServiceType discoveryInfo:nil session:self.mySession];
    self.browserViewController = [[MCBrowserViewController alloc]initWithServiceType:ServiceType session:self.mySession];
    self.browserViewController.delegate = self;
    self.mySession.delegate = self;
    [self.advertiserAssistant start];
}

2.3 设置sessionde代理方法通道是否链接Ok,是否有接收到数据;设置MCBrowserViewController是否选择了蓝牙热点,并dissmiss控制器。

// 显示控制器view
- (void) showBroserVc{
    [self presentViewController:self.browserViewController animated:YES completion:nil];
}
//取消控制器
- (void) dismissBrowserVc{
    [self.browserViewController dismissViewControllerAnimated:YES completion:nil];
}
// 点击browser按钮
- (IBAction)browserBtnClick:(id)sender {
    [self showBroserVc];
}
// 发送文本
- (void) sendText{
    NSString *message = self.chatBox.text;
    self.chatBox.text = @"";
    NSData *data = [message dataUsingEncoding:NSUTF8StringEncoding];
    // 通过会话发送
    [self.mySession sendData:data toPeers:[self.mySession connectedPeers]  withMode:MCSessionSendDataReliable error:nil];
    // 收取数据
    [self reciveMessage:message fromPeer:self.myPerrID];
}
// 收取数据
- (void)reciveMessage:(NSString*) message fromPeer:(MCPeerID*) perrid{
    NSString *finalMessage = nil;
    if (perrid == self.myPerrID) {
        finalMessage = [NSString stringWithFormat:@"\nMe:%@\n",message];
    }else{
        finalMessage = [NSString stringWithFormat:@"\n%@:%@\n",perrid.displayName,message];
    }
    self.textBox.text = [self.textBox.text stringByAppendingString:finalMessage];
}
#pragma mark MCBroserControllerDelegate
- (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController{
    [self dismissBrowserVc];
}
- (void) browserViewControllerWasCancelled:(MCBrowserViewController *)browserViewController{
    [self dismissBrowserVc];
}
#pragma  mark  文本框的代理
- (BOOL) textFieldShouldReturn:(UITextField *)textField{
    [textField resignFirstResponder];
    [self sendText];
    return YES;
}
// session 的代理方法监听是否接收到数据
- (void) session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID{
    NSString *message = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self reciveMessage:message fromPeer:peerID];
    });
}
//session 监听是否连接成功
- (void) session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state{

三 . 目前最常用的一种CoreBluetoolth 核新蓝牙技术,也称为低功耗

无论是GameKit还是MultipeerConnectivity 都局限于苹果的手机上运行,非常的不方便。 CoreBluetooth.framework 基于BLE4.0标准,同时也能满足其它手机,目前使用非常广泛。运用在市场定义,室内定位,微支付,家具等领域。它的设计方式同样是机遇服务器和客户端的设计模式。 服务器端为外围设备Peripheral,客户端为Central.

下面以本地LocationManage定位为中央设备,外围热点为其它蓝牙设备来做相关说明

3.1 定义设备标示和名字;

//蓝牙服务的唯一标识
//32位       8 - 4-4-4 - 12
#define kUUID @"00000000-0000-0000-0000-000000000000"
//当前蓝牙的标志
#define kIdentifier  @"SomeIdentifier"
@import CoreBluetooth;
@import CoreLocation;
@interface ViewController ()<CLLocationManagerDelegate, CBPeripheralManagerDelegate>
/** 向外广播的beacon */
@property(nonatomic,strong) CBPeripheralManager *peripheralManager;
/** beacon的范围*/
@property(nonatomic,strong) CLBeaconRegion *beaconRegion;
/** 定位管理 */
@property(nonatomic,strong) CLLocationManager *locationManager;
@end

3.2 请求定位服务->需要注意iOS8.0之后需要对用户是否同意定位进行判定

- (CLLocationManager *)locationManager{
    if (!_locationManager) {
//  iOS8之后,定位服务需要用户许可
        _locationManager = [CLLocationManager new];
        _locationManager.delegate = self;
//先判断是否有某个方法,如果有则执行..
        if ([_locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
//请求授权操作,需要修改info.plist文件
            [_locationManager requestAlwaysAuthorization];
        }
    }
    return _locationManager;
}

3.3 在LocationManage的代理方法选择性的实现当进入区域或者退出热点区域

- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region{
    NSLog(@"didExitRegion 退出某个区域");
}
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region{
    NSLog(@"didEnterRegion 进入某个区域");
}
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region{
// 在里面,在外面,未知
    NSLog(@"状态的变更");
}
- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray<CLBeacon *> *)beacons inRegion:(CLBeaconRegion *)region{
    NSLog(@"didRangeBeacons 获知beacon的距离 %@", beacons);
    for (CLBeaconRegion *region in beacons) {
//      可以获取每个region 的 详细参数
//   proximity这个枚举变量, 标志当前距离
//        远/近/特别近/找不到
//        region.proximity
    }
}

3.4 使用LocaitonManager的代理方法获取当前位置的所有热点对象

- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray<CLBeacon *> *)beacons inRegion:(CLBeaconRegion *)region{
    NSLog(@"didRangeBeacons 获知beacon的距离 %@", beacons);
    for (CLBeaconRegion *region in beacons) {
//      可以获取每个region 的 详细参数
//   proximity这个枚举变量, 标志当前距离
//        远/近/特别近/找不到
//        region.proximity
    }
}

#pragma mark - beacon类型
- (CLBeaconRegion *)beaconRegion{
    if (!_beaconRegion) {
        NSUUID *proximityUUID=[[NSUUID alloc] initWithUUIDString:kUUID];
        _beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:proximityUUID identifier:kIdentifier];
    }
    return _beaconRegion;
}

3.5 开始监视热点,停止件事热点,停止检测热点,开始检测周围热点,开始广播,停止广播,

//检测
- (IBAction)monterning:(UISegmentedControl *)sender {
    if (sender.selectedSegmentIndex == 0) {
        [self.locationManager stopMonitoringForRegion:self.beaconRegion];
    }else{
        [self.locationManager startMonitoringForRegion:self.beaconRegion];
    }

}

//定位, Ranging  范围
- (IBAction)location:(UISegmentedControl *)sender {
    if (sender.selectedSegmentIndex==0) {
        [self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
    }else{
        [self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
    }
}

//广播
- (IBAction)advertise:(UISegmentedControl *)sender {
    if (sender.selectedSegmentIndex == 0) {
        [_peripheralManager stopAdvertising];
    }else{
        _peripheralManager=[[CBPeripheralManager alloc] initWithDelegate:self queue:nil options:nil];
    }
}
//当广播状态更新时触发
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral{
//    如果广播状态为 开启
    if (peripheral.state == CBPeripheralManagerStatePoweredOn) {
        CLBeaconRegion *region=[[CLBeaconRegion alloc] initWithProximityUUID:self.beaconRegion.proximityUUID major:rand() minor:rand() identifier:kIdentifier];
        [_peripheralManager startAdvertising:[region peripheralDataWithMeasuredPower:nil]];
    }
}
时间: 2024-10-05 14:37:43

2.OC蓝牙功能的相关文章

经测试稳定可用的蓝牙链接通信Demo,记录过程中遇到的问题的思考和解决办法,并整理后给出一个Utils类可以简单调用来实现蓝牙功能

说明:这是本人在蓝牙开发过程中遇到过的问题记录和分析,以及解决办法. 在研究过程中,许多的前人给出的解决方案和思路指导对我相当有帮助,但并非都是可采取的解决方法, 经过本人对这些方法的测试和使用过后,给出自己的理解和解决方案,不一定是正确的,但这些方法的确可以解决问题. 如果有人遇到同样的问题,并且看到我的文章解决,那是我的荣幸. !!!!!!但特别需要说明的是,看的越多,不明白的越多,我的看法可能是完全错误的,这些方法只是暂时解决了我的问题, !!!!!!如果有人发现了我的错误,请私信或评论告

win10系统自带蓝牙功能怎么用

Windows10系统自发布后就一直备受关注,而它也不负众望新增了很多功能.大多用户都知道Win10有蓝牙功能,可以连接蓝牙耳机.鼠标等,但是还有部分用户不知道,win10的蓝牙还可以进行文件传输.比如连接手机的蓝牙,文件就可以在电脑和手机上互传了.下面小编就告诉大家win10蓝牙传输文件的方法. 热门推荐:win10系统官方下载 具体如下: 1.使用快捷键"Win+R",打开运行窗口,输入"fsquirt"并"确定". 2.之后会出现一个蓝牙文

mtk硬件启动关闭蓝牙功能的项目:mtk 上层操作GPIO应用示例

mtk硬件启动关闭蓝牙功能的项目:mtk上层操作GPIO应用示例 项目要求: 接上篇: 1:蓝牙按键(KCOL2+KROW1)长按3秒,软件上控制GPIO144拉高2秒后关闭,蓝牙就开启并搜索配对.同时拉高GPIO98,控制音频的模拟开关切换蓝牙音源. 2:蓝牙在工作状态下,给出个1.8V的高电平,给GPIO145用来检测蓝牙的工作状态. 3:蓝牙在工作装态下想要重新配对,在长按蓝牙按键3秒,控制GPIO97拉高3秒后关闭,蓝牙模块在收到这个信号后执行清空列表和重新搜索功能. 4:蓝牙按键(KC

海美迪Q5智能机顶盒的蓝牙功能

虽然在硬件上,海美迪Q5智能机顶盒没有集成蓝牙模块,但是在软件系统上,Q5是支持蓝牙驱动的,所以它可以通过USB外接蓝牙适配器来扩展出蓝牙功能,简单来说,就是你另外买个蓝牙适配器,插到Q5上面,就能用Q5连接耳机/音箱/游戏手柄等等蓝牙设备了. 本文主要记录了我用Q5连接蓝牙音箱的操作步骤: Step1:我使用的是下面这款蓝牙适配器,奥睿科(ORICO) BTA-406-RD Step2:启动Q5,进设置界面,在左边选择"蓝牙",右边会显示"要监测设备,请打开蓝牙功能&quo

为什么2014这年头蓝牙功能越来越差

蓝牙在2.4G频段进行工作的,可为什么WIFI 蓝牙都使用2.4G频段呢? 2.4G正好是各国通用的免费频段.为了避免和军事,移动通信或者其他专用通讯频段相互冲突和干扰各国都有自己的无线电频率管理机构,大部分的频率使用都需要向该机构申请.而免费频率不需要.主要的免费频段有433MHz 866MHz 915MHz 2.4G和5G等.Wifi 起初定义的时候又要考虑前瞻性, 生产成本, 频率通用性, 而基于前瞻性的考虑 433Mhz 和866 915 显然不够快, 因此一开始的Wifi就用了2.4G

记录使用微信小程序的NFC和蓝牙功能读取15693芯片的开发历程

开发目标: (1) 对于Android手机,直接通过微信小程序调用手机的NFC功能,对15693协议的芯片进行读写操作: (2)对于苹果手机(及没有NFC模块的手机),通过微信小程序的蓝牙功能连接到蓝牙/NFC读写器,然后通过蓝牙发送指令操作读写器对15693协议的芯片进行读写操作. DAY #1 上午开了半天会,下午开始开发. 先开发简单的:直接通过Android手机的NFC模块读写芯片.开发思路如下: 1. 首先调用 wx.getHCEState(OBJECT), 判断设备是否支持NFC,如

微信小程序开发-蓝牙功能开发

0. 前言 这两天刚好了解了一下微信小程序的蓝牙功能.主要用于配网功能.发现微信的小程序蓝牙API已经封装的很好了.编程起来很方便.什么蓝牙知识都不懂的情况下,不到两天就晚上数据的收发了,剩下的就是数据帧格式的定义,当然这部分就不是本次博客的重点.1. 准备硬件 这里我准备了CH341SER这个作为USB转串口.用sscom5.13.1 串口工具.由于我不太懂硬件开发.硬件部分都是由公司其他人开发的.我只是负责把环境搭建起来.然后负责我的微信小程序开发. 2. 开发小程序简单讲解 onLoad

mtk硬件启动关闭蓝牙功能的项目:mtk 硬件ScanCode和keycode应用示例

项目要求:该项目由于没有使用android5.0,导致启动bluetooth的蓝牙audio slave功能必须使用第三方模组,该第三方模组,启动是通过android主板通过GPIO控制.UI界面是通过图形选择或者一个kpd组合按键来打开关闭或者是启动蓝牙搜索功能. 1,用户按键的侦测: 标准的行为,用户的组合按键,kernel里面向上层发送scancode,然后framework把scancode转换成keycode的keyevent,该keyevent会被PhoneWindows接受并处理.

为什么这年头蓝牙功能越来越差

蓝牙在2.4G频段进行工作的.可为什么WIFI 蓝牙都使用2.4G频段呢? 2.4G正好是各国通用的免费频段. 为了避免和军事,移动通信或者其它专用通讯频段相互冲突和干扰各国都有自己的无线电频率管理机构.大部分的频率使用都须要向该机构申请.而免费频率不须要.基本的免费频段有433MHz 866MHz 915MHz 2.4G和5G等.Wifi 起初定义的时候又要考虑前瞻性, 生产成本, 频率通用性, 而基于前瞻性的考虑 433Mhz 和866 915 显然不够快, 因此一開始的Wifi就用了2.4