首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用bluetoothLEScanner().startScan时未触发的广播

使用bluetoothLEScanner().startScan时未触发的广播
EN

Stack Overflow用户
提问于 2020-03-08 18:13:16
回答 1查看 561关注 0票数 1

当设备进入带有特定UUID的信标区域时,我试图唤醒我的应用程序。

到目前为止,我尝试使用本机BluetoothAdapter.getBluetoothLeScanner,提供一个PendingIntent来启动广播接收者。

我还尝试了RxBleClient,这是一个很棒的库,它在进行常规发现时工作。

我尝试了AltBeacon库,这也是一个非常彻底和出色的库。

我还试过在Apis附近提供游戏服务。

但都失败了。他们都可以定期扫描信标,但当他们试图基本上,注册和让设备扫描时,在bg。广播永远不会被触发。

在使用前台服务的同时,我也尝试了所有4种服务。这也于事无补。我还提到这一切都是在Android 8上完成的,我在这两个库中查看了代码,它们最终都使用了来自本机蓝牙适配器的相同函数调用。所以我假设如果失败了,其他一切都会失败。我还提到,当为startScan函数提供CallBack而不是PendingIntent时,所有扫描的BT设备都会不断触发回调。如果我只为UUID添加了一个ScanFilter来筛选,它就会失败。我遗漏了什么?

顺便说一句,当我在Ios中实现这一功能时,它运行得完美无缺。这个应用程序被唤醒了,好像我使用了Geofence /exit触发器。

为什么这在Android系统中不起作用?有什么想法吗?

编辑:这就是我如何使用来自AltBeacon库的代码。它基本上是一个复制粘贴从DOCS教程。唯一的区别是,我将它封装在一个单独的类中:

代码语言:javascript
复制
public void init(AppCompatActivity context) {
    if (isRegistered) {
        return;
    }

    BluetoothManager bluetoothManager = (BluetoothManager) context.getApplicationContext().getSystemService(Context.BLUETOOTH_SERVICE);
    if (bluetoothManager != null) {
        bluetoothAdapter = bluetoothManager.getAdapter();
        if (!bluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            context.startActivityForResult(enableBtIntent, 1002);
        } else {
            register(context);
        }
    }
}

public void register(AppCompatActivity context) {

    if (isRegistered) {
        return;
    }

    executorService.execute(new Runnable() {
        @Override
        public void run() {
            Region region = new Region("com.sample.WakeOnDiscovery", Identifier.parse("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0"), Identifier.fromInt(11180), null);
            bootstrapRegion = new RegionBootstrap(new BootstrapNotifier() {
                @Override
                public Context getApplicationContext() {
                    return Application.getContextFromApplicationClass();
                }

                @Override
                public void didEnterRegion(Region region) {
                    Logger.log(TAG, "didEnterRegion: " + region.toString());
                }

                @Override
                public void didExitRegion(Region region) {
                    Logger.log(TAG, "didExitRegion: " + region.toString());
                }

                @Override
                public void didDetermineStateForRegion(int i, Region region) {
                    Logger.log(TAG, "didDetermineStateForRegion: " + region.toString() + "|" + i);
                }
            }, region);
        }
    });

    isRegistered = true;
}

这是当我试图扫描这个特定的UUID和主int (而不是主int)时。我认为只有didDetermineStateForRegion才会被触发。使用int i=0或1。

关于UUID,我尝试了两个不同的UUID。第一个是在我用IOS编写的示例应用程序中生成的。ios应用程序自诩为信标。我可以在另一个使用常规发现功能的应用程序中看到它。但是onEnterRegion不会触发。

我还尝试了一个来自iBeacon设备的UUID,这是我多年来经常使用的。还是没有骰子。

当我尝试使用本机android扫描仪时,我使用以下内容:

代码语言:javascript
复制
ScanSettings settings = (new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)).setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES).build();
    List<ScanFilter> filters = new ArrayList<>(); // Make a scan filter matching the beacons I care about
    filters.add(new ScanFilter.Builder()/*.setServiceUuid(ParcelUuid.fromString("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0"))*/.build());
    bluetoothAdapter.getBluetoothLeScanner().startScan(filters, settings, getPendingIntent(context));

以及:

代码语言:javascript
复制
private PendingIntent getPendingIntent(Context context) {
    return PendingIntent.getBroadcast(context, 0, new Intent(context, BTDiscoveryBroadcast.class), PendingIntent.FLAG_UPDATE_CURRENT);
}

我尝试将null作为过滤器传递,我尝试了一个空数组列表,并使用相同的UUID尝试了一个实际的过滤器。

还是什么都不管用。

我在logcat中偶然看到的是这样的错误消息:

代码语言:javascript
复制
E/NearbyDirect: Could not start scan. [CONTEXT service_id=49 ]
java.lang.IllegalStateException: Receiver com.google.location.nearby.direct.bluetooth.state.FastPairScanner$4@535d6ea registered with differing handler (was Handler (adxv) {8fab16a} now Handler (android.app.ActivityThread$H) {e4e0078})

我认为在使用AltBeacon库时也会出现这种情况。我只能假设这与我的问题有关。

编辑2: --我尝试过这样做:

代码语言:javascript
复制
ScanSettings settings = (new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)).setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES).build();
            List<ScanFilter> filters = new ArrayList<>(); // Make a scan filter matching the beacons I care about
            byte[] manufacturerData = new byte[] {
                    // iBeacon identifier prefix
                    0x02, 0x15,
                    // Your Proximity UUID
                    (byte) 0xE2, (byte) 0xC5, 0x6D, (byte) 0xB5, (byte) 0xDF, (byte) 0xFB, 0x48, (byte) 0xD2, (byte) 0xB0, 0x60, (byte) 0xD0, (byte) 0xF5, (byte) 0xA7, 0x10, (byte) 0x96, (byte) 0xE0,
                        0x3, 0x20, 0x3, 0x20, (byte) 0xC5
            };
            int manufacturerId = 0x004c; // Apple
            filters.add(new ScanFilter.Builder().setManufacturerData(manufacturerId, manufacturerData).build());
            bluetoothAdapter.getBluetoothLeScanner().startScan(filters, settings, getPendingIntent(context));

在进行常规.startDiscovery扫描、定位bt设备并从ScanResult中提取数据后获取的字节数据。只是为了确保它完全一样。

仍然不触发广播:

EN

回答 1

Stack Overflow用户

发布于 2020-03-09 18:00:42

如果您想设置一个扫描过滤器来查找信标UUID,这样的代码将无法工作:

代码语言:javascript
复制
filters.add(new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0")).build());

上述代码将设置一个筛选器,以查找一个BLE设备,该设备用于广告GATT Service UUID,匹配E2C56DB5-DFFB-48D2-B060-D0F5A71096E0。GATT Service UUID与蓝牙信标接近UUID完全无关,尽管这两个UUID表面上看起来可能是相同的。换句话说,您正在告诉过滤器寻找一个可连接的蓝牙设备,该设备广告的自定义服务恰好与您的信标标识符相同。这将永远找不到任何东西,因为这样的设备几乎是不存在的。

相反,你想要做的事情更复杂--你想要设置一个扫描过滤器来寻找蓝牙制造商的广告( iBeacon和AltBeacon广告就是这样),它有一个特定的制造商代码,并以一定的字节序列开始。

获取过滤器的确切字节序列是很困难的,因为它取决于制造商ID、信标布局(iBeacon或AltBeacon)。这是Android灯塔图书馆为您处理的众多复杂问题之一。

如果你真的需要自己去做,你会为iBeacon做类似的事情(警告:未经测试的代码):

代码语言:javascript
复制
byte[] manufacturerData = new byte[] {
            // iBeacon identifier prefix
            0x02, 0x15, 
            // Your Proximity UUID
            0xE2, 0xC5, 0x6D, 0xB5, 0xDF, 0xFB, 0x48, 0xD2, 0xB0, 0x60, 0xD0, 0xF5, 0xA7, 0x10, 0x96, 0xE0
            };
int manufacturerId = 0x004c; // Apple
ScanFilter filter =
filters.add(new ScanFilter.Buider().setManufacturerData(manufacturerId, manufacturerData).build());
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60590570

复制
相关文章

相似问题

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