在Android 4.3蓝牙BLE上重置蓝牙芯片后调用BluetoothGatt.connect()时引发了DeadObjectException

时间:2014-02-18 10:01:16

标签: android exception bluetooth bluetooth-lowenergy android-bluetooth

我开发的应用程序利用了Android 4.3中新的蓝牙BLE API。

我使用了适用于Android 4.2的三星BLE堆栈,即使稳定性更好,它也能正常工作。

现在有4.3,对于每个客户端连接,我们有一个BluetoothGatt类的实例。

也就是说,我通过调用

连接到BLE设备
BluetoothGatt gatt = device.connectGatt(this, true, callbacks);

这些BluetoothGatt对象是用于实际与设备交互的对象。

由于我想连接多台设备并与之互动,因此我将BluetoothGatt个实例缓存在HashMap定义为我服务的私有财产中:

private HashMap<String, BluetoothGatt> devicesGatts 
    = new HashMap<String, BluetoothGatt>();

密钥是设备地址。

然后,只要我想连接到某个设备,我就会将BluetoothGatt个实例从此HashMap中拉出来:

public BluetoothGatt connectGatt(final BluetoothDevice device){
    if(device == null){
        return null;
    }
    String adr = device.getAddress();
    BluetoothGatt gatt = devicesGatts.get(adr);
    if(gatt == null){
        gatt = device.connectGatt(this, true, mGattCallbacks);
    } else {
        BluetoothDevice gattDevice = gatt.getDevice();
        if(gattDevice != null && adr.equals(gattDevice.getAddress())){
                gatt.connect(); // PROBLEM APPEARS HERE
        } else {
            gatt = device.connectGatt(this, true, mGattCallbacks);
        }
    }
    devicesGatts.put(adr, gatt);
    return gatt;
}

问题在于,有时,如果设备尝试通过调用BluetoothGatt通过其缓存的gatt.connect()实例重新连接,则会收到一个名为DeadObjectException的错误(非致命)。

当我暂停应用程序并重新启动蓝牙芯片,然后恢复应用程序时,就会发生这种情况。

在发生这种情况之后我不能使用缓存实例并不奇怪,但我想知道如何在它发生之前捕获该异常或检测它。 / p>

这是堆栈跟踪:

02-18 10:43:51.884: E/BluetoothGatt(23312): android.os.DeadObjectException
02-18 10:43:51.884: E/BluetoothGatt(23312):     at android.os.BinderProxy.transact(Native Method)
02-18 10:43:51.884: E/BluetoothGatt(23312):     at android.bluetooth.IBluetoothGatt$Stub$Proxy.clientConnect(IBluetoothGatt.java:841)
02-18 10:43:51.884: E/BluetoothGatt(23312):     at android.bluetooth.BluetoothGatt.connect(BluetoothGatt.java:759)
02-18 10:43:51.884: E/BluetoothGatt(23312):     at MYSERVICE.connectGatt(...)

异常是由本机方法引发的,但蓝牙堆栈类不会引发异常。

我怎么能抓住它?

1 个答案:

答案 0 :(得分:1)

我找到了解决方法。

我只是在蓝牙芯片关闭时重置HashMap。

IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
this.registerReceiver(bluetoothStatusChangeReceiver, filter);

private final BroadcastReceiver bluetoothStatusChangeReceiver
= new BroadcastReceiver() {

    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if(action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)){
            if(intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) 
                    == BluetoothAdapter.STATE_OFF){
                devicesGatts.clear();
                resetBluetooth();
            } else if(intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) 
                    == BluetoothAdapter.STATE_ON){
                initBluetooth();
            }
        }
    }
}

initBluetooth和resetBluetooth函数允许我重置BluetoothGattServerBluetoothManager实例。