信标+蓝牙通信(GATT配置文件)无法正常工作[BLE]

时间:2017-02-07 08:32:40

标签: android bluetooth-lowenergy altbeacon gatt

问题

我发射的外围设备正在发出具有特定ID的信标。我的智能手机(具有核心作用)正在搜索外围设备的信标。当它找到正确的信标时,它通过GATT配置文件开始蓝牙通信。 第一次连接设备时,数据会正确地从一个发送到另一个,但第二次(我每隔20秒尝试连接两个设备的计时器),连接失败我没有&#39 ;我知道为什么......我要杀死应用程序进程并重新打开以使其再次运行。

我做了什么

对于信标,我使用altbeacon,因此中央设备中信标检测的代码是:

@Override
public void onBeaconServiceConnect() {
    beaconManager.setRangeNotifier(new RangeNotifier() {
        @Override
        public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
            Log.i(TAG, "Beacon detected!");
            if (beacons.size() > 0 && Utils.getUserData(getApplicationContext(), "id").compareTo("-1") != 0) {
                if(region.getId1().compareTo(Identifier.parse(identifier))==0) {
                    Beacon beacon = beacons.iterator().next();
                    Log.i(TAG, "The first beacon I see is about " + beacon.getDistance() + " meters away. "
                            + region.getId1());
                    String mac = beacon.getBluetoothAddress();
                    Log.i("MAC", "MAC: "+mac);
                    CustomBluetoothManager customBluetoothManager = CustomBluetoothManager.getInstance(getApplicationContext());
                    if(!customBluetoothManager.isScanning()) {
                        customBluetoothManager.scanLeDevice(true, mac);
                    }
                }
            }
        }
    });

    try {
        beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", Identifier.parse(identifier),
                null, null));
    } catch (RemoteException e) {    }
}

当找到信标时,则调用scanLeDevice:

public void scanLeDevice(final boolean enable, String mac) {
    target_mac = mac;
    mHandler = new Handler();

    if (enable) {
        // Stops scanning after a pre-defined scan period.
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mScanning = false;
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
            }
        }, SCAN_PERIOD);

        mScanning = true;
        mBluetoothAdapter.startLeScan(mLeScanCallback);
    } else {
        mScanning = false;
        mBluetoothAdapter.stopLeScan(mLeScanCallback);
    }
}

这里是mLeScanCallback代码:

 private BluetoothAdapter.LeScanCallback mLeScanCallback =
        new BluetoothAdapter.LeScanCallback() {
            @Override
            public void onLeScan(final BluetoothDevice device, int rssi,
                                 byte[] scanRecord) {
                long epoch = System.currentTimeMillis() / 1000;
                SharedPreferences prefs = context.getSharedPreferences(
                        "epoch", Context.MODE_PRIVATE);
                long epochStored = prefs.getLong("epoch", 0);

                if (device.getAddress().compareTo(MAC) == 0 && after20Seconds) {
                    prefs.edit().putLong("epoch", epoch).apply();
                    Log.d("epoch", Long.toString(epoch));
                    mDeviceAddress = device.getAddress();
                    final Intent gattServiceIntent = new Intent(context, BluetoothLeService.class);
                    context.bindService(gattServiceIntent, mServiceConnection, context.BIND_AUTO_CREATE);
                }
            }
        };

我不得不对MAC地址进行硬编码,因为信标中包含的信标的MAC地址与实际设备MAC不同(来自BLE定义的那个,但我不知道)确切地知道它是如何工作的。)

最后,当数据发送时,我关闭并断开蓝牙通道,我也尝试解除绑定服务,但没有任何作用:

@Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        super.onCharacteristicWrite(gatt, characteristic, status);
        disconnect();
        close();
        unbindService(mServiceConnection);
    }

因此,使用此代码,第一次连接设备时数据会正确发送,但在20秒后,在第二次尝试时,永远不会建立通信。

问题

  1. 知道问题可能是什么?
  2. BLE如何运作?在信标包中,出于安全原因,MAC是假的。但是,如果我从beacons扫描应用程序获取它并将其硬编码到应用程序中,那么通信工作......我认为它不应该有效。
  3. 如何从信标包中获取正确的设备MAC?
  4. 您是否知道任何使用蓝牙通信信标的示例?
  5. 如果我停止扫描&#34; mBluetoothAdapter.stopLeScan(mLeScanCallback)&#34;方法,似乎扫描并没有真正停止......这是正常的吗?日志连续显示&#34; BluetoothLeScanner:startRegisteration:mLeScanClients = {org.altbeacon.beacon.service.scanner.CycledLeScannerForLollipop $ 4 @ 5445b45 = android.bluetooth.le.BluetoothLeScanner ......&#34; < / LI>

1 个答案:

答案 0 :(得分:1)

您无法使用Android BLE API读取MAC地址。如你所知,操作系统将伪造的MAC映射到真实的MAC上进行欺骗。所以这条线不可靠:

device.getAddress().compareTo(MAC) == 0

这可能是导致连接失败第二个齿的原因。它首次发布的事实令人惊讶,可能仅仅是由于Android的MAC欺骗旋转算法的确定性实现。第二次连接不起作用的事实

您可能需要找到一种不同的方法来找到要连接的设备,可能是通过信标标识符。

很难找到用于连接信标的良好示例代码,因为这不是典型的用例。通常,它们被视为设计时仅传输设备。这就是Android Beacon Library不提供连接BLE服务的工具的原因 - 所有信标制造商都没有标准实现。也就是说,您的定制方法是合理的。

了解Android Beacon Library会执行自己的蓝牙扫描来检测信标。这就是为什么即使您停止扫描,仍然会在日志中看到扫描结果。这来自图书馆。

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