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

问题描述 投票:0回答:2

我正在编写一个应用程序,当应用程序位于前台和后台时扫描蓝牙信标。我有前景部分,但我不知道如何为背景部分做什么,特别是在Android 8.0及以上系统不允许应用程序在后台运行15分钟更长时间。

该应用程序需要扫描信标并获取其mac地址和UUID。此外,它应该获得扫描响应,因为那里有一些我需要解码和保存的信息。我使用指南here使用BluetoothLeScanner实现前景扫描。至于背景,我尝试将扫描模式更改为LOW_POWER,但操作系统在大约15分钟后杀死应用程序。请注意,我不希望前台服务有持续的通知,我只能以~15分钟的间隔运行扫描。

许多人建议使用Android Beacon Library,但是我找不到我们使用的信标类型所需的beaconLayout,Kontakt Beacon Pro BP16-3,因此Beacon Library没有检测到它们。

我需要信息的信息包括唯一ID和电池百分比。有关它们在扫描响应中的位置的详细信息,请参见[此处](https://support.kontakt.io/hc/en-gb/articles/206294004-How-to-check-the-battery-level-on-your-beacons)。

我很感激任何帮助编写代码来搜索背景中的信标,这些信标适用于6.0及以上的任何Android版本,或者帮助将Beacon Library与我上面提到的信标一起使用。

编辑:扫描响应的唯一ID和蓝牙

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

当我使用Beacon Library时,我找不到一种简单的方法来获得扫描响应的解析版本。相反,我必须使用NonBeaconLeScanCallback来获取字节数组。然后,字节数组结果是

[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中打印下面的内容:

 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

提前致谢。

android bluetooth-lowenergy ibeacon android-bluetooth ibeacon-android
2个回答
1
投票

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

使用Android Beacon Library时,扫描响应也可用,Android操作系统会获取扫描响应并将其存储在BluetoothDevice#name字段中。 (见here)。 Android Beacon库在解析信标时会将该字段复制到Beacon#name字段中。因此,如果您可以解析信标并且设备检测到扫描响应,那么信息将作为字符串提供给您。

这里有两个障碍:

  1. 您的Kontakt.io信标似乎没有宣传实际上是灯塔广告的任何内容。您可能需要将其配置为通告iBeacon格式或Eddystone-UID格式。完成此操作并使用该布局配置Android Beacon Library后,它将检测到它。请注意,显示的字节:processing pdu type 16: 0201060d166afe0206010a64f456425a4d08094b6f6e74616b74000000000000000000000000000000000000000000000000000000000000000000000000 with startIndex: 5, endIndex: 16 This is not a matching Beacon advertisement.与iBeacon或Eddystone不对应。这似乎是某种专有的16位GATT服务广告(AD类型0x16)。它具有0x0102的16位服务UUID,其对应于standardcustom 16位UUID的蓝牙SIG列表中的任何内容。你的猜测和我的一样好!
  2. BluetoothDevice#name或Beacon#name将是String。您需要将其转换为字节,然后按照Kontakt.io在其扫描响应文档中描述的那样解析电池电量。

1
投票

您只需扫描广告就无法读取Kontakt.io信标的电池电量。您必须使用板载GATT服务连接到它(更多信息如下)。

对于背景和前景中的一般扫描,您当然可以使用Android Beacon Library。您可能想要使用iBeacon布局:

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

但是,虽然以上将检测到您的信标,但它不会告诉您电池电量。这是因为Kontakt没有公布其电池电量。要获得它,您必须单独连接到服务UUID = 0x1805的GATT服务,然后读取特征UUID = 0x2a19的特征值。这将返回介于0-100之间的值,表示电池的百分比级别。

您可以在Kontakt.io的“其他BLE扫描仪”部分here中查看有关如何访问此内容的详细信息。

好的,所以这并没有告诉你如何编写代码来读取该值。为此,您需要学习蓝牙LE GATT编程的基础知识,这需要一些学习。一个好的起点是here.你需要编写几个步骤:

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

使用附近信标的蓝牙MAC地址字符串的存储副本,所有上述内容可能会被放入预定的作业中,每15分钟运行一次。

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

© www.soinside.com 2019 - 2024. All rights reserved.