苹果蓝牙后台的限制,原本广播会有两个段分别是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. php 5 与7有什么区别

    PHP 7.0使用新版的ZendEngine引擎,带来了许多新的特性,其与相比,有如下特性: 性能提升:PHP7比PHP5.0性能提升了两倍. 全面一致的64位支持. 以前的许多致命错误,现在改成抛出 ...

  2. Nginx配置简单基于域名的虚拟主机

    首先修改hosts文件,让浏览器在看到a.com或是www.a.com的网址时知道上哪里去找: # Copyright (c) 1993-2009 Microsoft Corp. # # This i ...

  3. 【maven】插件和依赖管理

    1.插件管理 定义 pluginManagement 用来做插件管理的.它是表示插件声明,即你在项目中的pluginManagement下声明了插件,Maven不会加载该插件,pluginManage ...

  4. c# winform访问 带有windows身份验证的webservice

    1 将webservice设置为windows身份验证iis10中,要确认已安装windows身份验证在 控制面板 - >打开或关闭Windows功能 - >万维网服务 - >安全性 ...

  5. HTTP和HTTPS概念

    HTTP和HTTPS HTTP协议(HyperText Transfer Protocol,超文本传输协议):是一种发布和接收 HTML页面的方法. HTTPS(Hypertext Transfer ...

  6. mac下安装face_recognition

    安装依赖库: 1.安装cmake (是一个跨平台的安装工具) brew install cmake 2.安装boost.boost-python(C++的程序库) brew install boost ...

  7. 【翻译】Flink Table Api & SQL —Streaming 概念 ——时间属性

    本文翻译自官网: Time Attributes   https://ci.apache.org/projects/flink/flink-docs-release-1.9/dev/table/str ...

  8. 【超分辨率】- CVPR2019中SR论文导读与剖析

    CVPR2019超分领域出现多篇更接近于真实世界原理的低分辨率和高分辨率图像对应的新思路.具体来说,以前论文训练数据主要使用的是人为的bicubic下采样得到的,网络倾向于学习bicubic下采样的逆 ...

  9. Django文档阅读之聚合

    聚合 我们将引用以下模型.这些模型用来记录多个网上书店的库存. from django.db import models class Author(models.Model): name = mode ...

  10. VueJS中学习使用Vuex详解

    转载自:https://segmentfault.com/a/1190000015782272,做了部分修改(这里建议不要用所谓的getters,一来多次一举,二来模块化时会产生很不协调的用法) 在S ...