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

时间:2015-04-19 14:28:12

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

我有2部Android 5.0.2手机,他们都安装了最新的Radius Beacon应用程序:定位信标,同时,我打开了2个IBeacon发送器,可以看到RSSI 保持使用应用程序在两部手机中更改

但是当我尝试编写一些示例代码来模拟上述情况时,我发现ble扫描回调总是在调用2或3次后停止调用,我最初怀疑'Locate Beacon'可能使用不同的方式,所以我尝试了2种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。

我之前在使用android 4.4设备的SamSung笔记2上播放了这个广告,它运行得很好,每秒都会调用回调。 那么有人可以帮忙吗? 为什么Radius'Locate Beacon在这里运作良好

2 个答案:

答案 0 :(得分:19)

扫描可连接的 BLE广告时,不同的Android设备的行为会有所不同。在某些设备(例如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 Beacon Library这样的SDK是一个很好的选择,可以防止你脱头发。

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

答案 1 :(得分:-1)

David - 您确定为每个不可连接的广告调用扫描回调。我有一台小米Redmi 3和另一款运行Android 6.0的Nexus 5手机。我有一个BLE传感器,每隔1分钟发送一次数据。这些出现在中央BLE设备上的电话应该接收并处理来自传感器的数据。我可以从空中下载(OTA)BLE捕获设备看到传感器每1分钟发送一次数据。然而,两部手机似乎以1分钟的间隔处理数据几分钟,但在此之后停止处理4-6分钟,然后开始处理ag 0 [main] make 1060 C:\msys64\usr\bin\make.exe: *** fatal error - error while loading shared libraries: /C/Users/Ryan/AppData/Roaming/NetBeans/8.2/bin/nativeexecution/Windows-x86_64/unbuffer.dll: cannot open shared object file: No such file or directory ain。 手机处理的时间间隔就像这样 1分钟,2分钟,3分钟,8分钟,9分钟,10分钟,11分钟 因此,在以1分钟的间隔处理3个数据包后,任何一部电话都将停止处理4-6分钟。

以下是执行处理的代码。

enter code here