close()和disconnect()之间的区别是什么?

55

Android 蓝牙低功耗 API 实现了 1 种连接设备的方法 connectGatt(),但关闭连接有两种方法: disconnect()close()

文档说明如下:

  • disconnect(): 断开已建立的连接,或取消目前正在进行中的连接尝试。

  • close(): 应用程序应在完成使用 GATT 客户端后尽早调用此方法。

BluetoothGatt.java 的源代码显示,close() 取消应用程序的注册,而 disconnect() 断开客户端。然而,它并没有说明这实际上意味着什么。我的意思是,如果只有一种连接客户端的方式,为什么有两种关闭/断开连接的方式?


我猜 Close 意味着您将不再使用 Gatt 对象。 - Konstantin Konopko
2个回答

95

使用disconnect(),可以在之后调用connect()并继续该循环。

一旦调用close(),你就完成了。如果想再次连接,必须再次在BluetoothDevice上调用connectGatt(); close()将释放BluetoothGatt持有的任何资源。


4
非常有帮助 - 我一直在调用 disconnect() 并且一直耗尽了蓝牙接口,使得无法建立新的连接。调用 close() 可以避免这个问题。 - dgel
10
每当我使用disconnect()close()方法时,回调函数onConnectionStateChange从未被调用,也没有指示STATE_DISCONNECTED状态。 - DaviF
2
close()不会调用onConnectionStateChange,但是disconnect()应该会。你确定在调用disconnect()时已经连接上了吗? - Douglas Jones
2
@AlexanderFarber,你可以调用close()而不调用disconnect(),但是根据我的经验,你将无法获得onConnectionStateChange回调。 - Douglas Jones
2
我也曾经遇到过不一致的行为。如果你调用gatt.close(),下次连接同一设备时,你需要重新进行服务发现。绑定的BTLE设备不应该这样做。绑定的对等方知道你是谁(无论是配对还是是否启用了特征),并且可以(按规范)立即发送任何数据。它会假设你知道它的服务。如果你已经关闭了gatt,则不会知道它的服务,并可能丢失那些数据。我不知道Android在底层做了什么,但是在使用嵌入式低级堆栈时,这绝对是这种情况。 - Brian Reinhold
显示剩余6条评论

15

这里有一些值得思考的内容:

只要您没有关闭Gatt,就可以尝试连接或发现它。因此,当我尝试为一台机器发现服务时,我通常会运行一个线程或可运行项来发出连接该机器的请求,持续一定时间。

首次尝试与机器建立连接将返回一个BluetoothGatt对象,稍后您可以使用该对象尝试发现BluetoothDevice对象的服务。建立连接似乎相当容易,但发现机器服务则更加困难。

mBluetoothGatt = machine.getDevice().connectGatt(this, false, mGattCallback);

所以在我的线程/可运行程序中,我将检查BluetoothGatt是否为null。如果是,我将再次调用上面的代码行,否则我将尝试发现BluetoothGatt服务。

mBluetoothGatt.discoverServices();

哦,而且在尝试连接或发现服务之前,我始终确保调用 BluetoothAdapter.cancelDiscovery()。

mBluetoothAdapter.cancelDiscovery();

这里是我在runnable中使用的连接方法:

public void connectToMachineService(BLEMachine machine) {
    Log.i(SERVICE_NAME, "ATTEMPTING TO CONNECT TO machine.getDevice().getName());

    mBluetoothAdapter.cancelDiscovery();

    if(mBluetoothGatt == null)
        mBluetoothGatt = machine.getDevice().connectGatt(this, false, mGattCallback);
    else
        mBluetoothGatt.discoverServices();
}

最后,确保关闭您连接的任何BluetoothGatt对象。似乎在Android开始显示“无法连接到Gatt服务器”或其他类似信息之前,它可以处理五个BluetoothGatt对象。

对于我创建的每个BluetoothGatt,我都会调用close()方法,然后广播一个更新,说明连接已关闭。很多时候,当BluetootGatt断开连接时,它似乎不会响应状态更改。我的关闭BluetoothGatt的方法大致如下。我将该方法开放给Activity调用服务并断开连接,如果机器变得不响应且未调用断开状态。

public void disconnectGatt(BluetoothGatt gatt) {
    if(gatt != null) {
        gatt.close();
        gatt = null;
    }

    broadcastUpdate(ACTION_STATE_CLOSED);
}

6
你称呼 disconnectGatt 方法,但实际上调用的是 close() 而不是 disconnect(),这有点令人困惑。 - Mr. Blond

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接