SMG*_*ost 5 android android-bluetooth google-pixel
我遇到一个问题,我可以连接到蓝牙设备一次,但断开连接后,在扫描蓝牙设备时我不再看到该设备。如果我完全关闭应用程序,设备仍然无法被发现,但如果我关闭手机,设备将再次被发现。
我还注意到这个问题发生在 Pixel、华为和 xiomi 设备上,但似乎适用于运行 Android 12 的三星。
我的假设是,Android 12 中有一些奇怪的功能,可以以某种方式保持连接与应用程序分开。在我的应用程序中,我调用此代码来断开连接:
gatt.close()
Run Code Online (Sandbox Code Playgroud)
还有其他方法可以确保设备完全断开连接吗?
编辑: 打电话
bluetoothManager.getConnectedDevices(BluetoothProfile.GATT)
Run Code Online (Sandbox Code Playgroud)
断开连接并关闭后仍然返回我连接的设备。
EDIT2: 我可以使用以下代码重现此问题:
private var gatt: BluetoothGatt? = null
@SuppressLint("MissingPermission")
fun onDeviceClick(macAddress: String) {
logger.i(TAG, "onDeviceClick(macAddress=$macAddress)")
val bluetoothManager: BluetoothManager =
context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
if (gatt != null) {
logger.i(TAG, "Disconnecting")
gatt?.close()
gatt = null
printConnectedDevices(bluetoothManager)
return
}
printConnectedDevices(bluetoothManager)
val btDevice = bluetoothManager.adapter.getRemoteDevice(macAddress)
logger.d(TAG, "Device to connect: $btDevice")
gatt = btDevice.connectGatt(context, false, object : BluetoothGattCallback() {
override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
super.onConnectionStateChange(gatt, status, newState)
logger.d(TAG, "Connection state changed to status: $status, sate: $newState")
when (newState) {
BluetoothProfile.STATE_CONNECTED -> {
logger.d(TAG, "Connected")
printConnectedDevices(bluetoothManager)
}
BluetoothProfile.STATE_DISCONNECTED -> {
logger.d(TAG, "Disconnected")
printConnectedDevices(bluetoothManager)
}
}
}
})
}
@SuppressLint("MissingPermission")
private fun printConnectedDevices(bluetoothManager: BluetoothManager) {
val btDevices = bluetoothManager.getConnectedDevices(BluetoothProfile.GATT)
logger.d(TAG, "Currently connected devices: $btDevices")
}
Run Code Online (Sandbox Code Playgroud)
只需调用一次 onDeviceClick 即可连接到设备,再次单击即可断开连接。断开连接后,我可以在日志中看到,对于 Pixel 手机,我的蓝牙适配器仍显示为已连接:
I/SelectDeviceViewModel: onDeviceClick(macAddress=00:1E:42:35:F0:4D)
D/SelectDeviceViewModel: Currently connected devices: []
D/SelectDeviceViewModel: Device to connect: 00:1E:42:35:F0:4D
D/BluetoothGatt: connect() - device: 00:1E:42:35:F0:4D, auto: false
D/BluetoothGatt: registerApp()
D/BluetoothGatt: registerApp() - UUID=ae98a387-cfca-43db-82f0-45fd141979ee
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=12
D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=12 device=00:1E:42:35:F0:4D
D/SelectDeviceViewModel: Connection state changed to status: 0, sate: 2
D/SelectDeviceViewModel: Connected
D/SelectDeviceViewModel: Currently connected devices: [00:1E:42:35:F0:4D]
D/BluetoothGatt: onConnectionUpdated() - Device=00:1E:42:35:F0:4D interval=6 latency=0 timeout=500 status=0
D/BluetoothGatt: onConnectionUpdated() - Device=00:1E:42:35:F0:4D interval=36 latency=0 timeout=500 status=0
D/BluetoothGatt: onConnectionUpdated() - Device=00:1E:42:35:F0:4D interval=9 latency=0 timeout=600 status=0
I/SelectDeviceViewModel: onDeviceClick(macAddress=00:1E:42:35:F0:4D)
I/SelectDeviceViewModel: Disconnecting
D/BluetoothGatt: close()
D/BluetoothGatt: unregisterApp() - mClientIf=12
D/SelectDeviceViewModel: Currently connected devices: [00:1E:42:35:F0:4D]
Run Code Online (Sandbox Code Playgroud)
EDIT3登录三星,一切正常:
I/SelectDeviceViewModel: onDeviceClick(macAddress=00:1E:42:35:F0:4D)
D/SelectDeviceViewModel: Currently connected devices: []
D/SelectDeviceViewModel: Device to connect: 00:1E:42:35:F0:4D
I/BluetoothAdapter: STATE_ON
D/BluetoothGatt: connect() - device: 00:1E:42:35:F0:4D, auto: false
I/BluetoothAdapter: isSecureModeEnabled
D/BluetoothGatt: registerApp()
D/BluetoothGatt: registerApp() - UUID=931b9526-ffae-402a-a4b4-3f01edc76e46
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=17
D/BluetoothGatt: onTimeSync() - eventCount=0 offset=346
D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=17 device=00:1E:42:35:F0:4D
D/SelectDeviceViewModel: Connection state changed to status: 0, sate: 2
D/SelectDeviceViewModel: Connected
D/SelectDeviceViewModel: Currently connected devices: [00:1E:42:35:F0:4D]
D/BluetoothGatt: onConnectionUpdated() - Device=00:1E:42:35:F0:4D interval=6 latency=0 timeout=500 status=0
D/BluetoothGatt: onConnectionUpdated() - Device=00:1E:42:35:F0:4D interval=38 latency=0 timeout=500 status=0
D/BluetoothGatt: onConnectionUpdated() - Device=00:1E:42:35:F0:4D interval=9 latency=0 timeout=600 status=0
I/SelectDeviceViewModel: onDeviceClick(macAddress=00:1E:42:35:F0:4D)
I/SelectDeviceViewModel: Disconnecting
D/BluetoothGatt: close()
D/BluetoothGatt: unregisterApp() - mClientIf=17
D/SelectDeviceViewModel: Currently connected devices: []
Run Code Online (Sandbox Code Playgroud)
EDIT4我尝试修改上面的代码以首先调用disconnect(),并且仅在蓝牙连接状态更改为断开连接时调用close(),但仍然存在相同的问题。
仅调用 gatt.close 是不够的。为了正确地断开与gatt服务器的连接;您需要首先调用BlueotoothGatt.disconnect,然后在onConnectionStateChange回调中您必须调用BluetoothGatt.close。
您活动中的某些地方
// Somewhere in your activity where you want to disconnect
// might be adequate in onPause callback
if(bleAdapter != null && bleAdapter.isConnected) {
bleAdapter.disconnect(); // In bleAdapter you're supposed to hold a reference to the gatt object.
}
Run Code Online (Sandbox Code Playgroud)
在您的 BLE 适配器实现中
private void disconnect() {;
if (bluetooth_adapter == null || bluetooth_gatt == null) {
Log.d("disconnect: bluetooth_adapter|bluetooth_gatt null");
return;
}
if (bluetooth_gatt != null) {
bluetooth_gatt.disconnect();
}
}
// And finally in your BluetoothGattCallback.onConnectionStateChange implementation you call the close method on your BluetoothGatt object reference
private final BluetoothGattCallback gatt_callback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.d(TAG, "onConnectionStateChange: status=" + status);
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.d(TAG, "onConnectionStateChange: CONNECTED");
connected = true;
}
else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.d(TAG, "onConnectionStateChange: DISCONNECTED");
connected = false;
if (bluetooth_gatt != null) {
Log.d(TAG,"Closing and destroying BluetoothGatt object");
bluetooth_gatt.close();
bluetooth_gatt = null;
}
}
}
// Other callbacks
};
Run Code Online (Sandbox Code Playgroud)
我将你的MRE kotlin代码转换为java,以下2种情况的代码是:
// This listener is defined in the onCreate callback
binding.fab.setOnClickListener(view -> {
final String target = "50:8C:B1:69:E5:63";
BluetoothManager bluetoothManager = getSystemService(BluetoothManager.class);
if(gatt != null) {
Log.d(TAG, "Disconnecting");
gatt.close();
gatt = null;
printConnectedDevices(bluetoothManager);
return;
}
printConnectedDevices(bluetoothManager);
BluetoothDevice bd = bluetoothManager.getAdapter().getRemoteDevice(target);
if(bd != null) {
gatt = bd.connectGatt(this, false, new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.d(TAG, "onConnectionStateChange: status "+status+", new state "+newState);
if(newState == BluetoothProfile.STATE_CONNECTED) {
Log.d(TAG, "onConnectionStateChange: Connected");
printConnectedDevices(bluetoothManager);
}
else if(newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.d(TAG, "onConnectionStateChange: Disconnected");
printConnectedDevices(bluetoothManager);
}
}
});
}
});
private void printConnectedDevices(BluetoothManager bluetoothManager) {
@SuppressLint("MissingPermission") List<BluetoothDevice> devices = bluetoothManager.getConnectedDevices(BluetoothProfile.GATT);
if(devices != null && !devices.isEmpty()) {
for(BluetoothDevice bd: devices) {
Log.d(TAG, "printConnectedDevices: "+bd.getAddress());
}
} else {
Log.d(TAG, "printConnectedDevices: no devices");
}
}
Run Code Online (Sandbox Code Playgroud)
以下是 2 台设备的结果...
D/MainActivity: printConnectedDevices: no devices
D/BluetoothGatt: connect() - device: 50:8C:B1:69:E5:63, auto: false
D/BluetoothGatt: registerApp()
D/BluetoothGatt: registerApp() - UUID=2c71d08a-1fb3-411c-8d85-26f49749c932
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=6
D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=6 device=50:8C:B1:69:E5:63
D/MainActivity: onConnectionStateChange: status 0, new state 2
D/MainActivity: onConnectionStateChange: Connected
D/MainActivity: printConnectedDevices: 50:8C:B1:69:E5:63
D/BluetoothGatt: onConnectionUpdated() - Device=50:8C:B1:69:E5:63 interval=6 latency=0 timeout=500 status=0
D/BluetoothGatt: onConnectionUpdated() - Device=50:8C:B1:69:E5:63 interval=30 latency=0 timeout=600 status=0
D/MainActivity: Disconnecting
D/BluetoothGatt: close()
D/BluetoothGatt: unregisterApp() - mClientIf=6
D/MainActivity: printConnectedDevices: no devices
Run Code Online (Sandbox Code Playgroud)
D/MainActivity: printConnectedDevices: no devices
D/BluetoothGatt: connect() - device: 50:8C:B1:69:E5:63, auto: false
D/BluetoothGatt: registerApp()
D/BluetoothGatt: registerApp() - UUID=558b17e5-6770-4f46-a4d8-4f8d0024d86c
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=5
D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=5 device=50:8C:B1:69:E5:63
D/MainActivity: onConnectionStateChange: status 0, new state 2
D/MainActivity: onConnectionStateChange: Connected
D/MainActivity: printConnectedDevices: 50:8C:B1:69:E5:63
D/BluetoothGatt: onConnectionUpdated() - Device=50:8C:B1:69:E5:63 interval=6 latency=0 timeout=500 status=0
D/BluetoothGatt: onConnectionUpdated() - Device=50:8C:B1:69:E5:63 interval=30 latency=0 timeout=600 status=0
D/MainActivity: Disconnecting
D/BluetoothGatt: close()
D/BluetoothGatt: unregisterApp() - mClientIf=5
D/MainActivity: printConnectedDevices: no devices
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1599 次 |
| 最近记录: |