Android 信标&x2B;蓝牙通信(GATT模式)是';t工作正常[BLE]

Android 信标&x2B;蓝牙通信(GATT模式)是';t工作正常[BLE],android,bluetooth-lowenergy,altbeacon,gatt,Android,Bluetooth Lowenergy,Altbeacon,Gatt,问题 我有一个外围设备,它发射带有特定ID的信标。我的智能手机(起核心作用)正在搜索外围设备的信标。当它找到正确的信标时,它通过GATT配置文件开始蓝牙通信。 第一次连接设备时,数据正确地从一个设备发送到另一个设备,但第二次(我有一个计时器尝试每20秒连接两个设备),连接失败,我不知道为什么。。。我必须终止应用程序进程,然后重新打开它,使其重新工作 我所做的 对于信标,我使用altbeacon,因此中央设备中的信标检测代码如下: @Override public void onBeaconSer

问题

我有一个外围设备,它发射带有特定ID的信标。我的智能手机(起核心作用)正在搜索外围设备的信标。当它找到正确的信标时,它通过GATT配置文件开始蓝牙通信。 第一次连接设备时,数据正确地从一个设备发送到另一个设备,但第二次(我有一个计时器尝试每20秒连接两个设备),连接失败,我不知道为什么。。。我必须终止应用程序进程,然后重新打开它,使其重新工作

我所做的

对于信标,我使用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) {    }
}
下面是回调代码:

 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秒后,在第二次尝试中,将永远无法建立通信

问题

  • 你知道问题出在哪里吗
  • BLE是如何工作的?在信标数据包中,出于安全原因,MAC是假的。但是,如果我从信标扫描应用程序中获取它,并将其硬编码到应用程序中,通信就会正常工作。。。我认为它不应该起作用
  • 如何从信标数据包中获取正确的设备MAC
  • 您知道使用蓝牙通信信标的任何示例吗
  • 如果我通过“mBluetoothAdapter.stopLeScan(mLeScanCallback)”方法停止扫描,似乎扫描并没有真正停止。。。这正常吗?日志持续显示“BluetoothLeScanner:StartRegistration:mLeScanClients={org.altbeacon.beacon.service.scanner.CycledLescannerForollipop$4@5445b45=android.bluetooth.le.BluetoothLeScanner……”

  • 您无法使用Android BLE API读取MAC地址。正如您所知,它会被操作系统映射到真实MAC的假MAC欺骗。因此,这一行不可靠:

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

    这可能是导致第二次连接失败的原因。它在第一次启动时工作的事实令人惊讶,可能只是由于Android的MAC欺骗旋转算法的确定性实现。第二次连接不工作的事实

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

    很难找到连接到信标的好的示例代码,因为这不是典型的用例。通常,它们在设计时被视为仅传输设备。这就是为什么不提供连接到BLE服务的工具的原因——没有跨所有信标制造商的标准实现。也就是说,您的自定义这种做法是合理的

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


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

    为什么需要altbeacon?据我所知……您的要求基于gatt中心和外围角色,它围绕设备的mac id。(同时我也在想为什么这是第二次的问题,记得面对类似的事情)感谢您的回复!我需要信标来知道用户何时靠近外围设备…通过这种方式,我们可以避免应用程序连续扫描用户周围的蓝牙设备。
    scanLeDevice
    其回调无论如何都会这样做,您只需计算接近度的rssi值——用于计算用户是否在设备附近我要感谢您的回复和您之前的帮助。在苹果版权/商标打击之前到之后,我一直使用RadiusNetworks android ibeacon库:).Altbeacon和eddystone的实现从那时起已经走过了很长的一段路。我想说,在这个特定问题中的实现将与和相关的类相关。
    @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicWrite(gatt, characteristic, status);
            disconnect();
            close();
            unbindService(mServiceConnection);
        }