当前位置: 首页 > 知识库问答 >
问题:

Android 5.0 Lollipop上检测到的BLE start Scan设备减少

阎作人
2023-03-14

短版本:

在我对Android 5.0Lollipop的测试中,我注意到了Android.bluetooth.le。BluetoothLeScanner检测BLE设备的频率低于Android 4.4 KitKat。为什么会这样?还有其他选择吗?

长版本:

我正在开发一个Android应用程序,专门为Nexus 7平板电脑开发,该应用程序专注于检测蓝牙低能耗(BLE)设备。该应用程序主要关注信标的RSSI值,以确定信标与平板电脑的距离。这意味着我不需要连接BLE设备,因为当检测到设备时,RSSI值会传递给扫描回调。

在Android 4.4 KitKat中,当我调用BluetoothAdapter时。startLeScan(LeScanCallback),我的回调对于每个检测到的BLE设备只调用一次。(我看到一些讨论声称,这种行为可能因设备而异)然而,我对不断变化的RSSI值感兴趣,因此目前推荐的方法是以设定的间隔(在我的情况下为250ms)连续进行StartEScan和stopLeScan:

public class TheOldWay {

    private static final int SCAN_INTERVAL_MS = 250;

    private Handler scanHandler = new Handler();
    private boolean isScanning = false;

    public void beginScanning() {
        scanHandler.post(scanRunnable);
    }

    private Runnable scanRunnable = new Runnable() {
        @Override
        public void run() {
            BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();

            if (isScanning) {
                adapter.stopLeScan(leScanCallback);
            } else if (!adapter.startLeScan(leScanCallback)) {
                // an error occurred during startLeScan
            }

            isScanning = !isScanning;

            scanHandler.postDelayed(this, SCAN_INTERVAL_MS);
        }
    };

    private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
            // use the RSSI value
        }
    };

}

本质上,这给了我所需的结果,但此过程非常耗费资源,最终会导致蓝牙适配器无响应。

出于这些原因,我将Nexus 7升级到Android 5.0Lollipop,看看我的BLE问题是否会得到解决。在Lollipop蓝牙适配器。StartEScan(LeScanCallback)被弃用,取而代之的是一个新的API,该API允许对扫描过程进行更多控制。从我的第一次测试来看,当RSSI值更改时,startScan似乎不会连续调用我的回调(在我的Nexus 7上),因此我仍然需要使用startScan/stopScan实现:

@TargetApi(21)
public class TheNewWay {

    private static final int SCAN_INTERVAL_MS = 250;

    private Handler scanHandler = new Handler();
    private List<ScanFilter> scanFilters = new ArrayList<ScanFilter>();
    private ScanSettings scanSettings;
    private boolean isScanning = false;

    public void beginScanning() {
        ScanSettings.Builder scanSettingsBuilder = new ScanSettings.Builder();
        scanSettingsBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
        scanSettings = scanSettingsBuilder.build();

        scanHandler.post(scanRunnable);
    }

    private Runnable scanRunnable = new Runnable() {
        @Override
        public void run() {
            BluetoothLeScanner scanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();

            if (isScanning) {
                scanner.stopScan(scanCallback);
            } else {
                scanner.startScan(scanFilters, scanSettings, scanCallback);
            }

            isScanning = !isScanning;

            scanHandler.postDelayed(this, SCAN_INTERVAL_MS);
        }
    };

    private ScanCallback scanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);

            int rssi = result.getRssi();

            // do something with RSSI value
        }

        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);

            // a scan error occurred
        }
    };

}

如您所见,我使用ScanSettings类配置了扫描仪,该类允许您设置扫描模式。我使用扫描设置。SCAN\u MODE\u LOW\u LATENCY,它有以下文档:“使用最高占空比扫描。建议仅在应用程序在前台运行时使用此模式。”听起来与我想要的完全一样,但不幸的是,我只每隔15-30秒检测一次信标,KitKat版本在此扫描间隔上每隔1-2秒向我显示一次相同的信标。

你知道造成这种差异的原因是什么吗?我是不是错过了什么,也许是一些新的设置?有没有其他方法可以做到这一点?

提前多谢!

阿贝尔

PS:我想包括更多指向我使用过的资源的链接,但我还没有足够的代表点。

共有3个答案

贺跃
2023-03-14

在KitKat和Lollipop中,我的Nexus 4经历了非常相似的结果。

使用KitKat,蓝牙适配器最终也没有响应;起初我认为它可能与较短的扫描间隔(200毫秒)有关,但将这个数字增加到一秒钟也没有帮助,在这件事上,我发现,当无响应时以编程方式禁用和启用适配器时,有时会解决问题。不幸的是,我不能说它一直有效。

现在有了Lollipop,我对解决这个问题寄予厚望,我经历了与你描述的相同的行为。我还不得不使用startScan/stopScan实现,在检测时间方面得到了类似的结果。可悲的是,我还没有找到一个能更快取得结果的方法。

根据你的描述,我认为这可能是硬件问题,即使Nexus 7和Nexus 4来自不同的制造商(华硕和LG)。

我知道,除了回答你关于你遗漏了什么的问题之外,我在这里没有提供太多帮助;我不这么认为,我认为问题在于硬件或蓝牙API在不同设备上的表现仍然不正常。

欧阳俊捷
2023-03-14

我还没有50个评论的声誉,所以请容忍我,这个评论将以回答的形式出现。在您的代码中,这部分不应该:

if(isScanning){scanner.start扫描(...)

改为:

if (!isScanning) {
 scanner.startScan(...)

因为按照你的代码,你在开始扫描之前调用了Stop Scan()。如果Stop Scan()方法是幂等/安全的,它可能不会对结果产生直接影响。但是你知道,为了代码的可理解性,你应该编辑问题。对你的代码做同样的事情,有时拜占庭的事情在起作用;)

您是否尝试过扫描间隔毫秒的较大值?如果是,有多大?

爱炯
2023-03-14

我用Nexus 5运行新的Android 5.0扫描API得到了非常不同的结果。当使用SCAN\u MODE\u LOW\u延迟时,BLE信标以10Hz的频率每100ms检测一次BLE数据包。

您可以在此处阅读完整结果:

http://developer.radiusnetworks.com/2014/10/28/android-5.0-scanning.html

这些测试基于运行开源Android Beacon Library 2.0的实验性Android-l-API分支。

您的测试结果有什么不同并不明显,但有可能开始和停止扫描正在改变结果。

编辑:硬件可能是不同之处。请参阅Nexus 4:https://github.com/AltBeacon/android-beacon-library/issues/59#issuecomment-64281446上类似计时的报告

 类似资料:
  • 我有一个正在开发的网站,我计划在它旁边发布一个配套应用程序,因为它在手机上看起来不像在桌面上那么好。还有很多性能问题。我注意到一些网站通知你去一个不同的页面,如果你正在使用移动设备,我想这样做,除了有一个消息弹出。我确信我可以处理消息部分,但我需要的帮助是检测移动设备使用情况背后的方法学。我通过一个简单的谷歌搜索看到了这个网站: http://detectmobilebrowsers.com/ 但

  • 我正在一台新的Windows10笔记本电脑上设置一个Android开发环境。我在使用其他操作系统的其他机器上已经这样做过很多次了,但这是第一次使用Windows10。问题是,Android Studio无法检测我的设备(LG区域3)后,我通过USB连接它。请注意,我以前曾在Arch Linux桌面上使用此设备进行开发。 我已经下载了Android Studio并创建了几个AVD。我可以运行我的应用

  • 检测网站是否正在移动设备或台式机/笔记本电脑上打开。 使用正则表达式来测试 navigator.userAgent 属性以确定打开设备是移动设备还是台式机/笔记本电脑。 const detectDeviceType = () => /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.us

  • 我似乎无法让DevTools设备功能在我的三星Galaxy S4上运行,即使遵循了中概述的步骤https://developers.google.com/chrome-developer-tools/docs/remote-debugging 我的设备有Chrome v32和Chrome Beta v33,而我的电脑有Chrome v33和Chrome Canary v35。 已在我的设备上启用U

  • 问题内容: 我想知道是否有可能检测浏览器是否在iOS上运行,这与使用Modernizr进行功能检测的方式类似(尽管这显然是设备检测而非功能检测)。 通常,我宁愿使用功能检测,但我需要根据该问题确定设备是否为iOS,因为它们处理视频的方式YouTube API无法在iPad / iPhone/非Flash设备上使用 问题答案: 我不喜欢User Agent嗅探,但是这是你的处理方式: 另一种方法是依

  • 我有目标设备的蓝牙mac-id。然而,蓝牙处于隐藏/不可见模式。 这两款手机都是Android手机。(非根)。 我做了研究,我*知道*如果我知道mac id,我可以连接到一个设备(在大多数情况下),但是我只想扫描接近度而不连接,即如果目标设备在蓝牙范围内,我知道它的mac id,我*可以*只*知道它是否接近(或者松散地说,扫描它?)