首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在后台实现蓝牙信标的JobScheduler扫描?

如何在后台实现蓝牙信标的JobScheduler扫描?
EN

Stack Overflow用户
提问于 2019-03-31 21:41:15
回答 2查看 1.6K关注 0票数 0

我正在写一个应用程序,扫描蓝牙信标时,应用程序是在前景和背景。我已经弄清楚了前台部分,但我不知道如何处理后台部分,特别是在Android8.0和以上版本中,系统不允许应用程序在后台运行更长时间的15分钟。

该应用程序需要扫描信标,并获取他们的mac地址和UUID。此外,它应该得到扫描响应,因为有一些信息,我需要解码和保存。我已经使用指南这里实现了前景扫描使用BluetoothLeScanner。至于背景,我试着将扫描模式更改为LOW_POWER,但是操作系统在15分钟后就会杀死这个应用程序。请注意,我不希望前台服务有一个不断的通知,我很好的扫描只运行间隔约15分钟。

许多人建议使用安卓灯塔库,但我找不到我们使用的信标类型所需的beaconLayout,KontaktBeaconProBP16-3,所以信标库没有检测到它们。

我需要的信息,从信标,包括唯一的ID和电池百分比。有关它们在扫描响应中的位置的详细信息,请参见这里

我希望您能帮助我编写代码,以便在6.0或更高版本的Android版本上搜索信标,或者帮助使用灯塔库和上面提到的信标。

编辑:唯一的ID &来自扫描响应的蓝牙

当我使用BLEScanner扫描信标时,我可以使用ScanResult::getScanRecord()来获取scanRecord对象。然后,我使用getServiceData()方法获得一个字节数组,其前4个字节表示ASCII中唯一的ID,接下来的两个字节是ASCII中的固件版本,最后一个字节是十六进制中的电池百分比。我甚至确认了电池水平与官方的Kontakt应用程序,所以我相信它是正确的。

当我使用灯塔库时,我找不到一种简单的方法来获得扫描响应的解析版本。相反,我必须使用一个NonBeaconLeScanCallback来获取字节数组。然后,字节数组被证明是

代码语言:javascript
复制
[2, 1, 6, 26, -1, 76, 0, 2, 21, -9, -126, 109, -90, 79, -94, 78, -104, -128, 36, -68, 91, 113, -32, -119, 62, -91, 68, 124, 56, -77, 8, 9, 75, 111, 110, 116, 97, 107, 116, 2, 10, -12, 10, 22, 13, -48, 68, 106, 69, 77, 52, 50, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0].

索引46-49中的字节似乎表示了ASCII中唯一的id,在本例中是"DjEM“。此外,索引52处的字节是以十进制为单位的电池百分比;在这种情况下,是68。

似乎通过使用BLE扫描仪,我可以在解析唯一的ID和电池方面节省很多麻烦。然而,要可靠地实现背景扫描要困难得多。因此,是否有一种方法可以将两者结合起来,并获得培根库来解析唯一的ID和电池百分比?

EDIT2:不识别我的信标时的信标库消息

尽管我同时使用iBeacon和EddyStone信标布局,但信标库仍然无法检测到我的信标。它在logcat中打印以下内容:

代码语言:javascript
复制
 processing pdu type 16: 0201060d166afe0206010a64f456425a4d08094b6f6e74616b74000000000000000000000000000000000000000000000000000000000000000000000000 with startIndex: 5, endIndex: 16
This is not a matching Beacon advertisement. (Was expecting 02 15.  The bytes I see are: 0201060d166afe0206010a64f456425a4d08094b6f6e74616b74000000000000000000000000000000000000000000000000000000000000000000000000
Ignoring pdu type 01

提前谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-04-02 22:23:31

根据链接的Kontakt.io文档,扫描响应中也有电池电平。(注意:当您检测到信标数据包时,扫描响应并不总是可用的,但它通常是可用的--它由Android操作系统提供,并在接收到扫描响应时与扫描数据合并。)在原始的Android扫描结果bye数组中,扫描响应被简单地加到常规扫描数据的末尾。

当使用Android时,扫描响应也是可用的,Android操作系统接受扫描响应并将其存储在BluetoothDevice#name字段中。(见这里。安卓信标库在解析信标时,将该字段复制到Beacon#name字段中。因此,如果您可以解析信标,并且设备检测到扫描响应,则信息将作为字符串提供给您。

这里有两个障碍:

  1. 您的Kontakt.io信标似乎没有广告任何实际上是信标广告。您可能需要将其配置为广告iBeacon格式或Eddystone-UID格式。一旦您这样做,并配置了Android灯塔库的布局,它将检测到它。注意,显示的字节:processing pdu type 16: 0201060d166afe0206010a64f456425a4d08094b6f6e74616b74000000000000000000000000000000000000000000000000000000000000000000000000 with startIndex: 5, endIndex: 16 This is not a matching Beacon advertisement.不对应于iBeacon或Eddystone。这似乎是某种专利的16位GATT服务广告(广告类型0x16).它的16位服务UUID为0x0102,这与标准自定义 16位UUID的蓝牙SIG列表中没有对应。你的猜测和我的一样好!
  2. BluetoothDevice#name或Beacon#name将是一个字符串。您需要将其转换为字节,然后解析出Kontakt.io在其扫描响应文档中描述的电池级别。
票数 1
EN

Stack Overflow用户

发布于 2019-03-31 23:37:59

您不能简单地通过扫描广告来读取Kontakt.io信标的电池级别。您必须使用GATT上的服务连接到它(下面将有更多的信息)。

对于背景和前景中的一般扫描,您当然可以使用。您可能希望使用iBeacon布局:

代码语言:javascript
复制
        mBeaconManager.getBeaconParsers().add(new BeaconParser().
                setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));

但是,虽然上面会检测到你的信标,但它不会告诉你电池的水平。这是因为Kontakt没有宣传它的电池级别。要获得它,您必须使用service = 0x1805分别连接到GATT服务,然后读取具有特征UUID = 0x2a19的特性的值。这将返回一个介于0-100之间的值,指示电池的百分比水平.

您可以在Kontakt.io的“其他BLE扫描器”部分这里中看到如何访问它的详细信息。

好的,这并没有告诉您如何编写代码来读取这个值。要做到这一点,您需要学习蓝牙LE GATT编程的基础知识,这需要一点学习。一个很好的起点是这里。,您需要编写几个步骤:

  1. 扫描设备( Android使用其测距API为您完成此部分,给出String macAddress = beacon.getBluetoothAddress();中的设备MAC地址)
  2. 连接到设备。如果您已经使用该库进行了发现,则可以获得对该设备的引用并使用bluetoothAdapter.getRemoteDevice(macAddress).connectGatt(...)连接到该设备。
  3. 发现服务
  4. 在上述步骤的服务列表中查找0x1805服务uuid。
  5. 从上面发现已发现的服务的特性
  6. 在上述步骤的特征列表中查找0x2a19特征uuid。
  7. 阅读上述发现特征的价值。

所有这些都可能被放到一个预定的作业中,每15分钟运行一次,使用附近信标的蓝牙MAC地址字符串的存储副本。

我知道这可不容易我知道。我希望我能给你几行代码,以获得电池的水平,但不幸的是,它不能那样工作。欢迎来到蓝牙世界关贸总协定编程!

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55445707

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档