GATT回调无法注册

Wib*_*ble 49 android bluetooth-lowenergy

我正在尝试编写一个通过蓝牙低功耗发送消息的应用程序,然后由我的外设中的UART传递.我按照这里的步骤操作,应用程序扫描并成功找到设备.但是,使用BluetoothGatt = BluetoothDevice.connectGatt(上下文,自动连接,回调)方法的连接失败,logcat说"无法注册回调".

来自:

//device scan callback
private BluetoothAdapter.LeScanCallback btScanCallback = new BluetoothAdapter.LeScanCallback() 
{
    @Override
    public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord)
    {       
        some stuff
        currBtGatt = device.connectGatt(parentActivity, false, btGattCallback);
    }
};
Run Code Online (Sandbox Code Playgroud)

和Gatt回调:

//GATT callback
private BluetoothGattCallback btGattCallback = new BluetoothGattCallback()
{       
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState)
    {
        // if connected successfully
        if(newState == BluetoothProfile.STATE_CONNECTED)
        {
            //discover services
            updateStatus("Connected");
            gatt.discoverServices();
        }
        else if(newState == BluetoothProfile.STATE_DISCONNECTED)
        {
            updateStatus("Disconnected");
        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status)
    {
        if(status == BluetoothGatt.GATT_SUCCESS)
        {
            //pick out the (app side) transmit channel
            currBtService = gatt.getService(uartUuids[0]);
            currBtCharacteristic = currBtService.getCharacteristic(uartUuids[1]);
        }
        else 
        {
            updateStatus("Service discovery failed");
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

Logcat说:

11-19 10:40:39.363: D/BluetoothAdapter(11717): stopLeScan()
11-19 10:40:39.373: D/BluetoothGatt(11717): connect() - device: DC:6D:75:0C:0F:F9, auto: false
11-19 10:40:39.373: D/BluetoothGatt(11717): registerApp()
11-19 10:40:39.373: D/BluetoothGatt(11717): registerApp() - UUID=3ba20989-5026-4715-add3-a5e31684009a
11-19 10:40:39.373: I/BluetoothGatt(11717): Client registered, waiting for callback
11-19 10:40:49.373: E/BluetoothGatt(11717): Failed to register callback
11-19 10:40:49.533: D/BluetoothGatt(11717): onClientRegistered() - status=0 clientIf=5
11-19 10:40:49.533: E/BluetoothGatt(11717): Bad connection state: 0
11-19 10:40:49.593: D/BluetoothGatt(11717): onClientConnectionState() - status=0 clientIf=5 device=DC:6D:75:0C:0F:F9
11-19 10:40:49.593: W/BluetoothGatt(11717): Unhandled exception: java.lang.NullPointerException
Run Code Online (Sandbox Code Playgroud)

有趣的是,我的外围设备进入"连接"状态(我有指示LED),我可以通过演示应用程序或PC BLE加密狗从同一部手机连接到它.任何想法都赞赏.

[编辑] connectGatt方法返回null,我猜这是预期的.

[编辑]在检查API 18源代码时,似乎传递了"Failed to register callback"消息,因为方法registerApp()返回false,因为IBluetoothGatt"mService"的registerClient()方法抛出了一个远程异常,可能在线:

enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Run Code Online (Sandbox Code Playgroud)

因为从未见过下一行中的日志消息.所以它可能是权限的东西,除了应用程序具有蓝牙和bluetooth_admin权限.

Lo-*_*Tan 100

我终于想出了这个问题.我正在使用的设备是三星Galaxy S4和实际问题(感谢Wibble在你的答案中提供指导,但你的结论略有偏差)似乎是一个线程问题.

在Wibble的回答中,他说添加一个连接按钮解决了他的问题.我开始想知道为什么这很重要,而且我也可以在整个会话期间连接和断开连接,而无需使用后台工作线程的GUI按钮.一旦我强制关闭我的应用程序,重新启动它,并尝试连接,我开始收到错误"无法注册回调".什么都没有用 我几乎把头发拉过这一个:)

有关我确切问题的详细信息,请参阅三星论坛中的帖子.

解决方案: 要解决此问题,请确保在UIThread中运行任何BLE交互代码(设备#connectGatt,connect,disconnect等)代码(使用处理程序,本地服务或Activity#runOnUiThread).遵循这个经验法则,你将有望避免这个可怕的问题.

在我们的库深处,我只能访问应用程序上下文.您可以通过使用将发布到主线程的上下文创建处理程序new Handler(ctx.getMainLooper());

如果您遇到其他连接问题,请部署示例应用程序samples\android-18\legacy\BluetoothLeGatt并查看该应用程序是否有效.这是我实现BLE实际上与我的外围设备一起工作的基础,并且给了我希望,如果我在我们的库中挖得足够多,我最终会找到答案.

编辑: 当使用后台线程执行BLE操作时,我没有在Nexus 4,Nexus 5或Nexus 7 2013上看到这个"无法注册回调"问题.这可能只是Samsungs 4.3实施中的一个问题.

  • 大!感谢您为我解开这个谜!顺便说一句:您不需要上下文来在主线程中创建处理程序.而不是`new Handler(ctx.getMainLooper())`你也可以编写`new Handler(Looper.getMainLooper())` (7认同)
  • 这些都是如此恼人的错误......谷歌可以在文档中提到类似"必须从主线程调用"的内容 (3认同)
  • @ Lo-Tan:谢谢.我终于设法解决了这个问题.显然在Android 4.3中,LeScanCallback上的回调是在不同的线程上完成的,而在5.0中,它们似乎总是在主线程上完成(或至少是启动扫描的线程).当立即尝试从onLeScan回调连接到设备时,这会导致4.3和5.0中的不同行为.在4.3中,这会导致错误.在5.0它没有. (3认同)
  • 非常感谢!当我调用connectGatt时,我无法理解为什么我的应用程序在没有任何异常的情况下注册,但为什么没有调用GattCallback.在主线程上调用connectGatt修复它! (2认同)
  • @Tbadams乍一看,我在主线程上进行了以下调用:gatt#connect,device#connectGatt,gatt #close,gatt#discoverServices (2认同)