苹果蓝牙后台的限制,原本广播会有两个段分别是localName和serviceUUID这两块,但现在后台广播时,是不发送在这两段的

手机app可以作为一个蓝牙外设端来模拟外设硬件,但广播包里的数据只能包含localName和serviceUUID,相对于外设硬件来说还是有一些不足之处。

一个128位的蓝牙UUID来标示

32个 x 是 0-9 或 a-f 范围内的一个十六进制的数字(0x00),X是字符串格式

把数据按uuid的格式加进去

self.peripheralManager startAdvertising:@{CBAdvertisementDataServiceUUIDsKey:serviceUUIDs,CBAdvertisementDataNameKey:localName}];

对应的值是数组

key: kCBAdvDataIsConnectable, value: 1

key: kCBAdvDataLocalName, value: SimpleBLEPeripheral

key: kCBAdvDataServiceUUIDs    //数据就在这里

       uuid(0): FF F0

key: kCBAdvDataTxPowerLevel, value: 0

Manufacturer Specific Data

NSArray *keys = [advertisementData allKeys];

NSData *dataAmb, *dataObj;

//获取所有的key

for (int i = 0; i < [keys count]; ++i) {

id key = [keys objectAtIndex: i];

NSString *keyName = (NSString *) key;

NSObject *value = [advertisementData objectForKey: key];

//处理所有的value

if ([value isKindOfClass: [NSArray class]]) {

printf("   key: %s\n", [keyName cStringUsingEncoding: NSUTF8StringEncoding]);

NSArray *values = (NSArray *) value;

//处理每个value里面的值

for (int j = 0; j < [values count]; ++j) {

if ([[values objectAtIndex: j] isKindOfClass: [CBUUID class]]) {

CBUUID *uuid = [values objectAtIndex: j];

NSData *data = uuid.data;  //获取到  uuid.data

if (j == 0) {

dataObj = uuid.data;

} else {

dataAmb = uuid.data;

}

printf("      uuid(%d):", j);

for (int j = 0; j < data.length; ++j)

printf(" %02X", ((UInt8 *) data.bytes)[j]);

printf("\n");

} else {

const char *valueString = [[value description] cStringUsingEncoding: NSUTF8StringEncoding];

printf("      value(%d): %s\n", j, valueString);

}

}

} else {

const char *valueString = [[value description] cStringUsingEncoding: NSUTF8StringEncoding];

printf("   key: %s, value: %s\n", [keyName cStringUsingEncoding: NSUTF8StringEncoding], valueString);

}

}

蓝牙周边后台执行模式

想要作为一个周边角色在后台工作,你需要在Info.plist文件中添加bluetooth-periphral到UIBackgroundModes关键字下。当你这么做了,系统会在你的app需要读,写,订阅事件的时候唤醒它。

除了可以在后台唤醒app处理连接的中心的读写订阅。蓝牙中心库还可以允许你的app在后台的时候广播。但是你需要了解app在后台的广播和在前台的广播状态不太一样。特别的,当你的app在后台广播时。

CBAdvertisementDataLocalNameKey 广告键是被忽略的,而且local name也不会被广播的

所以 CBAdvertisementDataServiceUUIDsKey中的服务UUID被放在一个“溢出”区,它们只能被明确搜索的iOS设备搜索到。

如果所有app都在后台广播,你的app的包广播频率会变少。

When you start advertising peripheral data, the peripheral manager calls the peripheralManagerDidStartAdvertising(_:error:) method of its delegate object.

Data advertising is done on a “best effort” basis, because space is limited and there may be multiple apps advertising simultaneously. While your app is in the foreground, it can use up to 28 bytes of space in the initial advertisement data for any combination of the supported advertising data keys. If this space is used up, there are an additional 10 bytes of space in the scan response that can be used only for the local name (represented by the value of the CBAdvertisementDataLocalNameKey key). Note that these sizes do not include the 2 bytes of header information that are required for each new data type. Any service universally unique identifiers (UUIDs) contained in the value of the CBAdvertisementDataServiceUUIDsKey key that do not fit in the allotted space are added to a special “overflow” area; they can be discovered only by an iOS device that is explicitly scanning for them. While your app is in the background, the local name is not advertised and all service UUIDs are placed in the overflow area. The exact format of advertising and response data is defined in the Bluetooth 4.0 specification, Volume 3, Part C, Section 11.

当开始广告外围设备数据时,外围设备管理器调用其委托对象的外围信息管理器didstartadvertising (_:error:)方法。

数据广告是在“尽最大努力”的基础上进行的,因为空间有限,同时可能有多个应用程序在做广告。当你的应用程序在前台时,它可以在初始广告数据中使用最多28字节的空间来组合支持的广告数据键。如果耗尽了这个空间,那么扫描响应中还有额外的10字节空间,只能用于本地名称(由CBAdvertisementDataLocalNameKey键值表示)。注意,这些大小不包括每个新数据类型所需的2个字节的头信息。在特定的“溢出”区域中添加不适合于分配的空间的CBAdvertisementDataServiceUUIDsKey键值中包含的任何服务通用惟一标识符(uuid);只有当iOS设备显式地扫描它们时,才能发现它们。当您的应用程序在后台时,本地名称没有广告,所有服务uuid都放置在溢出区域。广告和响应数据的确切格式定义在蓝牙4.0规范第3卷C部分第11节中。

在初始化中心或者周边管理者的时候选择是否需要支持状态的保存和恢复

在初始化时指定CBCentralManagerOptionRestoreIdentifierKey选项,并为中心管理者提供一个字符串作为“恢复标识”就可以了:

myCentralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:@{ CBCentralManagerOptionRestoreIdentifierKey: @"myCentralManagerIdentifier" }];

CBPeripheralManagerOptionRestoreIdentifierKey

恢复你的中心和周边管理者

当你的app在后台被系统重启时,你的第一件事就是根据“恢复标识”恢复适当的中心和周边管理者就像他们第一次创建时一样

当你的app被系统重启时,你可以检索系统为你的应用程序保留的中央管理器对象的所有恢复标识符,像这样:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSArray *centralManagerIdentifiers = launchOptions[UIApplicationLaunchOptionsBluetoothCentralsKey];

在拿到恢复标示符之后,只需要遍历并恢复适当的中央管理者。

- (void)centralManager:(CBCentralManager *)central willRestoreState:(NSDictionary *)state { NSArray *peripherals = state[CBCentralManagerRestoredStatePeripheralsKey]; ...

iOS 作为蓝牙外设广播信息的更多相关文章

  1. esp32使iOS 获取蓝牙外设的Mac地址

    最近在做一个需要上下位机的项目,我负责的任务下位机,使用的主控芯片是esp32.这个项目中有一项是需要手机扫描二维码然后连接作为esp32的蓝牙.二维码中包含了mac地址信息,在手机扫描周围设备的时候 ...

  2. 微信小程序之蓝牙广播信息

    期初第一次做蓝牙开锁的时候遇到的最尖锐的问题就是ios设备如何对获取的广播信息进行读取,大概用了4中方式,都无法解决,最后不得不求助官方人员.给了一个方法,大家可以参考.在此附图: 由于mac地址是6 ...

  3. ios设备app作为蓝牙外设端

    苹果手机可以作为蓝牙外设端,被蓝牙中央端来扫描连接交互数据,实现模拟蓝牙外设硬件.通过阅读CoreBluetooth库,可以找到一个CBPeripheralManager的类,该类主要的作用就是允许你 ...

  4. iOS之 PJSIP蓝牙外设音频支持

    如题,蓝牙设备作为音频输出,在app中如果包含VoIP那么就要设定当连接蓝牙设备时候是否选择或者支持蓝牙输出 最近在处理一个工单就是公司的voip-app与硬件话机底座联调(蓝牙2.0)坑爹的如果是4 ...

  5. iOS - App 与外设间的通信方式

    1.前言 一般 iOS 开发者做 App 开发大部分时候都是通过 Http(s) 请求跟后台服务器打交道,做一些信息展示和用户交互.很少涉及到去跟外部硬件设备连接的开发.随着近年来车联网和物联网的兴起 ...

  6. iOS之蓝牙开发—CoreBluetooth详解

    CoreBluetooth的API是基于BLE4.0的标准的.这个框架涵盖了BLE标准的所有细节.仅仅只有新的iOS设备和Mac是和BLE标准兼容.在CoreBluetooth框架中,有两个主要的角色 ...

  7. iOS,蓝牙开发!!--By帮雷

    iOS的蓝牙开发大致有以下几种方式. 1 GameKit.framework [只能存在于iOS设备之间,多用于游戏 能搜索到的demo比较多,不确切说名字了,code4app里面就有] 2 Core ...

  8. iOS关于蓝牙连接的简单介绍与使用

    下面是两台iPhone6连接同一台蓝牙设备的结果: **成功连接**** peripheral: <CBPeripheral: 0x1700f4500, identifier = 50084F6 ...

  9. ios获取CELLID,LAC等信息方法

    搞了一个来月的这个东西了,还是没有完全解决问题,下面方法可以获取简单的Cell信息,方法一://CoreTelephony.h//主要就这两个结构体,其他需要的话,自己添加struct CTServe ...

随机推荐

  1. MySQL Group By 实例讲解(一)

    MySQL Group By 实例讲解 group by语法可以根据给定数据列的每个成员对查询结果进行分组统计,最终得到一个分组汇总表. SELECT子句中的列名必须为分组列或列函数.列函数对于GRO ...

  2. (5)Flask项目会员登录页

    一.添加登录和登出的路由 修改app/home/views.py内容,增加登录("/login/")和登出("/logout/")的路由: # coding:u ...

  3. 泡泡一分钟:Teaching Robots to Draw

    Teaching Robots to Draw 教会机器人画画https://h2r.cs.brown.edu/wp-content/uploads/kotani19.pdf Atsunobu Kot ...

  4. SAP views

    文章转自 http://blog.csdn.net/HikenWong/article/details/8263969 1. sap的视图的类型sap的视图的类型有五种: Database views ...

  5. css选择器测试2-用ul和li简单排版

    之前的博文:测试了一些css样式的优先级,都是比较常见的选择器 ,这里测试一些其他一些选择方式. *:通配符,所有页面的元素都走这个.设置多个class:一个标签里不能有两个class,如果想要设置多 ...

  6. [ARM-Linux开发]linux 里 /etc/passwd 、/etc/shadow和/etc/group 文件内容解释

    linux 里 /etc/passwd ./etc/shadow和/etc/group 文件内容解释 一./etc/passwd 是用户数据库,其中的域给出了用户名.加密口令和用户的其他信息 /etc ...

  7. php xml转array的方法

    php xml转array的方法 <pre><?php $responseXml='<xml><appid>12</appid></xml& ...

  8. Linux下Python安装PyMySQL成功,但无法导入的问题

    今天使用 Nginx 部署 Django应用.安装python库都显示成功安装. 尝试启动 uwsgi 服务,竟然报错 Traceback (most recent call last): File ...

  9. IDEA 获取类的相对路径和绝对路径

    1.相对路径: 结果:action.HelloAction 2.绝对路径 结果:E:\javaProject\JavaEEProject\day08_Struts2_test01\src\action ...

  10. day39——SQL语句简单介绍、库、表、记录、安装mysql简单命令

    day39 SQL语句简单介绍 库(增删改查) 查看数据库 show databases; 查看其中一个库 show create database db1; 创建数据库 create databas ...