android - Ble 扫描回调只被调用几次然后停止

标签 android bluetooth-lowenergy ibeacon indoor-positioning-system

我有2部Android 5.0.2的手机,都安装了最新的Radius Beacon的App:Locate Beacon,同时我开启了2个IBeacon sender,可以看到RSSI keep使用应用程序在两部手机中更改

但是当我尝试编写一些示例代码来模拟上述情况时,我发现 ble 扫描回调总是在调用 2 或 3 次后停止调用,我最初怀疑 'Locate Beacon' 可能使用不同的方式,所以我尝试了两种 API,一种用于旧的 4.4,另一种是 android 5 中引入的新方式,但两者的行为相同(但都在 android 5 上运行)。

4.4 版:

public class MainActivity extends Activity {
private BluetoothAdapter mBluetoothAdapter;
private static final String LOG_TAG = "BleCollector";
private TextView calledTimesTextView = null;
private int calledTimes = 0;
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
    @Override
    public void onLeScan(final BluetoothDevice device, int rssi,
            byte[] scanRecord) {
        calledTimes++;
        runOnUiThread(new Runnable() {
            @Override
            public void run() {

                calledTimesTextView.setText(Integer.toString(calledTimes));
            }
        });
        Log.e(LOG_TAG, "in onScanResult, " + " is coming...");
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    calledTimesTextView = (TextView) findViewById(R.id.CalledTimes);
    mBluetoothAdapter = ((BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE))
            .getAdapter();
    mBluetoothAdapter.startLeScan(mLeScanCallback);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}}

和 5.0.2:

public class MainActivity extends Activity {
private BluetoothAdapter mBluetoothAdapter = null;
private BluetoothLeScanner mLescanner;
private ScanCallback mLeScanCallback;
private static final String LOG_TAG = "BleFingerprintCollector";
private TextView calledTimesTextView = null;
private int calledTimes = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    calledTimesTextView = (TextView) findViewById(R.id.CalledTimes);
    this.mBluetoothAdapter = ((BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE))
            .getAdapter();
    this.mLescanner = this.mBluetoothAdapter.getBluetoothLeScanner();

    ScanSettings bleScanSettings = new ScanSettings.Builder().setScanMode(
            ScanSettings.SCAN_MODE_LOW_LATENCY).build();

    this.mLeScanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            calledTimes++;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {

                    calledTimesTextView.setText(Integer
                            .toString(calledTimes));
                }
            });
            Log.e(LOG_TAG, "in onScanResult, " + " is coming...");
        }

        @Override
        public void onBatchScanResults(List<ScanResult> results) {

        }

        @Override
        public void onScanFailed(int errorCode) {
        }
    };
    this.mLescanner.startScan(null, bleScanSettings, this.mLeScanCallback);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}}

它们非常简单,只是在 UI 中显示一个计数器,最后证明总是停在 2 或 3。

我之前在三星 note 2 和 android 4.4 设备上播放过这个 ble 广告接收,它运行完美,回调每秒被调用一次。 那么有人可以帮忙吗? 为什么 Radius 的 Locate Beacon 在这里效果很好

最佳答案

不同的 Android 设备在扫描可连接 BLE 广告时表现不同。在某些设备(例如 Nexus 4)上,扫描 API 每次扫描发射器时仅获得一个回调发送一个可连接 广告,而对于不可连接 广告,它们会得到每个广告的扫描回调。其他设备(例如 Nexus 5)为每个广告提供扫描回调,无论它是否可连接。

Locate app你提到使用开源 Android Beacon Library检测信标。它建立在您在问题中显示的相同扫描 API 之上,但它通过定义扫描周期(前台默认为 1.1 秒)并以此间隔停止和重新启动扫描来解决此问题。 停止并重新启动扫描会导致 Android 发送新的回调。

这里还有一些其他注意事项:

  • 为可连接设备获取多个扫描回调的问题适用于 4.x 和 5.x 扫描 API。

  • 目前尚不清楚在不同设备上为可连接广告传送扫描回调的差异是由于 Android 固件差异还是蓝牙硬件芯片组差异。

  • 似乎没有办法检测设备是否需要重新启动扫描以获得可连接广告的额外回调,因此如果您的目标是多种设备,您需要计划停止并重新开始扫描。

  • 使用 Android 的原始扫描 API 是了解 BLE 信标工作原理的好方法。但是使用 BLE 信标有很多复杂性(这只是一个例子),这就是为什么使用像 Android 信标库这样的 SDK 是一个不错的选择,可以避免你的麻烦。

完全披露:我是 Locate app 的作者在 Android Beacon Library 的首席开发人员中开源项目。

关于android - Ble 扫描回调只被调用几次然后停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29731176/

相关文章:

Swift:从有符号 2 的补码 Uint8 到十进制数

ios - ios 7.1 上的 ibeacon - 应用程序在一段时间后停止收听信标

php - 在 Android 中将 Retrofit 发布到 Rest 服务器

android - "android.permission.MOUNT_UNMOUNT_FILESYSTEMS"权限问题

c++ - 在 Windows 10 上为 BLE GATT 设备开发 HID 输入设备驱动程序

ios - 仅广告数据与连接 BLE 设备的优势

android - 让 Samsung Android 设备作为 iBeacon 做广告

ios - iBeacon:如何将自定义数据放入 advdata?

php - 我在 Android 中将 JSON 对象解析为 String 时出错

Android ListView 状态列表不显示默认项目背景